Can you imagine nowadays a non trivial software system with no automate testing, with no unit tests, integration tests or GUI tests? Have you ever worked on such a system? For sure, I have. Hundreds of thousands of lines of code with ZERO test coverage, this was the system I worked on years ago. Adding new features was harder and harder, changing something required by a customer broke features of other two customers and the product demanded a bigger and bigger testing team, the only safety net we had. And, the fear we were experiencing after every new production deployment… we ended up creating separate branches for some of the customers. I can’t imagine now a bigger mistake than that: merging bug fixes into many branches, developing the same feature multiple times as some customers branches were lagging behind and synchronizing all the branches would have been impossible.
But now (working on a different product), we do have tests, thousands of tests. I wonder if the testing code is not larger than production code. I can easily check, but this is not important now. The test code quality is important, we should be able to easily add new tests, to easily update the existing tests. Test code should be maintainable, reusable flexible. “Test code should be just as important as production code. It is not a second-class citizen. It requires thought, design, and care. It must be kept as clean as production code” (Robert C. Martin, Clean Code). Tests are the most reliable documentation of the system as well. When it is required to change a certain functionality the best thing you can do first is to read the existing tests (unless you are the luckiest developer in the world and have an up to date documentation of that feature that covers all the corner cases). So, write clean tests, it will pay off long-term. This is the second most important lesson I’ve learned, the first one being obvious: test your code!
Besides tests code quality, tests speed is important as well. Maybe this problem is not visible in the beginning when you are just starting to create tests. But when you have thousands of tests, the speed is critical. Developers will avoid running the tests on the local machine if they are too slow. In the most cases, GUI and end to end tests are the slowest ones and we tend to write many of them. Don’t forget about the test pyramid. Write less GUI and end to end tests and mostly unit tests. That’s the third lesson.
What are your lessons learned? Leave your comments below.
Hi Marius. Have you taken on a large project with no tests and introduced tests after ? How do you go about it ? Aren’t the changes needed to make code testable overwhelming ? Can you still be sure you don’t break anything ?
There is no magic solution to this problem, you just have to start writing tests. First, write tests for the new code. You will find that the new code suddenly looks better than the old one as unit testing usually leads to better code modularization. Now that you know how testable code looks like, start writing tests for the old code. Start with the core functions of the system, with the code that really matters. Usually, a code base without testing is not so well organized, the “units” are not so clear so, sometimes, refactoring will be needed. Measure the test coverage often, never allow coverage to decrease. This is hard work but it will pay long term. I’ve seen a large project (around 500K lines of Java code) going from 0% to 14% test coverage in a relative short period of time.