From time to time I have to argue with some of my colleagues whether writing and maintaining unit tests is useful work or not. Mainly this is happening when somebody changed some code with existing unit tests and got a message from Jenkins stating that the build went either unstable or broke (depending on the configuration). Since I’m the one who introduced the usage of Jenkins in the company I am the main contact when it comes to answering the following questions:
– Is it really useful to have this test?
– This test is not from me can you fix it for me?
– Is it ok to disable/delete the test?
If I answer to any of the above questions with “no” the arguing begins!
Is it really useful to have this test?
Obviously the test was useful otherwise you wouldn’t have noticed that something broke (Oh, YOU didn’t noticed this. Jenkins did and told you…). Now start to find out what the purpose of the broken test was and decide if the tested result/behavior is still valid or if the expected result needs to be adjusted because of your changes.
What should I do with this test?
Either adjust the code or adjust the test. It depends. Deleting the test is only a valid option if the tested feature was removed. If a new feature was introduced and the tested feature is still valid then new tests should be written. And of course the code should be changed so that both features are still working as desired.
Introducing unit tests will break the design
That is true. But why is it breaking the design? It’s because the existing design is not ready for testing. To be honest our code base is up to 12 years old and in the “old” days unit testing was not known in our team. Now we have a big ball of mud of old code (also from me and I’m not proud of it) and I need to have unit tests for the entire code to provide high quality product. In order to get this mud testable you have to change the design. But the design changes can be done intelligently or stupid (and introduce new problems). Think about the best solution before you start and if you are not sure how to do it properly ask your colleagues.
I don’t understand the purpose of the test
Hmm, that could happen if you are in the unlucky position to break a test from the “old” days when we started to introduce unit tests. In those days we didn’t care much about the method naming. Some of the test methods still have the old JUnit naming convention with test<tested method><used parameters>. In this way the IDE creates test method stubs for a given class. So you know which method is tested but you don’t know why. Nowadays we use the “should” method names and the test purpose should be much clearer (not always). Sometimes the method names have the name of a Jira issue as part of it and I can find more information about the test there. If you still don’t understand the purpose of the test then you have to ask the author (if she is available and can remember) or you have to find out yourself (using the debugger). Finally rename the test to make it more clear for the next person and if necessary add some helping comments to the test.
To write unit test for the class I’m currently working on is impossible
Yes there can be corner cases where it is impossible to create tests. But mostly it is “impossible” because the design of the class is “sub optimal”. Very often the “untestable” class has very complex methods. Usually I don’t want to test the whole complex method at once but only the part where I changed the code (either because of a new feature or because of a bug fix). In this case I try to separate the block of code I want to test from the complex method (using refactoring tools from the IDE) and create only tests for this extracted code. This approach has the advantage that the complex code gets better and better every time I have to create tests.
Why should I write unit tests for a found bug?
The rest of this argument goes like this: “If I already found the bug there is no need to create a test. I already know/checked manually that the bug is gone.” True, but if we have legacy code with no tests at all we should start to create a safety net step by step. The best place to start with the safety net is the class with a known bug. Most of the time a class which has a single found bug has more bugs. At the same time it is most probably so complex that it should be refactored to a simpler design. And this should only be done if a safety net is available. BTW this approach is called DDT (Defect Driven Testing).
I don’t get time from management to write unit tests
That’s the “beat me to death” argument. In this case the developer has to decide by himself if he wants to deliver high quality code (tested, documented, extendable…) or not. It’s your choice. If you want to deliver high quality software and your company doesn’t give you the needed time then you have to ask yourself how long this company will be successful with its product. The more untested features get implemented the more effort is needed to find newly introduced bugs and to extend the product.
I don’t know how to use the unit test framework
This statement should only come from a junior developer fresh from the school. If a developer is giving me this statement I don’t know what to tell him. In my opinion every developer should good know at least for one unit test framework (JUnit, TestNG, you name it). If not, he maybe should change his job at least he should not call himself a professional software developer.