Unit Testing Best Practices

welcome to this presentation on unit testing best practices this video is in continuation to a few other videos that are already posted on YouTube such as unit testing rebooted and deaths spies and test mediators as well as test doubles so the first thing is you want to test the interface and not the implementation this is it seems very obvious or simple it’s similar to the idea of programming to interface and not implementation when we write tests we shouldn’t be looking at the implementation to decide what we need to test or what kinds of test methods we need to test so in the past what I’ve done is as an exercise for myself but later on for my teams I have given them an assembly that’s compiled so they can’t see the code and along with this assembly I give them a functional requirements with the class or classes that they might find this is an in in this assembly and they’re asked to write unit tests for this and once they’ve written the unit tests based on the functional requirements and they have a cop with the scenarios we then look at the code coverage if you will see if any scenarios were missed I think this is a great exercise to get people into the groove of writing to the functional requirements and scenarios rather than two classes and the implementation of these classes Delta coverage should be as close to zero as possible this is the Delta coverage across the different kinds of tests so if you remember from the very first part of on unit testing rebooted we talked about acceptance tests and then class tests or class integration tests the idea is not to write tests for every class and so the idea is to have tests such that they don’t overlap now if you are intentionally making the choice to write a test for a class that overlaps the class that’s one thing but the aim is not go about writing a bunch of tests that covered the class the same class across different kinds of tests such as the acceptance tests in class tests in class integration tests and compose a test and so on it’s a very easy mistake to make but that’s not what we want to be doing so let me show you in diagram form what that might look like so let’s say you have a class and you have your acceptance tests on this class that are covering this class to a certain extent and then you decide to write class integration tests for the same class now if you make that by choice you make that decision by choice then you know you’re duplicating the the coverages and this is the same scenario and so you’re repeating tests at a different level by level I mean acceptance test versus class tests or class integration test being different levels it’s similar to if you would look at this side as a set based operation then if that is the set of integration tests and this is your set of class integration tests then this intersection is what you have to be worried about in some cases these are choices you’re making intentionally so that’s fine let’s that’s a risk you’re willing to take so the the benefits outweigh the the cons if you will but if you’re doing this without knowing then that’s where the problem is that’s where the problem starts to arise because you could be writing a bunch of tests or huge numbers of tests that are essentially just duplicating the work that other tests are already doing and is that something you really want so you have to be very careful of that intersection as long as you’re doing that by by choice or by intent that’s of course your your choice in your in tendency you know that you’re doing that but in a lot of cases because you’re doing this unit testing style which is every class in isolation you don’t realize sometimes you’ve got a bunch of tests that are being repeated across different levels of testing it’s that that’s what I meant by Delta college next up is the unit test should run in isolation from other unit tests and this is very important you don’t want unit tests that depend on other unit tests either by way of the fact that maybe one tests need to run before the other or can’t run until certain other tests

