Why Solitary Tests Should Be Easy To ReadSeptember 9, 2020
Occasionally someone asks me the question whether it’s necessary to test the code of solitary tests? Usually this question is ushered by folks who are opposed to the idea of automated tests. Somehow they have the notion that one can keep writing tests for tests for tests for tests, etc. Obviously this is a complex and absurd thing to do. This attitude often stems from test code being overly complex to the point that an average developer is no longer able to understand the scenario at hand.
Solitary tests should be simple and easy to read because we need to be able to easily verify their correctness. This is also where the age-old principle of double-entry bookkeeping comes in.
According to Wikipedia, double-entry bookkeeping:
“ Is a system so named because every entry to an account requires a corresponding and opposite entry to a different account. The double entry has two equal and corresponding sides known as debit and credit. The left-hand side is debit and right-hand side is credit.— Wikipedia
Applying this principle to automated tests means that the test code verifies the production code, and that the production code verifies the test code. This means that solitary tests can be tested by introducing the very bugs in the production code that they are intended to verify and detect. The easiest and fastest way to accomplish this is by first writing a failing test before writing the implementation that fixes the test failure.
When we add solitary tests after writing the production code, then it’s more difficult to determine whether these tests are making the proper observations. The only way to determine this is to temporarily remove or comment the production code again to see if the test fails or not. This approach adds more overhead to the development process with an extra back-and-forth between the production code and the test code compared to a test-first approach. Regardless of whether we use Test-Driven Development or not, we should always see our solitary tests fail. This makes them more trustworthy. Never ever trust a test unless you have seen it fail!
Even when rigorously following the principles of Test-Driven Development the test code is only verified once, right after it has actually been written. What will happen when we change any of the code later on? In order to avoid going down the rabbit hole of writing tests for tests for tests, we need to be able to visually verify the correctness of our solitary tests, by using our eyes and our brains. And in order to easily do this, test code should be simple, small, discoverable and easy to read.
How can we accomplish this? For starters, test code should always have a cyclomatic complexity of 1. This is a software metric used as a quantity measure for the number of linearly independent paths through a program’s source code. It’s a very useful indicator as it indicates the number of pathways through a (test) method. This directly translates in never, ever using any branch constructs in the code of a solitary test like “if” statements or “for” loops.
It’s also quite important to avoid testing too much functionality in a single test. We should therefore try to focus on a single concern at a time. That is why designing production code for testability is such an important consideration.
If you and your team want to learn more about how to write maintainable unit tests and get the most out of TDD practices, make sure to have look at our trainings and workshops or checkout the books section. Feel free to reach out at email@example.com.
Jan Van Ryswyck
Thank you for visiting my blog. I’m a professional software developer since Y2K. A blogger since Y2K+5. Provider of training and coaching in XP practices. Curator of the Awesome Talks list. Past organizer of the European Virtual ALT.NET meetings. Thinking and learning about all kinds of technologies since forever.
Watch The Videos
February 2, 2022
December 15, 2021
October 7, 2021
June 22, 2021
April 23, 2021
- Behavior-Driven Development
- Concurrent Programming
- Continuous Integration
- Core Skills
- Design Patterns
- Domain-Driven Design
- Event Sourcing
- Fluent Interfaces
- Functional Programming
- Object-Relational Mapping
- Open Source
- Software Design
- Test-Driven Development
- Visual Studio
The opinions expressed on this blog are my own personal opinions. These do NOT represent anyone else’s view on the world in any way whatsoever.
Thank you for visiting my website. I’m a professional software developer since Y2K. A blogger since Y2K+5. Author of Writing Maintainable Unit Tests. Provider of training and coaching in XP practices. Curator of the Awesome Talks list. Thinking and learning about all kinds of technologies since forever.