Test-driven Development (TDD) in .NET
The Agile/XP notions of frequent releases and constant redesign can be worrying. There was a day, not far in the past, that code changes, any code changes, struck fear into the heart of a developer or project manager. In many cases this fear was justified. The majority of code was quite brittle and fragile. The smallest of changes could bring an application to a grinding halt. That’s why, when we’re doing things the Agile/XP way, we use Test-driven Development(TDD). As we destabilize the code with refactoring and destabilize the release process with continuous integration, we aim to compensate with TDD.
Constant redesign and constant releases requires constant testing. The three options are: the developer steps up their manual unit testing to include detailed functional tests every time they make a change, offload an enormous and continuous burden onto the QA team, or automate the core functional tests. Continuous change to the code is bound to break with only manual testing so test-driven development takes the third route: automating the core functional tests.
When developers began using testing frameworks such as NUnit to develop software, they found an interesting side effect. What began as a useful way to help ensure the robustness of the code during refactoring soon took on a life of it’s own: Test-driven development contributes to design an architecture decisions. As developers create tests they learn things about the architecture with hands-on firsthand use. It turns out that test-driven development counteracts the sometimes hands-off, almost academic way in which architecture can sometimes happen. Test-driven development doesn’t just test the code features and stories, it tests assumptions about the design as well.
Traditionally, unit testing was carried out by the developer during and after the development of a module. In a small organization, the developer was expected to make the application entirely production-ready. In a larger organization, a team of professional testers would take the module and subject it to the full rigor of automated and manual tests. This process would be particularly thorough when the application was first created. After the first release, however, the testing would be pared down to a set of regression tests, usually a much abbreviated set of tests. Many occasions would arise where even these would not be run before a new release.
Test-driven development reverses the traditional order and puts testing first. The developer, as she conceives of the program structure, creates tests which the code must pass. Pure test-driven development is done by writing the tests which fail before writing code to allow those tests to succeed.
Here’s one way to map the evolution of testing:
OLD – Software Life Cycle Development
Develop -> Release -> Formal Testing( QA)
NEW – Test-driven Development
Create Tests -> Develop Against Tests -> Tests Run Successfully
IN THE REAL WORLD – Test-driven Development
Create Some Tests -> Develop some code -> Create More Tests -> Develop Against Tests -> Tests Run Successfully -> Some Formal Testing(Unit Test and QA)
Test-driven Development(TDD) lowers the risk on fast-moving release cycles, making it a natural habit in Agile development.
How does .NET help?
- Unit Test Template(in VS)
- VSTest.Console.exe(replaces MSTest in VS 2012)
- ASP.NET MVC Framework
What are other useful tools?
For Testing – a useful comparison of options
For Mocking – a useful comparison of options
What is the effectiveness of TDD?
Test-driven development is highly effective for trivial code and code with few dependencies. Its effectiveness decreases with increased complexity and dependencies in the code. More here by Stevens Anderson.