Writing tests to cover most of your functionality after you've finished your project can be painful, trust me I know. However trying to maintain projects without the help of testing modules can be even more painful, tedious and annoying. We can all agree that it's much easier to fix a bug or add a feature to a project with full test coverage because we can rest assured that if our updates have caused or will cause any regression, there is a good chance that it will result in a number of failed tests. Writing tests has always been beneficial but equally hard to enforce on software engineers who are constantly pressured by the business side to deliver more and more quality features as fast as possible. This is where Test Driven Development and Behavior Driven Development come in to play. As software engineers, we DO understand the importance of testing and if we had ample time we WOULD love to create unit tests for some of the more sophisticated modules in our systems, but usually deadlines are too tight and the pressure to deliver upgrades faster than the competition often gets the better of us.
Test Driven Development
I'm sure that you've read in several blogs and posts that Test Driven Development can solve the problem I've mentioned by forcing the developer to design tests first and then produce the code satisfying the test requirements later. In Test Driven Development, the developer does not design the system module by module and then start the implementation of the features right away. In TDD the developer looks at the feature and translates it into a number of tests which would test the functionality of that feature. The tests are implemented first and are obviously expected to fail once they are implemented as the modules they are meant to be testing have no functionality yet. After the tests are ready, the modules are implemented and re tested until the tests are completely satisfied.
In TDD the following sequence of steps is usually followed:
- Understand the Feature
- Add a number of Tests
- Run all tests and see which ones have failed
- Implement the modules (write the code)
- Run Tests again
- Refactor Code
- Repeat
This sequence is often represented through the Red-Green-Refactor sequence as shown in the diagram below:
The red represents a failed tests, the Green Represents making the test pass through continous refactoring (blue). I will go through more detail about TDD including how to use it in future blogs however for the time being, in order to compare the differences between TDD and BDD it's very important to understand what TDD is and how it works.
Behavior Driven Development
The problem with TDD was that developers were focused too much on the design and technicalities of the system rather than the expected behavior by the user. Software engineers were having difficulty expressing the features into tests as this seemed unnatural to the traditional flow of software development. Very often the tests were asserting the quality of the system from a design and technical point of view but not from a behavioral perspective. This is the reason behind the evolution of Behaviour Driven Development. While TDD focuses on the functionality of the system, BDD specializes on the features within the system and whether the functionality results in the features requested by the user or not.
Web Developers are often sucked into the functionality and robustness of the system without putting the user's expectations at the core of the web site. Yes it's very important to make sure that your web site is robust and maintainable but tests should not just cover robustness and functionality, they should also test the behavior of the system which is what the customer is paying for at the end of the day. It is very easy for the behavior of the system to change slightly during a bug fix or an upgrade at the cost of the user's satisfaction which will ultimatly devalue your product.
While TDD is a development methodology, BDD is a Team methodology where the business are heavily involved in specifying the features in the form of a number of behavioral tests. The developer can then start engineering the modules which will eventually satisfy all the tests and guarantee that the expected system behavior is fully satisfied. In BDD the actual users or testers can create the Tests using frameworks such as 'MSpec' and 'SpecFlow'.
In TDD, it is common practice to express your tests in three A steps:
- Arrange
- Act
- Assert
On the other hand in BDD we express our tests in the following manner:
- Given 'x' number of steps
- When 'y' number of steps happen
- Do 'z' number of steps
TDD or BDD
It really depends on the team you're working with and the resources available to you. In big corporate companies, several teams are involved in the development of features. Product owners or Product managers can assist with the BDD process by defining the features using the frameworks we just mentioned. Developers can then build their code around these tests making sure all the requirements are fully satisfied. The BDD tests will eventually act as the specifications of the new features. However that does not mean that TDD should be put on the side. If you really want guaranteed quality within your project, you should still write several tests which will guarantee the functionality of your system. While analyzing the BDD specifications, experiences software engineers should be able to visualize the modules required within the systems and a TDD approach should be used when designing these specific modules.
A system featuring a high standard of quality should comprise of both types of tests. The users of the system should be able to express/comprehend the system using BDD frameworks, while the software developer should define his modules and functionality using TDD. At the end of the day, the right functionality should satisfy all the required features ensuring the user's satisfaction.
That's all from me for today. In the coming blogs I will go into more detail on which frameworks to use for both methodologies and we'll go through some examples together.
Until then, thanks for reading!
Shaun