Some years back we started to see the need to unit test our code. This practice is now universally accepted as an approach to improving the quality of software applications
It has been some time since we blogged about this, and over that time, we have embarked on a journey from our initial forays into unit testing, to our recent adoption of Behaviour Driven Development (BDD). Read our previous related blog post Improving the Quality of Software Systems through Automated and Unit Testing
Testing, testing …1…2….3……
The first step on this journey was to change how we wrote code to make it easier, or in some cases even possible, to unit test. This involved adopting certain test friendly patterns, such as dependency injection. Initially we carried on with writing code up front adding unit tests after the fact. Our metric was code coverage with a percentage set at > 85% for most projects. We saw benefits to unit tests in some cases, but we also began to see that coverage alone wasn’t a meaningful metric. For starters there were cases where developers would achieve coverage with tests that added little real value.
A Move to Test Driven Development
In an effort to keep improving our approach to unit testing, our next step was a move to Test Driven Development (TDD). This technique involved writing the tests before the code to implement the requirement. So now our coding ran in the following
- Write a test for the feature to be implemented
- As the test is added before the feature has been implemented, it will fail
- Check the test fails, if it does not it has no value
- Implement the feature
- Check that the test passes
- Refactor – with passing tests in place the implementation can be “tidied up”
- Repeat the process until all features have been implemented.
We found that the key to this approach was to keep it simple taking straight forward verifiable steps. This approach led to higher quality of tests and we began to see a greater return for our effort. We started to see the kind of improvements promised by unit testing i.e.
- Safer refactoring
- Fewer regression bugs
- Code is well structured as thought is given to how it will be tested before it is written
- Writing tests first gives a clearer understanding of what is required by the code
- Tests act as a true picture of how the code currently works
- Debugging time is reduced
- Implementation does what it is meant to do and no more
- Bugs found and fixed sooner
But we still found that there were problems. Small iterations of the test and development cycle seemed to lead to a lot of refactoring which began to feel unwieldy as the code base grew over the lifecycle of a project. Sometimes it was difficult for the developer to know what or how much needed to be tested. We became too focused on “how” when writing tests. Tests were written that ensured that the system did what it did, but was the system doing the right thing? Sometimes there could be disconnect between the test and the feature which led to passing tests but for a feature that was not quite what was required.
In general we were also were looking to improve how we document code, our visibility of team progress and our planning and estimation.
It all led us to Behaviour Driven Development
All of this led us to BDD - our current approach to unit testing. BDD gave us the benefits of Test Driven Development but in a more focused way. BDD is basically a feature driven approach to TDD. The benefits of BDD helped us meet some of the challenges outlined above and can be summarised as:
- A shift in focus to what the system should do.
- Improved communication between development team and business/customer
- Features tied directly to code that is written
- Choice as to which tests to write is made based on the scenario rather than just driven by developer
- Code is truly self-documenting
- Easier to break down, therefore:
- easier to estimate
- easier to be agile
- Easier for new developers on project to get up to speed
- More visibility into team progress and status
Early Days for Early Adopters
It’s still early days for BDD and especially for BDD at Dataworks. We’ve carved out our own approach. There is still a lot of debate and different approaches out there. Some of the tooling is geared more towards acceptance testing but our current approach is more aligned with integration testing.
There are also test scenarios that fall outside of BDD:
- A level above BDD, acceptance testing. Here we take two approaches
- Manual acceptance testing, this is sometimes the best approach particularly in regulated environments
- Automated acceptance tests (we are evaluating Coded UI for this purpose) for the pieces of the UI which are not tested by our BDD tests
- A level below BDD
- If the application has very complex business rules, there may be a case for writing traditional unit tests at the business model level to test particular scenarios
- In this case we use Moq for mocking
So that’s our journey to date. We hope to keep learning, and keep improving in this area with the ultimate goal of continuing to provide our customers with the highest quality software solution possible.
At Dataworks we enable the perfect hybrid of configurable off the shelf toolsets and custom software development to deliver innovative solutions to match your specific business process requirements. This ensures we are the best at what we do.
If you would like to discuss how we can use our experience and expertise to deliver real benefits toyour business please contact us today on 051 878555 or email firstname.lastname@example.org
- Back to Blogs