Define Success with Test-Driven Development

Test-driven development peaks when you are defining what success means. By driving solutions through tests written before implementations, software teams can build the right software that solves problems in a domain. This forces teams to clarify and refine their understanding of how the domain should operate.

What does success mean? The answer to this must be clear when starting a feature development. Typically, requirements of a story could define success. Requirements define how a screen should look, what interactions a user should experience, or whatever example is out there. Success is meeting some set of clearly defined criteria

Defining success is at the core of the test-driven development methodology. The value of writing tests before implementation is to provide clarity on these requirements. Requirements do not map directly to the code already written. Rather, requirements are the basis for test cases that should be written. Those test cases, then, help drive the implementation.

Best Practices for Defining Success

What can a developer do to define success using test-driven development? First, a developer must understand the requirements of a story. Without understanding what a feature should do, it’s going to be impossible to start writing a test before implementation. If requirements need clarification before even starting a feature, maybe a spike is necessary to explore the problem space. Code developed from the spike shouldn’t be wrapped in tests afterward. Rather, requirements should be recorded in the story, and the test-driven development process can begin.

Now with clear requirements gathered, a developer should write test cases using the wording of those requirements. Test cases must be framed in the same language as these requirements. There are a few benefits to this. First, a developer can easily start with a test without knowing what the implementation looks like. Secondly, the test descriptions will naturally become the documentation for the codebase. Over time, as more requirements are mapped to test cases, the test suite will become the culmination of all the story requirements.

If a developer writes new edge cases that did not come up in the story requirements, the developer should update the story with new details. This allows stakeholders and subject matter experts to review the new requirements or clarify questions that the development process produces. The more tests the developer writes, the further they clarify what it means for a feature to be finished.

Benefits

With the mindset of continually defining success through test-driven development, software teams can reap many benefits.

First, using test-driven development helps keep the language consistent throughout the documentation, user stories, and code. This lowers the communication barriers between developers and subject matter experts when discussing the details of new functionality. With everyone using the same language, developers will write code that reflects the intentions of the subject matter expert that defines the feature set.

Second, tests are naturally decoupled from implementation details. Test cases should be built around actual behavior. It matters less what the implementation is that drives the behavior. Because tests are defining what business rules should be applied, developers are free to refactor the entire implementation and check if business rules fail. This property doesn’t hold for test suites written after the implementation. These types of tests tend to have the opposite effect: calcifying the implementation details. If refactors become painful due to the number of tests you need to update, consider refining your testing strategy to focus on defining business requirements.

Defining Success with Test-Driven Development

Building software that does the right thing is tricky. It requires constant iteration of business rules. Using test-driven development as a mechanism for defining success for the software, in turn, also defines success for the domain you are working in.