As discussed in my last article, Unit Testing is the practice of writing code that can be run interactively or automatically to exercise (test) isolated blocks (units of work) of an application (the System Under Test).
There are four main reasons that you should care about Unit Testing:
- Improving Estimation For Changes
How do you know that your code works as expected? Does a successful compile mean the requirement has been met? Are there typos (that made it past the compiler in compiled languages) that change the functionality from what was intended by the developer?
Perhaps you create a separate little application to manually execute your code, carefully stepping through the debugger while intently examining the watch window. Maybe the testers in Quality Assurance are responsible for validating an application and reporting back to the development team if the application is working.
While these options have been used for years to validate software (and certainly working software has been successfully deployed long before the Unit Testing movement), they are very manual and time consuming. Manual and repetitive tasks tend to get abandoned when schedules are tight or projects fall behind, and in general tend to be unsustainable for very large, lengthy, or complex projects.
Unit tests validate the code as you write it, especially when you are using Test or Behavior Driven Development. With well written Unit Tests in place, you are validating each of the building blocks that make up the larger system. As you build up the application with more and more blocks of code (methods in languages like C# and VB.NET), you gain increasing confidence in the application as a whole. Each part has been tested and can stand on its own, increasing the likelihood of larger successes.
Integration, end-to-end, and surface testing are still required components and are not replaced by unit testing, but enhanced by the practice. When an issue is found in the larger testing runs, you will still have to expend effort to track down where the bug is located. When the bug is found, the test gets updated to guard against that use case, and you have the confidence that it won’t happen again.
Having unit tests in place gives developers the courage to try new approaches, refactor inefficient code, improve the user experience, and other code changes that might not be attempted otherwise due to fears of possible side effects. Making large scale changes means large scale testing, and if it’s manual, it usually won’t get done.
Does your application have unit tests in place? Then go ahead and make the change. The number of breaking unit tests can objectively show the overall impact of a change. If a significant number of tests break, the effort required to refactor the rest of the code probably outweighs the benefit of the change. Your team no longer needs to fear innovation.
Only a portion of development time is spent actually typing. Most developers spend the majority of their time in think time – looking at existing code, mentally working through the next steps, debugging, etc.
Unit Tests help increase the cadence of development by reducing the time spent wondering what the effects of a code change would be, stepping through code (either mentally or through debugging), and other delays. Since a well written unit test proves whether or not the code works as expected, more time can be spent producing code and less time is spent fretting over code.
Unit Tests will quickly show if the rest of the code still works without manual testing, allowing the development team to continuously deliver and not spend so much time in analysis paralysis.
Improving Estimation for Changes
Another area of increased confidence is estimating changes. Having significant code coverage (the percentage of application code that is “Under Test”) in an application can assist in objectifying certain types of development estimates. For example, assume that a system has 1000 unit tests in place and it took six months to develop. When changes are made to the code, and all of the unit tests are executed, the percentage of failing tests will give an indication of the magnitude of the effort required to productionize the change. Of course this doesn’t work with all types of changes and enhancements to an application, but can be very helpful in a lot of situations.
Unit Testing isn’t just about writing more code. There are very real, tangible benefits to an effective testing strategy, some of which are outlined here. It’s important to also remember that Unit Testing doesn’t replace other testing practices like surface testing or load testing, but supplements them. Issues are found earlier in the development cycle due to the rapid feedback loop that unit tests provide, enabling QA to be more holistic in their testing, resulting in much higher quality software being produced.