Test-driven development
Test-driven development, or TDD, is the technique of writing test cases before writing the code that will need testing.
A test case is a formal specification of the inputs, execution conditions, testing procedure, and expected results for a single testing objective. Test cases help ensure that your testing is methodical.
In test-driven development, software requirements are first transformed into test cases. When following a TDD approach, you'll consider all possible scenarios first, write down the facts that are involved in those scenarios in the form of tests, and then implement the solution in the code that will make the tests pass.
TDD is designed to:
Encourage you to think through your code design.
Create a healthy development environment.
Keep you focused.
Validate code automatically.
Maintain high standards.
Let's have a look at how it works in practice.
Apply TTD with the red-green-refactor cycle
TDD relies on the red-green-refactor cycle. This method consists of three phases that are repeated continuously: red, green, and refactor.
Let’s look at them more closely:
Red: The first phase is writing a test. Since at the moment of writing, the corresponding code that supports the tested functionality does not exist, the test is destined to fail. Therefore, it gets marked red. 🛑
Green: The second phase is writing the production code - the intended functionality that will correspond to the test. Here, less attention is paid to the elegance of the solution. The primary focus at this moment is to pass the test and turn it green! ✅
Refactor: The next phase is to refactor both the code and the tests. The goal here is to pay attention to the contents and find ways to make improvements. 🚀
If a new functionality comes into the system, this approach allows you to think of a new set of tests to be written (again, starting in red, or not passing) and later write the code that will support the new features. This results in new code built on top of previous specifications that lives well with other new, emerging code.
As a good practice, if a bug is identified out of the test suite during development or production, it's recommended to analyze it, write a test for it, reproduce it (starting in red, or revealing the bug to the test suite), and then fixing it, making all the code go green again.
A huge advantage to following the red-green-refactor cycle is that you only refactor in the green - after the test has passed and the function is working! Any possibility of breaking functionality while implementing "clever" solutions will impact the test result - it will turn red, which will keep you alert at all times and force you to make sure all improvements are still valid! Overall, this method allows you to make your code more performant, legible, and extensible, making sure that you don't introduce side effects or bugs that could bring your system down in production.
Behavior-driven development
Behavior-driven development, or BDD, combines the general TDD approach with a user story, organization-oriented, and documentation-orientated approach. It allows you to skip the code and focus on scenarios in simple text manner. It also improves the communication between the stakeholders of the project so that each feature is correctly understood by all members of the team before development process starts. This helps to identify key scenarios for each story and also to eradicate ambiguities from requirements.
Gherkin syntax
BDD relies on Gherkin syntax, which is a guided format for writing specifications through example scenarios. The format has three components: "Given-When-Then." For example:
Scenario: Transfer 75 of 100 dollars out of an account.
Given the customer has logged into the account
And the balance is shown to be 100 dollars
When the customer transfers 75 dollars to another account
Then the new current account balance should be 25 dollars
This concrete, standardized syntax allows you to provide functional documentation, involving user roles, scenarios, conditions, and expectations. This is communicated between the people involved in the development of the software, including developers, product owners, quality assurance personnel, and business analysts. This way, they don't depend solely on the development team to delimit the scenarios for a problem to be resolved.
SpecFlow, aka "Cucumber.NET"
Cucumber is a software tool that runs automated acceptance tests in BDD using Gherkin syntax. SpecFlow is Cucumber for .NET. It is an open source tool that facilitates behavior-driven development, fully compatible with Visual Studio. With SpecFlow, you can create documents in Gherkin syntax, commonly named as "feature files," and integrate them with Visual Studio with rich UI options and regular-expression support, as well as other features including reverse-engineer and coding features like tables, parameters, and more.
Choosing between TDD and BDD
In most cases, you can use either TDD or BDD, depending on your testing strategy, the way the requirements are translated into documentation, the different scenarios that the software will support, and the results that it should get for final users.
Lots of software companies apply TDD as a default for making sure the developers follow a think-twice-before-you-code strategy. The common approach is to focus on scenarios and non-typical situations to write even the first lines of code, collect requirements from the business owners, and document them for future reference. In common TDD environments, you, as a developer, will be in charge of the code and how it works. You will need to bring questions and concerns to business personnel so you can make the software more extensible.
As you get more experience with TDD, you may extend your testing approach to BDD. The decision will rely on your organization's needs and how specifications are handled.
Let's recap!
Test-driven development, or TDD, is a standardized set of practices for developing software based on the red-green-refactor cycle. You write the tests first, starting in red, and transition to green as you complete the code and make the tests pass. Following the "timely" principle from the previous chapter, always write code that gets covered by unit testing.
Behavior-driven development, or BDD, is a code-agnostic approach that allows you to focus on the scenarios of the system in pure, simple text, which can later be used by developers to make the software work as expected. Following a BDD approach includes writing specifications using Gherkin syntax, or Given-When-Then scenarios, to collaborate with other members on your team. For .NET based apps, you can use SpecFlow (Cucumber .NET) to compose, generate, and integrate Gherkin-based scenarios.