Clean code — Unit Test
Right now I’m reading for the second time, the great book Clean Code by Robert C. Martin aka Uncle Bob and I think it’s a good idea to write down the most important ideas that it tries to convey to us. Today, I will focus on the ninth chapter.
The Three Laws of TDD
Everyone knows that TDD asks us to write the unit tests first before we write the production code. But that rule is just the tip of the iceberg. Consider the following three laws!
First law You may not write production code until you have written a failing unit test.
Second law you may not write more of a unit test than is sufficient to fail, and not compiling is failing.
Thrid law You may not write more production code than is sufficient to pass the currently failing test.
These three laws lock you into a cycle that is perhaps thirty seconds long. The tests and the production code are written.
Keeping Tests Clean
That having dirty tests is equivalent to if not worse than having no tests. The problem is that tests must change as the production code evolves. The dirtier the tests, the harder they are to change. As you modify the production code, the old tests start to fail, and the mess in the test code makes it hard to get those tests to pass again. So the tests become viewed as an ever-increasing liability.
From release to release the cost of maintaining my team's test suite rose. Eventually, it becomes the single biggest complaint among the developers. When managers asked why their estimates were getting so large, the developers blamed the tests. In the end, they were forced to discord the test suite entirely.
But, without a test suite, they lost the ability to make sure that changes to their codebase worked as expected. Without a test suite, they could not ensure that changes to one part of their system did not break other parts of their system. So their defect rate began to rise. As the number of unintended defects rose, they started to fear making changes. In the end, they were left with no tests, tangled and bug-riddled production code, frustrated customers, and the feeling that their testing effort had failed them.
Test code is 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.
Clean Tests
What makes a clean test? Three things. Readability, readability, and readability. Readability is perhaps even more important in unit tests than it is in production code. What makes the test readable? The same thing that makes all code readable: clarity, simplicity, and density of expression.
One Assert per Test
There is a school of thought that says that every test function in a JUnit test should have one and only one assert statement. Those tests come to a single conclusion that is quick and easy to understand. But Robert Martin isn't afraid to put more than one assert in a test. I think the best thing we can say is that the number of asserts in a test ought to be minimized.
Single Concept per Test
Perhaps a better rule is that we want to test a single concept in each test function. The best rule is that you should minimize the number of asserts per concept and test just one concept per test function.
F.I.R.S.T
- Fast: When tests run slow, you won't want to run them frequently. Eventually, the code will begin to rot.
- Independent: Tests should not depend on each other. One test should not set up the conditions for the next test. You should be able to run each test independently and run the tests in any order you like.
- Repeatable: Test should be repeatable in any environment. You should be able to run the tests in the production environment, in the QA environment, and on your laptop while riding home on the train without a network.
- Self-Validating: The tests should have a broken output. Either they pass or fail. You should not have to read through a log file to tell whether the tests pass.
- Timely: Unit tests should be written just before the production code that makes them pass. If you write tests after the production code, then you may find the production code to be hard to test.
Conclusion
Tests are as important to the health of a project as the production code is. Perhaps they are even more important because tests preserve and enhance the flexibility, maintainability, and reusability of the production code. So keep your tests constantly clean. Work to make them expressive and succinct. If you let the tests rot, then your code will rot too. Keep your test clean.