around exeter that that causes a lot of flaky tests and so you want to make sure that they’re running in isolation in Kent Beck spoke when he talked about unit testing or isolation when he wasn’t used the word isolation he really meant that the unit tests themselves should be running in isolation this was because earlier on in his career he was burnt by decide this this fact that when he would get won’t come to the office in the morning and he see a stack of paper that indicated a bunch of tests had failed and on examining that over the over the days he’d realized that even though let’s say 100 tests that fail it wasn’t that hundred tests had failed it was one test that caused the other test to fail and this sort of thing was going on repeatedly and so he decided to clean up sacked and come up with idea that tests need to run in isolation today of course when people talk about isolation they mean that every class should be tested in isolation but that’s not what came back was talking about unit tests should be automated repeatable consistent and minimum of course automated repeatable and consistent really means that every time we run the tests they should they should be automated they should be consistent in their outcome in other words they should be flaky and flaky test actually is a big problem if as soon as you find you have a flaky test you need to nail it down if you let it go on and hope you know somebody else is gonna fix it it just becomes comes to a point where then people don’t want the test because they don’t know when to protesting would not do so you need to have tests that are automated such that you click a button and it there on Martin follow even talks about this and one of the big reasons he says people should be doing unit testing is for this the fact that you can have a suite of automated tests if you can’t automate them through a command line or some other interface doesn’t matter what it is as long as it’s automated it’s fine if you can’t automate it that’s a problem and I know from my own experiences that when I wrote a bunch of tests and they weren’t automatable in the sense that if I just had control RA which is the shortcut and Visual Studio and my test and run and succeed they didn’t run off with the fail because of something had to be done or set up before I could on the test that was something that was I used to really hate minimal is kind of going talking back to the Delta coverage bullet Collier in the same same way what it means is that you need to be cautious of the fact that you don’t write too many tests you only want to write as many as are required if you are satisfying all of the functional requirements and scenarios of the system you you’re you’re building then that’s what that’s all you need to write there’s no need to write tests above and beyond that requirement and if you’ve got gold plating in your system maybe you got some class they can do ten things more than it than the actual system requires then maybe you need to remove that the idea is not to build a system that can do more than its required to do you should be building the system to the extent that it is required to do so that you can ensure that that is exactly what you require it to do and so you can test against it test should be maintainable this this reminds me of my when I first started unit testing and I wasn’t really sold on this idea I mean I should do testing of course you know you can’t build software and not test it I used to call them test harnesses they were essentially a bunch of console applications that were there were you know part of source control and all that but they were not they were automated by way of the fact that every complex feature or scenario was tested through these test harnesses and so if you ran a bunch of tests Alice’s your tests were automated in that sense but the notion of unit testing as I was first introduced to it which was test every class that didn’t quite gel with me and so it took me a while to be convinced of the benefits of unit testing and of course as soon as I started writing unit tests the way I felt comfortable which is the approach that I’ve been presenting to you over the last few videos starting with the unit testing rebooted video I started to see the value for writing unit tests in the framework that’s given to you by in this case we just to do and the unit testing framework so that you can make them automated and repeatable but even today

I find in organizations people Creed writing unit tests as a junior programmer job now I’d managers would come to me and say you just put that person on unit testing detail for a couple of months I think new people should be starting with unit testing but that’s not because unit tests are not valuable or they shouldn’t be maintainable they should start there probably because they get a good insight into what the area of the system that they’re looking at is doing and how it’s expected to behave but I think unit tests are as important maybe if not more important than Prussian code so even though we treat production code as sacred I think unit tests are certainly at the same level if not more and the unit tests therefore need to go through the same rigor the same practices the same best practices of best coding practices as you do in your Prussian code if you’re designing some aspects in your unit-tests products themselves in regards to let’s say certain sort of classes method names browser names all that the the same practices should be followed they’re in Ken Beck’s book when he talks about red green refactor refactor Lee mentally factored the the test methods the unit tests not so much the code because that was a completely different step for him to start sort of do the design of the code you know refactor the code but when he said red green refactor you talk about refactoring the test methods themselves so you don’t let the test methods get to the point where they’re unmaintainable this is this is a big deal I think unit tests should be written in a very very maintainable clearly understandable fashion in fact just to reiterate this this idea I think I feel very strongly that I have to put an extra effort with names primary names method names test method names and variable names and such because I’m trying to tell my future self or somebody else on the team or somebody that may join the team in the future provide them with as much help as I possibly can so that when they see the test and the CD the code inside the tests there’s a whole lot of information in there not by way of comments I don’t like comments but by way of the way you name things and the way you write your code that helps people understand what it is your intent was because you’re because you’re in the groove at this moment in time tackling this one functional requirement and the various scenarios you’re in the best position to write the most helpful code variable names etc method name is the scenario names all of that to the best extent possible to help yourself your future self and others on the team and future members of the team as well understand what you were thinking and what the requirements were as you knew them then maybe five years data requirements have changed but at least by looking at what you’ve done five years ago you know exactly where you were what state of mind you Warren and what your mindset was at that time code coverage this is it’s a fantastic tool I think core coverages is really great but it’s completely misused for the most part code coverage should be used as a guide if you are starting with the tests on in a certain project and you write the test and you look at the code coverage and you say okay you know I missed this one you know a branch of code over here I need to think about like why did I miss it you know did I not get a certain scenario or functional scenario in place or is that conditional branch probably not even required you know CEO to make that choice but you can use code coverage for those kinds of things you know you might have missed a certain class oh yeah you know I didn’t this one class is not in play and it’s not been tested either you this is scenario or you need to write a class test or class integration test to make sure that that class is completely tested and unfortunately you know managers and other organizations in general like the statistics and they debase all of their sort of performs metrics based on statistics and so this is a good number to get and then they drive you to high code coverage values the other downside to going towards a like say a number lets you decide amongst a team that we need at least 80% code coverage well

