A major insurance client was undertaking the development of a new quoting application. The new platform was expected to have a lifetime of 15 years with ongoing and numerous enhancements.
A traditional design, build and test development methodology was generating an unmanageable number of defects and an unpredictable schedule. Traditional testing was prone to long regression testing cycles and a high defect density. The regression testing duration was difficult to estimate and required a large team to execute.
- The time between defect creation and fix was too long – and defects found later in the development cycle are much more expensive to fix than those detected early in the cycle.
- Far too many defects were finding their way to production.
- Small, seemingly simple code changes would take too long due to a lack of confidence in avoiding unintended side effects.
The client recognized that, once in production, the resources required to “keep the lights on” would materially affect the amount of money that could be spent enhancing and expanding the quoting systems functionality. A more sophisticated Test Driven Development (TDD) approach was the solution.
TDD is a software engineering ‘best practice’ where development teams write following a RED-GREEN-REFACTOR workflow:
- RED – The developer writes a failing test essentially capturing the requirements in a test
- GREEN – The developer implements the business functionality, writing just enough code to pass the test
- REFACTOR – The developer refines and improves the code without adding new functionality.
While TDD results in good test coverage and a lasting regression test suite, it is also a software design and development technique that results in easy-to-maintain, loosely coupled software.
Centric implemented and trained the project team on TDD techniques and tools for Unit and Integration Testing. Pair programming was used to match experienced TDD developers with those new to the practice. Our teams leveraged continuous integration to provide rapid feedback and detection code defects and to automate the application build process. A closer look at the implemented TDD process is provided below:
- The developer writes a failing test, writes the code to pass the test and refactors as necessary.
- Once the developer completes the business features, all necessary unit or integration tests are executed.
- A peer code review is performed starting with the tests. This review process helps ensure that no requirements were overlooked and the code meets the team’s design standards.
- The code is then committed to the source control management system and is merged into the code base.
- The continuous integration server detects the code commit and begins its compilation workflow:
- The latest source is retrieved and compiled from the source control management system.
- All Unit and Integration tests are executed and the results are published.
- The compiled source is deployed to a development/staging area.
- Finally, to make the overall process transparent and visible, a custom-built dashboard displays the results of the entire process, giving the development team immediate visibility into build quality.
The client predominantly worked with the Microsoft .NET Framework utilizing Team Foundation Server (TFS). TFS fills the Source Control Management (SCM), Continuous Integration (CI) and Work Item Tracking roles. The TDD toolset needed to be compatible with .NET and TFS’s SCM and CI tools.
While Microsoft has a Unit Testing framework (MSTEST), the assertion patterns are not widely used outside of their ecosystem. There are two dominant and community supported TDD test writing styles, xUnit and Behavior Driven Development (BDD). The client already had some experience unit testing using both patterns so developers could choose the pattern to use case-by-case. NUnit was chosen for the xUnit style tests and MSpec for the BDD style tests. Both NUnit and MSpec have solid .NET implementations and were compatible with TFS and broad community support.
After implementing TDD, the client experienced a transformation that resulted in the following benefits:
- Code Coverage – There are more than 15,000 coded Integration and Unit tests executed every time new code is committed Defects for well-tested features are found soon after they are created. New code written has close to 80 percent code coverage. Existing code tests are continually updated and maintained, expanding the 80 percent code coverage goal.
- Fewer Defects – Our client’s historic code promotion process did a great job of capturing production defects. Comparing traditional development efforts with the new TDD powered effort has resulted in a much lower number of defects making it into production.
- Culture – The transparency of the build and code review process has created a culture of ownership. Developers go to great lengths to not be the person that “breaks the build.” Also, knowing that their work product will come under peer scrutiny more time has been spent in design resulting in a better product.
- Productivity – Productivity enhancements have been numerous:
- Because one side-effect of TDD is a solid set of regression tests, developers are refactoring with confidence knowing that if they create new defects they will be caught the next time the test suite is executed. Team members also know that if there are unintended side effects of their code it will be found quickly.
- TDD done right improves the design. Well-designed software is easier to modify and maintain. And for this client, TDD has actually helped reduce the Agile team’s average cycle time of completing feature cards.
- Developers do not have to “site-read” the code to define the intent as the intent is easy to read from the tests.
- New team members are productive earlier as their mistakes can be exposed via the test suite. Also, it is easier to mentor the new team member via examination of their tests.
Interested in learning how we can help your organization apply an Agile Approach that works?