Unit Tests
The Tree Laws of TDD
- 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.
- Third Law: You may not write more production code than is sufficient to pass the currently failing test.
The tests and the production code are written together, with the tests just a few seconds ahead of the production code. If we work this way, we will write a lot of tests, the sheer bulk of those tests, which can rival the size of the production code itself, can present a daunting management problem.
Keeping Tests Clean
Tests must change as the production code evolves. So, the dirtier the tests, the harder they are to change. Therefore test code is just as important as production code, it must be kept as clean as production code.
Tests Enable the -ilities
No matter how flexible your architecture is, no matter how nicely partitioned your design, without tests you will be reluctant to make changes because of the fear that you will introduce undetected bugs. But with tests that fear virtually disappears. So if your tests are dirty, then your ability to change your code is hampered.
Clean Tests
What makes a clean test? Readability. What makes tests readable? The same thing that makes all code readable: clarity, simplicity, and density of expression.
Domain-Specific Testing Language
Rather than using the APIs that programmers use to manipulate the system, we build up a set of functions and utilities that make use of those APIs and that make the tests more convenient to write and easier to read. These functions and utilities become a specialized API used by the tests. They are a testing language.
A Dual Standard
The code within the testing API does have a different set of engineering standards than production code. It must still be simple, succinct, and expressive, but it need not be as efficient as production code.
That is the nature of the dual standard. There are things that you might never do in a production environment that are perfectly fine in a test environment.
One Assert per Test
There is a school of thought4 that says that every test function in a JUnit test should have one and only one assert statement. Unfortunately, sometimes you might have to split the tests which results in a lot of duplicate code.
The single assert rule is a good guideline, but you may need to break it sometimes.
Single Concept per Test
Perhaps a better rule is that we want to test a single concept in each test function.
F.I.R.S.T.
Clean tests follow five other rules:
- Fast Tests: should be fast. They should run quickly. When tests run slow, you won’t want to run them frequently and you won’t find problems early enough to fix them.
- Independent: Tests should not depend on each other. One test should not set up the conditions for the next test.
- Repeatable: Tests should be repeatable in any environment. If your tests aren’t repeatable in any environment, then you’ll always have an excuse for why they fail.
- Self-Validating: The tests should have a boolean output. Either they pass or fail.
- Timely: The tests need to be written in a timely fashion. Unit tests should be written just before the production code that makes them pass.