then a one gets to 80% and whether you’ve covered the functional scenarios that are required to be covered or not is irrelevant because you’ve got to 80% and it kind of acts as a marker or a milestone for people to achieve so in some cases if the milestones are attainable then people stop right there in other cases they’re not attainable let’s say like hundred percent code coverage then people are doing everything they can to get there and you find that to get to that hundred same code coverage you’re writing lots of tests there are sort of irrelevant to the business but you tryna get that that number the other side of it is that 100% code coverage doesn’t imply that you have no bugs in the system you only have the option code coverage only indicates that you have coverage of the code you’ve written but the of course that doesn’t say that you missed or not miss certain functional scenarios or that your understanding of the business requirements themselves are a bit warped and so you’ve you’ve got a bug in the implementation and your tests are not telling you that because that’s your understanding so how could you possibly know you introduced about you can always trust low code coverage levels if you’ve got you written a certain amount of code and you’ve got now unit tests for that and you’ve got a low code coverage you can certainly trust the fact that you got low code coverage it doesn’t say anything about where you stand but certainly local College is telling you you’ve got low code coverage which means you have either missed a certain few scenarios or you’ve got some gold plating in your system either ways so if you have a high code coverage you can’t quite trust the high numbers but you can only trust the the low numbers test induced damage this is probably my biggest pet peeve with with unit testing TDD and and such something that I still sees is very prominent in the software field and was one of the reasons that I was not happy about doing unit testing at least the way I was introduced to it which was testing every class no matter what testing every class and isolation so the first bullet point this is designing for testability now it seems innocent designing for testability I think that’s the problem I think designing something for testability itself is the problem and a lot of people aren’t driven by this you know I can’t if I do like the second test something I’m not sure that I want to design a system to be testable I want to design a system that works for the business at hand for the for the job its intended intended to do I do believe that if you design your system well it will be testable but I don’t start off but I don’t ever think about the testing aspect while I’m just doing the design that’s not to say sometimes you trip up and introduce some bad design because you know we’re all human so we do make mistakes but the focus should be on designing a system well doing a really good job of doing the design of system well and if you have designed your system well then it should be testable conversely just because that system is testable doesn’t mean its design well and I’ve seen plenty of the stuff myself I’m probably guilty of doing it in my formal formative days of getting into just being a road tester system you know designing a system and being ro tested without the unit testing aspect but certainly going down there are unit testing I’ve done the same thing you know focus on the the testability of it so I’m designing everything and on testing and then I find I what a great system that can be tested but it’s not designed well and she would be very careful about that test induced damage another pet peeve of mine and I’d rather go down this rabbit hole here it is dependency injection I personally believe that dependency injection is test induced damage till date I don’t use dependency injection in my designs because I consider to be a design damage now that doesn’t mean I can’t do testing again I can do the same amount of testing that you can without dependency injection that you can with dependency

