This is a summary of what learned from a “Mastering TDD” course with Kent Beck. Given he is the creator of JUnit, I guess his thoughts on unit testing are worth considering.
In some cases I might have rewritten, changed, extended or simply misunderstood what he was saying, but these were my notes from the course, nevertheless.
- Doing TDD is like losing weight. You like having lost some weight, but not actually losing it.
- Taking really, really small TDD steps is useful when you’re unsure/confused about the code you are writing. That way you are at least moving forward.
- What kills productivity isn’t doing something slowly, but not doing it. I.e. when you switch to reading email, surfing the web, etc instead of working.
- Implementing a piece of code inside a test keeps your options open if you’re not sure about the future interface.
- Start writing the test which you expect to learn the most from.
- Most important, according to Kent: Writing a test is really telling a story about the code. Having that mindset helps you work out many other problems with testing.
- Deleting tests comes down to story telling – which tests do we need to tell the story about this code. (There is also a technical/coverage aspect, but it is of lower importance).
- When unsure about whether to clean something up or not – think about the amount of leverage it will give you. Worth it?
- When coding exploratory (without TDD), start TDD:ing when/if you don’t expect the code to die anymore, or when you think you’ve learned the most important lessons.
- In many cases: The more discussion, the less important the decision. Everyone agrees about the really important ones.
- Write code in a functional style, as it is more suitable for testing.
- Consider not using dependency injection as it makes TDD harder by encouraging a design where dependencies are spread out over the system. Instead, design many stand-alone modules which are unit tested individually without the need for mocked dependencies, then join them together in other classes which are tested through integration tests.
- Avoid abstact superclasses for unit test classes as they make the individual test classes harder to read.
- Duplication is often more okay in tests than in the production code because readability of tests is so important.
- For infrastructure-related setup code, @Rule can be used instead of inheritance in many cases.
- Write tests on the high and low level, but be weary of too many tests on the mid level. They tend to be more of a problem than help when refactoring.
- Kent: “I try not to have more tests than I need”
- Use one test class per fixture (i.e. set of test data). Name the classes after the fixture. That is how JUnit is designed and intended to be used.