Software testing has become an essential activity in modern software projects. Unit testing promises automation and thus increased efficiency and reusability when it comes to software testing. In practice, however, unit tests are rather a burden than an efficiency booster. The problem here is that most companies do not use the knowledge that has been created over the last decades, while unit testin emerged. They rather create ad-hoc tests to satisfy some code coverage criteria. In this article, I show you in 5 steps how to overcome this problem and bring your unit testing into the 21st century.
1. Think, Specify, Code
Usually, people start writing code right away when they get some requirements from a customer. After some functionality is implemented, they write some unit tests to make sure that code coverage is not too low. As a result, software code becomes spaghetti code after some time, because noone thought about a meaningful structure in the first place. Even if a solution architect has provided some overall architecture, as soon as someone has to look under the hood of the individual building blocks of the software, chaos emerges. However, by following these three steps, you make sure to avoid these pitfalls:
1. Think. Think of what you want to do, before writing any code. Try to envision what functionality you want to implement, and how to do that, as detailed as possible. Also grasp the dependencies and synergies between different functionalities of your desired system. If something is unclear at this stage, make sure to clearify it! Talk to someone else who has the knowledge and decision authority to help you (e.g. your dev lead, or your project manager).
2. Specify. By writing down your thoughts from the previous step in a structured way, you can dry-proof your concepts. In other words, you see whether what you envision could actually work, or if some refinement is still needed before implementation. One way to do that could be by already defining and even implementing unit tests for the desired functionality (this idea became famous as Test-Driven Development). In many cases, it might already be sufficient to just write and draw down what’s going on in your mind. Either way, if you find out that some of your thoughts do not play out when being specified properly, don’t ignore that! Try to think of a solution. Only start with the final step if you know that everything in your thought actually plays out on paper as well!
3. Implement. Only in a last step, actually implement your thought, based on your particular specification.** When you’ve completed the previous step properly, this is simply a translation of your specification to the programming language of your choice (maybe even automatically? but that’s a topic for another article ;)).
As a result, you can make sure to have a clear code structure by thinking about how to integrate new functionality into the existing code. More importantly, you avoid having to throw away code, because you know from the beginning why you write each line of code, and have all the necessary information to make your thoughts play out as after they have been implemented.
2. Be efficient
In the end, you want to write as much code as possible, in as little time as possible. But how can you actually achieve that in your daily work? You can read my detailed personal take on efficiency in unit testing here:
1 Simple Rule To Better Unit Tests But in the end, it comes down two the following two aspects:
1. Gain as much value as possible from each unit test
2. Minimize effort for (i) creation, (ii) execution, and (ii) maintenance of your unit tests
3. Use the right methods
Most of the time in software development (and thus lifetime of software developers) is lost because developers simply do not know how to use practice-proven methods that make them more productive, especially when it comes to unit testing. You can e.g. save 60 % of your unit testing effort by applying two simple methods when creating unit tests. These methods are described in detail in the following article:
2 methods that help you save 60 % of your effort in Unit Testing
4. Stop writing unit test code
One essential time killer for every person responsible for unit testing is to actually have to write code for every single unit test. One essential problem here is that in the end, the same general-purpose languages are used than for writing software, although all unit tests have a similar structure. Every unit test requires a unit under test, input data for this unit under test, and output data that has to be checked. This definition alone should be enough to create a unit test. Additionally, the input and output information can also be generated automatically for a given code unit (but that’s content for another article ;D). However, to actually implement a set of unit tests, the same lines of code have to be written (and maintained) over and over again.
5. Learn from test executions
Unit tests are not only about executing test cases to find errors in your code. First of all, simply writing tests does not tell you anything about your software without an evaluation of the completeness of your test suite (find out more about test suite evaluation in hack #5 here:
5 Greatest Hacks For Unit Testing.). But more importantly, you can also learn a lot from executing your unit tests, besides finding software defects. Read more about these learnings in this article:
5 things you can learn from executing your test cases
Cartoon vector created by PCH.Vector – www.freepik.com
Daniel Lehner