injection I can do without I could test every class of my system that’s what I wanted to do you know test every class in isolation but I don’t like to design my classes so that they can be tested just like I don’t like to design my systems so that they can be tested I’d like to design my system and then I’ll tested but enough said about dependency injection I know it’s another religious thing with most people Bowl returning methods this is one of those classic ones in fact let me show you thing a post from Martin Fowler where he talks about this it shows this as an example here so here’s his mocks and stubs blog post and he has this assertion here order dot is filled cut this is a method because Java so in Java we don’t have properties for say you got methods I can’t imagine that the order class has a need in production for is filled why would you want to know that I mean I call the fill method here and if the fill method succeeded that’s fine I’d want to check to see if it’s filled if it didn’t succeed I would expect you to throw an exception so I won’t have a is full method of property here and this I believe is test induced damage if I saw classes of mine having methods like this which are not really required in production then that is test induced damage so bull returning methods if you have a bull returning method it should be an actual bull such as is leap year or you know some some method like that that truly requires to be a bull returning method but I always suspect bull returning methods the moment I see a bullet and I’m checking to see what is it doing and do I need it to be a bull now if there are methods are action like insert customer update customer delete customer these are actions or commands they don’t require return values except for insert insert is one of those cases where it can ask to do both I’d you you create a new record as and you have to return the city the identifier for that I caught that’s one of the odd cases but the lead customer update customer don’t need need return values if they succeed they could do not bill throw an exception so if you find yourself writing returning a bull for those methods you know delete customer bull to tell you it was deleted or not that’s wrong similarly if you have a bull for an update customer an action or a command method out question yeah and I see this a lot with bull returning methods or or properties that are bull so you can check up on it so I think that takes care of the different kinds of testing dues damaged is a variety of them but these are the high-level ones that I think are most prominent and people don’t see them in the the thing is normal to do that and I’ve known people that will go in and add methods and properties to production classes during that testing video they’re having difficulty kind of test some aspect okay this is probably the one of the best thing that I have discovered I guess from Rochelle’s book on the art of unit testing which was the naming convention for the test methods now in his book he is a three-parter so I don’t mean the book is a three part of the method name is got these three parts to it the underscores delineating the the parts I’ve introduced class name as a first part just because in Visual Studio when you look at the the tests let me show you there I don’t do that normally for acceptance tests because acceptance tests are at that level where you don’t care to know what the classes you’re only concerned about the actual unit of work so you can see here that these these acceptance tests don’t have the class name as the sort of prefix so the first part is the unit of work the next part is the scenario and so on let me just get back to the slides I can show you so the first part is the class name and cell said this was more for the reason that Visual Studio is it’s easier

to see because somebody you might have a the same scenario being tested from the acceptance level versus the class level and you want to make sure that you can see the difference so the first part is the class name second part is the method name or the unit of work name depending on what what you’re doing what you feel comfortable with sometimes from my case most method names are the the functional requirement right so it’s not like the method names are different and so the unit of work and the method name are in sync the third part is the scenario what is the actual scenario that you are trying to test around that functional requirement and then the your expectation of that all the businesses expectation of that in that scenario see if I look at over here with our well I got the this one scenario this say one functional requirement is five scenarios so the first one functional scenario is register member the expect the scenario is with the existing member email the expectation is should throw the next scenario is with null email address should throw with no full name should throw with no password should roll with valid parameters should succeed and so of course there’s one positive next destiny others are negative tests they’re all being tested and so it’s very easy to understand what is there you’re trying to test what is it deadlier you’re doing in that test but I got the test method itself you can see that I can see with null passwords you throw and immediately I know exactly what the scenario is and what the expectation is the other thing I do is when I start writing the tests also define the scenario and expectations so allows once have written the test method itself I start with the assertion so I’ll go into the test method and I’ll if I’m not ready for the court at this point I’ll write it in common form how do I intend to assert on that expectation that’s fine I find that helps me think about what is the lamp Rhino test and how will I do the testing okay so this is the same as or similar to your coding convention in decoding you know guidelines I guess were from a maintainability standpoint it won’t be very aware of method names variable names and such and I think in the you know testing me write your test matters is even more important let me see if I can show you something here so the scenario here is with no password throw register remember with null password row this is the register member method here and this panara here if I were just put in a null there I’d say okay well what why is Boston all part of course now with c-sharp you can prefix the panara name as well but it doesn’t help with the understanding you have to do it all so it clutters up the code a bit and really I prefer to make sure that I name my variables with the intent so by looking at the variable name I can tell the value of Y well in this case in these cases works really important so we’re here it’s with not email address I gotta not email address so you can see that this panera is the Dino email address and so on so naming of the parameters is very useful is very helpful and also very important let me show you another project over here this is the one we you probably saw this in the test mediator despise video not supported product I could have very easily just put a nexus 6 right here and I’m gonna be wondering why is it xxx why is it not something else you know was it on ABC some people actually and I had a end up writing actual names that are and you have to wonder like why is that supposed to be not supported how do I know that so the variable name tells me it’s not supported I can make it what I need whatever I want it to be the name tells me it’s not supported so I don’t have to worry about I would even go further and say something like over here let’s say the first parameter here is

