When writing software we often are only focused on just that: getting the feature done. With the rise of Test Driven Development (TDD) some of us will first write tests before the actual code and this is great. Personally I like the concept of TDD, but I can’t seem to make myself adhere to it as I am always to eager to write the code instead of first write the test.
Another reason I don’t do TDD is that I find it hard to write a test for something that doesn’t even exist yet. At least the public interface should exist, but this interface can change often during my implementation because I don’t come up with a full design in the beginning.
But even though I don’t do TDD, I spend a lot of time writing unit tests, making sure all of my code is being covered and that I didn’t forget anything. I do this because this is the only way to avoid bugs in the future. Others however will spend either much less time on writing tests or none at all but will write a lot more code. To an outsider it may seem like these developers are more productive as they output more code. There are however a couple of problems with this idea.
The most obvious could be that there are bugs the developer didn’t think of and was not covered by his tests. In this case the bugs might appear much later and will have to be fixed. Because of the delay in which the bug occurs itself you will spend much more time on investigating and fixing it than you would have if you found it during the initial development. Thorough testing of all scenarios makes sure that as many bugs as possible are discovered as soon as possible.
But even if all the code of the developer is completely bug-free, there is no guarantee that changes to the code will not introduce regressions. The only way to prevent this is to test all the scenarios again, but due to a lack of automated testing it will be very intensive to do this over and over again and you might easily forget some special corner case.
Even developers who know that they should be writing tests will sometimes not do so. Either because of a tight deadline that may not be achievable when spending too much time on testing, or because the current state of the software is so ‘simple’ and ‘small’ that it doesn’t need any testing. While the first is acceptable if you take full responsibility of the fact that bugs will occur after the deadline and a lot more time will be invested to fix them and add decent automated testing later.
The second however is straightforward unacceptable as no piece of software, no matter how simple or small should go without testing. Your small piece may (and probably will) grow in the future and by doing so it may break your initial usage (causing a regression) as you are only focused on the new requirements and not the old. The automated testing acts as a guard that flags the old behaviour has been broken.
In the end, real constructive working is achieved only if by destructive working nothing can be broken. This boils down to having tests to try and break the code and prove that it works as expected and thus the code is good enough to be released. In the end writing automated tests is much more productive than constantly fixing bugs caused by the lack of tests.