Effective Unit Testing by Eliotte Rusty Harold

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
[Music] welcome I'm Eliot Harold this is effective unit testing welcome I hope everyone can hear okay it sounds like the mic is on I however cannot see okay there are these incredibly bright lights going right into my eyes so if you want to like me to see you you need to come up to the front we have plenty of space currently where do I come from what's my experience with testing I've done a number of things over the years right now I'm tech lead of Google's cloud tools for Eclipse currently has about 70% test coverage as measured by jacoco I honest I think that's a little low I'm working on bringing that up should be higher I'm also the developer of zom which is an independent library I did some years before I joined Google that runs about 99 percent test coverage I'm very proud of that I mean really you're down to just the you know the only things aren't covered or like catch blocks for runtime exceptions it can't actually happen but you have or checked exceptions can actually happen but you have to put them in there anyway just to make the compiler happy so that was written test first and that worked really well I'm also the current maintainer of the Jackson xpath library I actually got started on that library because like you didn't have such great test coverage I was using it I started submitting tests to it I often discovered when I started write any tests for the classes if there were bugs nobody had noticed which is often the case with untested code and because no good deed goes unpunished I'm now the maintainer of the project I've written a few books over the years done yet on testing but I've got a few years yet to do that I this is not going to be an introductory talk I'm not going to give you a lot of details about the syntax of j-unit or how you write your setup methods or your fixtures or anything like that what I want to talk about today is given that we're writing tests in whatever language Java c-sharp C++ Python doesn't really matter given that you're doing test room development given that your writing unit tests how do we do this more effectively how do we get the most bang for the buck how do we improve our development process through testing so why do we write our tests well I know why I write them number one because I want my code to work if it isn't tested isn't broken I actually found that out this morning I was looking at some code in cloud tools for eclipse and some one of our developers who proposed refactoring I said well do we have tests for that class oops looks like we forgot to test that class so I started writing some tests for that class and wouldn't you know it I found a bug we didn't know about and I've got a pull request out for that still needs a little work we also write tests because we want the code to keep working very many times when I make a change when I send out a pull request a test I wasn't even thinking of fails so that keeps me from committing that it keeps me from breaking the things that already work it's also important to write tests because I want to write code faster and with fewer regressions and more confidence you know sometimes you will say we don't have time to write tests we have to just you know that that's great we'll do that later my answer is I write code a lot faster and I get to production a lot sooner when I'm writing tests at the beginning it actually lets me move through and lets me see the mistakes immediately rather than seeing the mistakes down the line where they're much hard to fix it also lets me understand my code better in terms of what I'm doing it lets me think about the code he speeds up my development it sounds counterintuitive you're writing twice as much code but you can do it in half the time if half of the code is test and of course we write tests because we all make mistakes all the time you know none of us write perfect code I am constantly amazed how many times I write a test for a method that's too simple to fail and wouldn't you know it the test fails and there's something I didn't understand about that method is not nearly as simple as I really thought it was even basic methods like set foo string s this dot s equals foo those can fail now I'm going to begin with what I think of as the fundamental principle of unit testing in any language and any framework this is something though that is often sort of missed what is a unit test at its base it's this it's a piece of code that verifies that a known fixed input produces a known fixed output known and fixed are very important you want to avoid any cases where you're trying to parameterize your tests too much where you're you know Cindy and random data where you're sending in time if you have a method for instance to test the square root net function test the square root of nine you know what the square root of nine is it's three don't test the square root of 17 you don't know what that is don't test the square root of two maybe a few people know that two about four decimal places they may know beyond four decimal places but you're still worrying about roundoff error and things like that try and aim for you know the test says here's the input and you want to test where you know the output where nobody's going to argue with you about what the output is that's your first test now sometimes you don't genuinely know the correct output what you do depends on the nature of the problem in some problems where it's just some weird strain coming from somewhere but it's consistent and reproduced will always be the same thing right a characterization test right a test that says assert that assert equals or whatever in your framework of choice foo expected get value and then did the test will fail but you will get the actual value out on the other hand a much trickier problem is when you're writing code for a sort of fuzzy area one thing I deal with sometimes is clustering problems where you've got a bunch of points in space and you're trying to divide them up into clusters and it's not really always obvious what the right answer is there may be more than one Milland so you've got points in the middle that could go over to here the cluster a or cluster B how do you set them what's correct what isn't don't test that what you do instead is you write input data where it's really obvious where in the case of clusters for example you've got points they're very close together over here and points are very close together over there nothing in the middle and then you make sure that you get the clusters you expect if your input data doesn't give you clear and obvious output expected values find input data that does that's really the trick but on all circumstances known fixed input and known fixed output anything that's going to make the input or output contingent or dependent you want to avoid you should never friends and generate random input you know you may want to do fuzz testing but that's a very different thing and even if you do fuzz testing you need to carefully record what values you fuzz with or you can't actually fix problems you discover so always use fixed values for unit tests very controversial point I prefer not to use name constants that come from the model code you know if their model code has a named constant like web and folder location I won't use that static final field in my test I'll just use the string literal this gives me an ability to test if the name constant is actually incorrect or if it changes I don't want changes in my model code to automatically change the test I want to know when the tests change I want to know that the changes are deliberate other things that can be problematic because they make your input not known that would include any sort of network access this is a mistake I've made in the past myself and preferably not the file system you can probably get away with the file system if you need to but it's a little flakier than in memory access and then the final thing I'll note is if you depend on something in the environment the time of day the speed of light the gravitational constant of the universe I don't care the geographical location where the test is running that most often sneaks into our tests in an unexpected way through time zones or default character encodings don't let that control the output of your test if necessary inject these values inject a clock into your test inject the gravitational constant of the universe whatever it may be so that you're not dependent on these things that are outside of your control in the environment that's going to make your tests a lot more reproducible and a lot more debuggable so that's point one known fixed input known output number two write your test first how many people here generally write their tests first more often than not how many of you write the model code first and then the test okay about half and half if you're writing the model code first you're slowing yourself down and you're not getting as good a test coverage uhm test-first development is not just about testing although that's part of it it's about software development when you write your tests first you're thinking like a user of your library of your class of your code therefore you create better api's you tend to create the api's you need you have fewer public methods more private methods you separate your interface from your implementation more cleanly because you don't even write the implementation until you've written the interface it starts with the user rather than the used code it makes your Tecna one common criticism of unit testing high coverage is that well now if I need to change something in my model code I need to change all these tests to because they're going to break that's only going to happen if you've coupled your tests tightly to your implementation if you wrote your tests before you wrote the implementation they're only coupled to the API I yes if the API changes then your tests are going to change too that's just going to happen but it gives you much less brittle code much less brittle tests that don't need to changes often when you write the tests first also makes for better tests okay so here's a very simple test class in Java for a list who here sees the bug in this test anybody there's a bug in the test not in the model code model code a standard Java dot util dot list it works okay I'll tell you something else I wrote this yesterday this morning I was looking at this slide and going damn it I know I put a bug in here where's the bug if you write your test first you will find the bug in this code you will find the bug in this code almost immediately if you don't write your test first you won't I'll give you a hint this code is only buggy in j-unit for not in J unit three does that give you a clue yes the into deserting the size of the list before the addition no it is not is it it not asserting that the size of the list excited the value-added is not in the list it's not doing that and it should but nonetheless that is not the bug here yes we're going to find the list outside the method so I don't know how many times it was called no there's only one method in this class and we'll get to that but even if it was called many times and other methods that would not cause the test to fail yes in the back no test annotation thank you and I can't tell you how many times this has happened to me where I've have said I find a bug in production I think dammit I thought we had a test for that and then I look at the code and for one reason or another including this one oops the test wasn't actually running now how does test-first development fix that when you write your test first you run the test first before you write the model code you make sure the test fails before you write the code to make it pass and if you write a test and you run the test and the test passes before it's even failed before you've even written the model code something's wrong you know maybe you forgot an annotation maybe there's some other problem but this one has bitten me repeatedly least once every two months this happens to me somewhere in some code I'm dealing with so that's another reason to write your tests first okay that's number two write the test first number three principle for effective unit test a sure to put numbers on my slides unit tests and why unit tests in particulars opposed to fuzz tests or integration tests or manual tests or behavior tests and all that source up unit of course means one each test test exactly one thing what a test is depends a little bit on your framework if you're in J unit basically each test method each method within that test annotation or begins test that is a single test not a test class but the method in other frameworks it can be a little different in terms of what constitutes a single test but every test method is one test best practice that is often observed more in the breach one assert per test method each test method makes exactly one assertion and if you want to set up your list and then assert ten different things about that list the way j-unit at least expects you to do that is you have ten different test methods and they can share the same setup code to set up the list and that makes debugging a little easier it lets you see what's actually broken and see how much is broken when you run your tests as opposed to a sequence of ten tests we're soon as the first one fails you get no information from the following tests so one assert per test method share the setup in your setup method or your fixture whatever that looks like in your language of choice something that is often forgotten is you do not need to have an exact one-to-one ratio of test classes to model classes it is perfectly okay that if you have one model class arm you know dialogue frame buffer or something that that single model class can have ten different classes that test different components of it generally they will have set up the class differently so that I would say in a lot of code bases we see not enough test classes we see too much crammed into a single test class and that means that you've got a lot of setup code in each class it only applies to half your test in the class 1/4 of the tests in the class 1 test of the class even more important though unit test means independent the individual test methods can run in any order you know the input to one test does not depend on the output of the previous test and test runners in practice do reorder test there's no guarantee what order your tests are going to run in generally for running in Eclipse if you're running in Travis or Jenkins or something like that and you don't change your JVM and you don't change anything else it's probably going to be the same order from run to run but then you pass the code to your fellow developer on your team and they're going to run in a different order and then you upgrade your JVM from 1.7 0.49 to 1.71 or something like that and your tests start running in a different order so if there's any order dependence it can bite you but at unexpected times so watch out for that pests in some test runners run in parallel in multiple threads there's no guarantee that they are running in a single thread so tests should not interfere with each other that's really important keeping in mind that the test even beyond the model code may be running to multiple threads try not to depend on synchronization or semaphores or any sort of special data structure this can run into deadlock problems most importantly though don't share data between tests the way this usually happens if you have non constant static fields anytime you see a non constant non you know if you want to put a constant final static string or equivalent in your test fine but if it's some sort of mutable object like a list and it's static or it's just a static int that different tests are reading and writing to it's not final watch out that is almost guaranteed lis a bug that is one way to couple two tests together so that they depend on the order in which they run beyond this an even harder nut to crack sometimes is if the code itself the model code under test has some sort of shared global state you may not be able to fix that in your test but you need to watch out for it in our project and cloud tools for eclipse we're dealing with eclipse a lot of the time and it has for example exactly one workspace and a lot of our bigger tests have to set up a workspace and projects and if those projects or workspaces are shared between tests well and we're in a world of hurt because Eclipse shares a lot of global state just in the model code even before you get to the tests you can't necessarily avoid that but you do need to worry about it I think I said those next two points to least-known a facts of unit testing this will answer your question from earlier number one I said static state shared instance data perfectly fine is there a bug in this class yes right no that is the common misunderstanding j-unit every test method test and and test add two elements the test Runner creates a completely new object for each one so they have two different list fields the test object itself is not reused the test classes it doesn't reload the test class with a new class loader but if you run this this test will pass both of these test methods pass no matter what order they're running even if they're run in parallel and that's simply because one is run with one object and what one is one with another object so I often see people in j-unit least putting code in the setup method that doesn't really need to be there because they don't understand that separate test objects are used so this is a neat trick that makes your code a little simpler and then I said this before number two you can have many different test classes per model class and it's the I see a typo now oh well it is the fixture the setup method really the distinguishes whether you need a new test class or not if you're going to change your set if you've got five tests that setup the database in one way and five tests that set it up in a different way that's two different tests class database testing is a whole nother talk okay speed of tests how fast do you want your test to be your entire test suite for your product as fast as possible sometimes that's not fast enough I mean we're having that experience with cloud tools for Eclipse where it takes on the order of 10 to 20 minutes to run the entire test suite I would say that's too slow we'll talk about what you can do about that but any given test any given single test or test class a second or less so you can run it very quickly in your IDE when you're developing get a very fast feedback cycle going of tests see the failure you know fix the bug run the test again oops that still fails you didn't fix the bug fix it again until it passes so the individual tests ought to run in a second or less ten seconds maybe if you have to a complete test suite probably a minute or less if it's going to take longer than that start separating your tests out into multiple sweeps start by running the faster tests first so if you have early failures or if you just on something that breaks everything you'll find out immediately you don't want the incredibly long running database integration test that takes 15 minutes just to set up the database to start before you've got your test for the set foo method if they're both broken might as well find the bug sooner rather than later and the faster your tests run the more frequently developers will run them and the easier it is I will show you an example this is actually this is something I fixed this week ok did not actually swap to the tab this is a pull request and all this pull requests did is you notice I took that integration test in pink there and I moved it down to the end of the list and the reason I did that is the integration test takes approximately forever to run and I'd rather the other tests run first plus the integration test is flakier and it fails for no good reason more often so sometimes if you've got particularly slow running tests adjust your order or break them up so that you don't always have to run them okay let's see presentation mode person to me I think will get back up to full screen okay general principle for testing passing tests produce no output or maybe just a green bar or single string test pass that's all you want if everything's good they should be quiet failing tests can produce more output now they can produce log messages they can produce you know debugging information stack traces etc that will help you debug the problem but you don't want that sort of detritus to come out of your passing test because it gets in your way of understanding what actually happened this is something Navin and some other test runners get really really wrong because they just generate humongous amounts of output even when everything is okay when's the last time you wanted to look at the log messages from your passing tests when everything was fine and dandy it's irrelevant we don't need it there's no reason to even generate it to the screen Eclipse is pretty good about this it doesn't show you a lot of details if things are passing it shows you more if things are failing if you've got loggers you may want to silence them in your tests that's your logging level to no logs at all but yeah it avoid things like system dot out print long system but they are different linings we're about put like I'd even redirect that unless you're specifically testing it failing tests those were interested in when's the last time you wanted to see the logs and stack traces and every other piece of information you could find from a test that failed for me that was this morning so clear unambiguous error messages you could help this by giving good assertion messages in your tests maybe not to every assert method but if something fails and you're not understanding it make the assert method more descriptive another technique that's really important rotate your test data one problem I often see is every ant in a suite of thousands of tests that the expected value is set to three and then when you see oops this was supposed to be three but it's really 17 it's not as immediately obvious where the problem arose furthermore sometimes you have problems that arise with like three and not with seventeen or vice versa in deep parts of the code so just pick new values for each test to the extent that it makes sense in the sense that's possible if you've got ants choose different ants if you've got times that you're testing don't set all your times to midnight on January 1st 1982 you know move the months around move the times of day around this will both help you to identify the errors in the test and find new bugs who might not have found with a more restricted set of test values okay flakiness yeah this is the this has been my bet and waar lately we've had some flakiness issues in cloud tools for eclipse flakiness is when a test sometimes passes and sometimes fails you run the test once green you check it in and then the next time you run the test suddenly it's red and maybe it's not red because of the new change you made maybe it's red just because sometimes it passes and sometimes it fails this is really dangerous and you need to watch out for try not to let it happen to you what can be flaky anything that's time dependent for example now that can be an explicit time dependence I have seen you know tests that failed across the new year boundary or tests that failed across the daylight savings time boundary I have seen tests that failed because of leap seconds but it can also mean that its timing dependent in particularly there's some sort of GUI test that's bringing up your application clicking buttons moving dialogues around if things run just a little bit faster maybe the dialogue isn't up when you're trying to click a button in it so sometimes it passes sometimes fail selenium tests same exact probably when you're using selenium or webdriver yeah I mean so generally GUI tests by their nature tend to be a little flaky err and we need to watch out for that and sometimes we play games like what we run it actually three times inva passes any of the three times we call it a pass but better yet if you can avoid it never if you can avoid it failing in the first place network availability is another source of flakiness if your tests are talking to the network then I have some tests in zom that went out and loaded external schemas from very so-called authoritative sources like the schema perhaps for the for Java server pages from Oracle except when I wrote it it was an Oracle it was Sun and eventually Oracle bought Sun and Oracle changed all the URLs everything so anything point to Sun I'm no longer worked I mean for a while it redirected men didn't even do that and suddenly my tests broke code didn't change code hadn't changed for months but my tests broke because I was depending on external network resources where she had external network resources I did not control so that's something to watch out for explicit randomness this is a really bad idea if you if you see in a unit test mass dot random or feel the rand function and see or anything like that watch out big warning flags should go off sirens Klaxons alarms and then the really nasty one multi-threading if you've got anything in your tests they're happening because of race conditions if it depends on things happen this is like anything involving multi-threading it can really be problematic we've had some of these issues and cloud tools for eclipse where you're looking at the output of a test and it's failed because the circuit variable is null in a certain place and you're walking through the code and you are absolutely convinced there's just no way that variable could be null at that location it was already dereference two lines before just it could not have happened like that it's utterly impossible that's a big sign that you've got a threading issue and then worse yet if that does happen to you take your screenshots take your stack dumps immediately record everything because the next time you run it it's going to pass and then it's going to pass twenty more times or two thousand more times and then it's going to fail again and any time and those bugs can be very very hard to track down and usually if that's happening in your test it's happening in your code too it's a real bug your test is founded but your test is not going to find it each and every time so you need to figure it out you need to understand how you need to synchronize your model code so that that does not become an issue yeah those are the scary ones that's the ones they pay us the big bucks to UM systems skew this is a different kind of flakiness sometimes you'll have tests that just pass all the time when you run them but then you pass them to someone else on your team and they run them and they fail immediately and every time they run them they fail or maybe you send them off to Jenkins or your continuous integration server and they fail there what's going on maybe it's because I'm using a MacBook and my teammate is using Windows and Jenkins is running on Linux and there can be subtle differences even if you're writing in Java more so if you're writing in C or C++ between these different environments sometimes it's just threading issues sometimes as assumptions about the underlying operating system like is the path separator character a forward slash or a backward slash or colon who remembers what's operating system has a colon is the path separator character nobody okay one person yeah Mac OS pre Mac OSX not really relevant anymore but these things happen you can also have in not as much in Java though they are too can have some undefined behavior a floating-point roundoff can be an error in early versions of Java all VMs were guaranteed to give you the same answers for all floating-point calculations however they round it off it would be the same that is no longer true it hasn't been so for years so I may take the square root of two and get a different answer than you do when you take the square root of two integer within C is along eight bytes sixteen bytes four bytes that varies here's a big one that applies in job as well if you depend on the default character set then my code that uses Greek letters may pass and your code that uses Greek letters may fail because we're using two different character sets for reading data that happens occasion it's one reason you probably shouldn't use the default character set ever for anything you should always specify your character set and the character set you specify should always be utf-8 but if your model code doesn't do that you may get some flakiness as a result so this is all as a result of different you know kinds of operating systems generally these problems often indicate real bugs in the model that need to be fixed they just may not be apparent from a single run on a single developers workstation another anti-pattern to watch out for conditional logic in tests if you see ill for loops that iterate across every element of a collection or fine but if statements you know if X is greater than five we're going to assert this else we're going to assert something else that should be two separate test methods not one with different input values and different setup when you see something like this happening the risk becomes one or both of these are not actually executing you may not be testing what you're think you're testing you may not be getting the coverage you need it is very easy for these tests to not actually run when conditional logics sneak them try and make again remember that known fixed input known fixed output and no choices in the middle okay development practices with tests debugging this is easy if you find a bug in your code you know it's shipped comes in from user report or her tester reports a bug or you just happen to notice something stop think don't fix the bug file the issue write a failing test make sure that test is read make sure and once you think you understand the bug you can write a test addresses it you run the test and as often is not the test passes and it's green which means you didn't really understand the bug in the first place or the bug isn't where you thought it was or maybe the test doesn't really expose the bug so whatever those are true you iterate on the test until you finally get a failing test that says aha now I understand the bug and then you can start fixing it and then when the test goes green you know I can stop now I fixed this bug furthermore since the test becomes part of your test Suites you're running for the rest of time the bug should not reoccur it should not regress or if it does it will be caught immediately before it ever gets checked into the repo so for debugging always get that failing test first nothing drives me nuts more than when you know a bug gets assigned to a developer and then I get the code review and you know here's the fix of the bug and there's no test change anywhere to be seen because even if I go ahead and then ask them okay could you please write a test for this bug how do I know that the test really actually addresses the bug maybe it's just some sort of random change please write your bug tests first if you write nothing else first this is a slide I added this morning because I was working on some refactoring break the code before you refactor it in the specific case I was looking at in cloud tools for Eclipse we had about eight different methods to create a folder scattered throughout the codebase and we wanted to combine them into one so I looked at some of the places where it was covered where these different methods were used you know you like code reuse you don't like duplicate code and I said to myself you know I'm not sure this class is tested so I took one of those methods to create a child folder and I commented it out and then I ran all the tests and once you know that they were all green so what does that tell you that tells you we're missing a test somewhere and in particular we were missing a test on the code we wanted to refactor which is dangerous so I said okay let me first write a test for this before I go ahead and refactor it and make it pass and in the process of writing that test what would I tell you earlier happens whenever you write a test for untested code you find buzz wouldn't you know it I found a bug there was a bug in this untested class which I am now half way through the process of fixing so that's why I write our test if we're refactoring as well as just trying to liberally break the code and making sure the tests they'll fail if you're measuring code coverage which I recommend you can look at your graphs you can see is this line at least covered that doesn't guarantee that you've really got a test but it's a prerequisite it's a line is not touched by the tests then it will not be covered by the tests when you refactor or do anything else if you have to write additional tests before you perform any unsafe refactorings I mean there are some refactorings that can be done automatically by tools like renaming a variable but in this case where we were trying to combine eight different almost but not quite copy and paste create child folder methods with slightly different signatures that needs some more thought davell other development practices who here is using continuous integration that's good that you know ten years ago I wouldn't have had so many hands up if you're not start if you're on github if you've got a public repo you can set it up for free with Travis it's really easy or you can run your own Jenkins server there are other options out there but basically every time a test goes into the repo as a code goes into the repo all the tests are run automatically and report is sent out and if you break something you know the email goes out better yet the test to run before the code is merged into the repo ideally using a submit queue anybody here using a submit queue okay this is less common I don't see any hands going up which is less than I would have thought and it's submit queue you never directly commit to the repo you never directly merge your own code instead what you would do you send out the pull request the continuous build server merges it into a branch it runs all the tests and if and only if the tests pass it will commit to the repo and that guarantees mostly aside from flakiness that no breaking changes get into the repo because otherwise you're still the problem where people are supposed to run the tests and they're supposed to respect the output of the continuous build server but they merge anyway or by accident and things happen so if you're using a submit queue you're ahead of probably 99% of developers strong principle for your development teams never ever allow a check-in if a test is failing I don't care if it's a p0 production emergency if a test is failing that code does not get checked in if it does happen that you know a PR get a pull request or change list gets accidentally merged and breaks things or maybe it was flaky and broke things maybe it went in in the past as every other time rollback first ask questions later I am assuming everyone here is using good source code control like github or equivalent so don't don't try and send out a patch for it don't you know try and do an emergency fix rollback and then you can fix at your leisure because there's nothing worse than you send out a patch and the patch doesn't fix it and make things worse and it just cascades if your tests are red no merges into the repo until the repo is fixed that's a very strong principle okay final thoughts and I think a lot of time for a few questions most importantly right your tests first before you change a model code make all tests unambiguous and reproducible no flakiness no randomness no dependence on external environmental conditions use the continuous build server so you can keep your test screen and with that if there any questions comments thoughts whatever that you may wish to share and we're asking people to go to the microphone because this is being recorded so that your question can be heard by everybody and get on to the video yeah one asset thing about writing the test first because in my experience usually the because I actually have trouble writing the test first that I usually find it more useful that you have that type development cycle or iteration where it's like I write a code or right to test a little test and I write a little code then I write a little test and I find that's usually the the really the big payoff well the tight development cycle is really important what I would just suggest is try it you know that write a little code write a little test write a little code write a little test just throw out the first step write a little test write a little code right I'll pass write little code it can be easier or harder depending on the nature of the code the more library like your code is the easier it is if it is sort of that functional input-output style that's very easy to test if it's something more along the lines of this code is bringing up these dialogues and configuring things in a certain way that's a little harder but the real key is people will prompt people born into is they try and write too big a test chunk at first so if I'm trying to write a test for I don't know create configuration method or something my first test is going to be public void test grade configuration [Music] you know App Engine libraries dialogue dialogue equal new app engine libraries dialogue dialogue crate configuration and that's before I've even written to create configuration method then I get a red squiggly underline in Eclipse and I'll use a quick fix and you'll create the method for me and then I'll say okay I think this method is going to need you know a string argument so I'll put a string argument in my test again compile breaks I don't even need to run the test red squiggly underline quick fix and goes a string argument and then I'll try and think about okay what's the next most immediate thing they can do what if the string is null should it throw a null pointer exception or not right the test for that write the code then it becomes a question what else is that method doing and how easy is it to test now if it's a method it's supposed to take input and give me a fixed output we're good because that's very easy to write a test for it just assert that assert equals expected value test object get value and then I can write as much model code need to make that pass sometimes that's just returned a fixed value and then I have to write another test sometimes it's something more but it can be a little tricky if what you're really testing isn't exposed as a return value if it's more of a void method then you may be trying to call other methods on the object to inspect the objects internal stay you know if that happens and you need to write the model code to understand what's really going on okay but try and write as much of the test first as you can and then if I said I'll say something else if you're not writing your test first you really really have to measure your code coverage because if you write your test first and you're religious about it you get 90% plus code coverage trivially it's really really easy if you don't write your tests first and you don't measure your code coverage you're going to have a lot of untested codes you don't know about and that's dangerous that's where the bugs lie okay other questions okay if not Thanks yes one more microphone please I have the same problem it is the previous question I think in code and not in tests what do you think of tools like cucumber for getting a staff is with it a bunch of tests first working from what do I think about tools like cucumber honestly I don't think much of tools like cucumber I've never used it so I can't say a lot about it one thing I like about test-driven development is because it is focused on the code the tests we write our code and if you're you say you're thinking code not in tests do you think in terms of implementation or interface input because that yeah you think in terms of implementation so really try thinking about the interface because that's really what you're testing and then if you have a list interface we don't really care if it's an ArrayList or a vector or you know some other weird data structure if we get the interface right and we can actually swap them out so and it's okay to think about the implementation you just don't write the implementation till you've got the interface in place one thing I discovered always doing zom is I wrote a lot of you know signs for implementation I discovered a lot of that I didn't actually need because there was no interface corresponding to it if we write the implementation first and you tend to expose the implementation in your interface you have methods you don't need you also have brittle code that's hard to change and hard to refactor when you need to I think we may have time for one more if not thanks everyone for coming I hope you have a happy rest of DevOps [Music]
Info
Channel: Devoxx
Views: 68,251
Rating: undefined out of 5
Keywords: DVUS17
Id: fr1E9aVnBxw
Channel Id: undefined
Length: 48min 10sec (2890 seconds)
Published: Tue Apr 11 2017
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.