customer ID all right I will do something like here the development customer ID like that so that it’s not it’s not relevant do you have a customer ID it doesn’t be matter where this one to or 23 it’s irrelevant so it’s very clear and in the intent is clear you know that the one doesn’t have a meaning to your test and makes it simple and clear for people to understand that you’re only interested in the non-supported product this is irrelevant and so don’t worry about it what is the one here quantity one is the quantity one relevant to this saying the scenario is when order place with not supported product but if it’s not supported to be care for the quantity so I would do the same thing I’ll do is relevant quantity moving and getting the spellings right there and that way I can use that here so I know by looking at this that the other two are irrelevant and this may be going a bit too far but it does I’m gonna get across this the point that descriptive and proof of purposeful variable names is really important and the other part is always I use the triple a style so whatever style you’re using begin when then or whatever the other behavior in testing styles are even though there’s no arrange I leave the range blank so it’s clear to me that an is called a miss it I always use the marker so I know where something starts and where it ends sort of thing so there’s many kids in art is we don’t have an arranged then doesn’t matter us to leave the the comment there so you know that there’s the part is there’s yeah it’s just feel it it’s more useful to see test in a consistent way rather than inconsistent manner the next to this line in the next one are I see very similar I’ll talk about the assert is true when is false as along with the S or R equals so first off don’t course something that is not a bull into a bowl so that you can use the is assert is true and is false that’s the wrong thing unless the thing you’re trying to assert on is intrinsically true or naturally Bowl don’t course it an example is let’s say you have a count of something and you say assert is true blah dot count equals three and so you course it now you’re saying blood of count equals three is a bull expression and you’re saying is that a certain that is true let me show you by way of for example okay so let’s I didn’t you just ended here I wouldn’t bother naming the name here correctly but so let’s say we have I say the test is all right so I’m not gonna do it for real I’m gonna just show you this so expected quantity in stock is let’s say 3m I need your your at you get actual quantity in stock let’s say this is three and then you do an assert they say assert dot is true expected or in stock equals actual quantity stock right I’m gonna run this test and this test passes everything is good now what if it doesn’t what if the expected is not the

same as actual you’ll see here now that the error message sorry for this one is the test fail and it says assert is to fail and you have no idea white fail so what you supposed to do with that now an alternative is the R equals which is what I’m actually suggesting but that go actually further than that so let’s say R equals and you say expected quantity in stock an actual corn in stock and let’s say we run this test again and you find that even here this is expected for actual three-month imagine you got thousands of tests and this one test fail fails what are you supposed to expect for me I understand from here you can’t send even without with the numbers you still don’t know what for I was three right so I suggest doing two things one is don’t course things that are not pulled into being a bull try and use a certain R equals four the most most part unless the the thing you’re asserting on is naturally a bull and then define a good helpful string message so let’s say who was that now let’s see what will happen when this test fails and you see here that gives you an actual message sister does they expect it for actual 3 and dennis’s the expected quality of the product in stock was 4 but the actual quantity found was 3 so between the the test method and scenario name and the message it’s very clear as to what went wrong and what your expectation really was and this may seem like a lot of work but I believe that your tests are as good as your failure messages if your failure messages are not helpful you might as well just don’t have the tests in place because when it fails you know the understands why it’s failed and what the expectation was of course you are when you’re writing this test you’re in the zone you understand the scenario you know exactly what is expected you are the best time to write the best and most helpful message for others on the team for yourself here feed yourself and then you move members on the team so always take the time now to write useful accurate messages so that you understand when things fail and somebody else who sees the test messages message itself in fact when I see this message I can glean more information as to what takes the expectation of that test was even though it’s not failed I can just by reading it I guess oh yeah you know that’s what’s going on here so these Testament these messages in DSS are useful so always use messages and this is just blatantly obvious so I already talked about both the assert are equals as well as the is true here’s another reason for why you want to do that if you didn’t use the message it will say something like expected register memory information actual register memory information you have no idea what what’s the difference like why aren’t these two equal right answer because they’re difficult to understand by looking at a message why they weren’t equal and so in your test message you might have to go a lot further and say well you know maybe the first name was supposed to be the same but they’re not the expected exception attribute and we talked about this in the test bias test mediators video but I’ll go through the whole thing here again I think it’s important to see the actual cases here all right so first up let’s look at this this one so here I’m using the expected exception attribute I’m using into the a attribute because I have this exception here which is extremely specific remember even address not unique exception there’s only one condition under which this exception will be thrown and so I can I can inch probably

should use this the expected exception attribute in this case because this very very specific so always or you should only use the expected exception attribute when the exception you’re expecting is very very specific as soon as the exception becomes a little more generalized meaning if you’re using the same exception from multiple different places with slightly varying scenarios then you should not use the expected exception attribute so another case here’s and this class this is the my member data manager class is doing a class integration test so it’s 2d working against through your database and I have this one scenario register members the method name of the unit work but knowledge the name should throw my that’s the scenario and expectation and what I do is I create a memory situation but I’m allowed the username which is the scenario with not leave the name and then I execute the register member method and I I’m expecting an exception here except but sequel server the exceptions are always going to be an SQL exception where there’s a store proc issue with this connection issue or a database error or internal error is always in SQL exceptions suppose this is like the the other extreme the sex section is sergeant generic that you just have no option but to do your testing this fashion I think it’s a good example on the less so in this case what I do like I catch the exception I am expecting an SQL exception but the problem is that sequel server all ad darknet it throws an SQL exception no matter what the problem is with the database even if you couldn’t connect to the database it’ll be in SQL exception so here I do catch the exception but then I go deeper into the exception and I arrive I’m really asserting on this sort of subset of the message I’m intentionally not trying to be very very specific about what the actual message will be I want a component of the message to be there and so I’m sitting on that fact I’m called an extension method on this it’s not actually an extension method is another class that does the the validation here so I can give it the exception I got and the sort of a part that I expect and this classes method does the the needful which is let me show you that here simple really simple implementation is doing in assert is true but is saying an exception of block type was thrown which is what can really happen however the expect exception message was expected to contain the words blah but the exception message was la and so just made it really simple free to honest and see the problem and when you do this whole thing we use the try-catch within your method to catch very specific exception always put an assert fails so after this method when this method is executed you’re expecting an exception if it doesn’t throw an exception you need to fail this test and that is critical if you don’t and an exception doesn’t happen your test will pass and you think you’re doing the right things as soon as you have a scenario we write the method immediately right the fail though you will forget it and then work on the implementation of the the catch in fact what I do is when I do this I said I write the method name and then I determine how I planned to do the assertion right away as soon as I determined that I need to do the try-catch i’ll also fill in this mine here so i know i don’t forget it all right now we are kind of coming to towards the end of this some misconceptions passing tests don’t imply good design well testable systems don’t imply a good design although passing tests imply good design some people have this idea that though if you can’t have passing test then your design is not good I’m not sure how that how they equate the two but this frequently mentioned around and so I thought I’d say that as a misconception 100% code coverage doesn’t imply no bugs we already discovered that we talked about that sorry hunt the same code coverage we probably also discovered it

but we talked about this hundred percent code coverage doesn’t imply a percent functional coverage we even talked about that indirectly where just because you got 10% code code it doesn’t actually mean you have implemented all of the business requirements of the system you’re trying to build some good and bad science speaks us to the last slide change in behavior warrants test to change this is a good sign because if your behavior has changed you must your test must change otherwise there’s something wrong there if they’re not changing even though you change your behavior you will missed a test or a scenario or something so that’s it’s not a good sign if changing a behavior doesn’t want to change test to change refactoring wants tests to change that’s a bad thing we talked about this in the unit testing we booted video we’re refactoring shouldn’t want your test to change or break so they do that’s a bad sign too few tests that basically puts you in a spot where you can’t confidently change code and that’s a bad thing that we don’t have enough tests to cover the scenarios that you’re supposed to as a result you don’t know if you can convert me change your code too many tests means you spend more time changing or fixing the test and needed to actually change the code of a fact of the code and that’s a very bad sign let’s go speaks to the sort of the unit testing metaphor of you know test every unit as well as the Delta coverage aspect so if you got too much coverage in too many different ways from two different to many different kinds of tests then you end up spending a lot more time changing and fixing the tests when requirements change as compared to the code itself the Prussian code and that brings us to the end of this session on unit testing best practices if you have any comments or suggestions please let me know by putting in your comments and I shall see if I can either answer them or accommodate some of the other suggestions that you might have with regards to videos thank you