What is BDD anyway?
Understand what BDD is, how is it used and how it helps with communication. Practice BDD on a real world example that you can showcase on your CV.
In the modern Software Development world, we have various stakeholders each with its own interest. In general, we can divide the stakeholders into 2 groups. The first group is the Internal stakeholders which include business owners, managers, and employees. Their main interest is to drive the company to success as they are directly involved in the running of the organization.
The other group is the External stakeholders. They are entities not within a business itself but who care about or are affected by its performance (e.g., clients, investors, suppliers, etc).
Now each individual group has its own vocabulary that they use in their everyday operations. Often there is a confusion of what actually needs to be done in order to keep all the stakeholders happy with each other.
For the business owners, the business needs being truly able to define the desired outcomes in terms of ROI. The employees especially the developers need to have a deep understanding of what needs to be built in order to fulfill the business needs and the users need to use the features in order to satisfy their needs.
In order to have a formal and verifiable way of checking that the business needs align with the actual application features, the Software Engineers, QA analysts and Engineering/Product Managers work together and create User stories.
A user story is a very high-level definition of a requirement, containing just enough information so that the developers can produce a reasonable estimate of the effort to implement it and test it.
This article will focus on the testing side of the user story. The purpose of testing is to ensure that the system that is built is working as expected. The main drive of this is the mere reality that software bugs are all over the place and due to the fact that fixing a bug that was not tested and found in production is almost 10x more costly compared to when it was found and fixed in development.
How we test software you say? Well, there are various approaches to testing. Let’s describe some of them.
There is the test-last approach where you write code first and then you write tests to verify that. You might have been writing code like that until now.
There is the test-first approach where you write tests first and then drive your code by making the tests pass. One application of this is Test Driven Development or TDD.
Of course, some would write no tests at all and rely only on QA testing.
Out of those ways to test we are interested in TDD. The primary disadvantages of writing code driven by tests are:
- When to test?
- What to test?
- How to know if a specification is met?
- Does the code deliver business value?
Overcoming those disadvantages is why BDD was born. But what exactly is BDD? Bear with me and we will find out by looking into some facts.
What are the Facts
Behavior driven development has nothing to do with testing.
Behavior-driven development, and it has nothing to do with testing. Testing is something you can’t do until the software exists. We write tests to verify that our assumptions work as expected. On the other hand, BDD is an approach or a different process to develop systems that are focused on delivering what the business actually needs while adhering to user requirements.
BDD helps communication within the team.
By providing a readable and understandable vocabulary BDD helps bridge the communication gap between clients, developers and other stakeholders. A shared language ensures everyone (technical or not) has enough understanding of the status of the project. This creates a collaborative environment that helps business and technical teams to create software with business value.
BDD is easy to start with.
Here is an example of a .feature_ file. We are using Cucumber in that case
Feature: Serve coffee Coffee should not be served until paid for Coffee should not be served until the button has been pressed If there is no coffee left then money should be refunded Scenario: Buy last coffee Given there are 1 coffees left in the machine And I have deposited 1$ When I press the coffee button Then I should be served a coffee
Here is another one with multiple input values to test:
Scenario Outline: eating Given there are <start> cucumbers When I eat <eat> cucumbers Then I should have <left> cucumbers Examples: | start | eat | left | | 12 | 5 | 7 | | 20 | 5 | 15 |
Instead of referring to “tests”, in BDD will use the terms “scenario” and “specification”.
In general BDD specifications answer the following questions:
- Where to start in the process
- What to test and what not to test
- How much to test in one go
- What to call the tests
- How to understand why a test fails
This type of DSL is very readable and portable and can be added as part of the development process in the user story tickets. That builds a documentation artifact that is accessible to all internal stakeholders which they can contribute.
OK enough theory lets code
The project is similar to this although you can use any framework you like. You are asked to build a simple GitHub viewer. Here is the main user story:
As a User I would like to have a Web application that connects to GitHubRest API and displays users from organizations. I need to be able to search for users and when I clicked on the user results I need to be able retrieve their repositories. Finally, I need to be able to click a repository so that all the commits are displayed in order. If the project has many commits I would likethe results to be paginated by 50 or 100 commits.
This could come from a friend or a customer so it’s important to analyze in detail what are the requirements of the application and what are the main features we need to develop.
So first things first you need to do those tasks:
- Read carefully the User story. Try to make note some keywords that map to actions. For example, connects means accessing or requesting the GitHub API using HTTP.
- Out of the actions, you noted down to write some simple scenarios for each one. For example:
Scenario: Search for user that exists Given I have visited the main page And I have focused on the search input When I enter a name of a user that exists And I press enter Then I should be able to retrieve the users repositories
- Try to think of edge cases or what can go wrong in your requests or responses. Write down those scenarios also.
- Create a Project on GitHub and install the required libraries. If you don’t want to w8 you can clone/fork this repo here. Add the scenarios you’ve written down as tickets using the built-in issue management.
- For each issue/task, you’ve raised write a .feature file and put it into the features folder. Make sure the file has a relevant name.
- Run your tests with Cucumber. They will all fail of course as you need to start implementing them!
- For each failing test implement the feature requirements. If at any point you think you missed something you can add more scenarios then. Repeat until you finish all the scenarios.
- While you are working on the tickets don’t forget to update the issue tracker.
- Extra Points: A tool that can help you with running tests is a Continuous Integration Tool or CI. What is a CI you say? That’s a topic for another article. I suggest you add Travis as its free and easy to use. The CI will run your tests after each commit and point you for errors.
- FINISHED: Congratulations. I hope you liked testing with BDD and understood a lot of it. Don’t forget to showcase your app to the world, add it to your LinkedIn Projects and also mention your awesome mentor.
Some links to help you for this task are:
- GitHub Developers API: For interfacing with GitHub API
- Cucumber.js: BDD tool
- Waffle Project Management: Project management tool Alternative to Git Issues.
- Mocha-Gherkin: If you want to use mocha and gherkin.
To sum up, the main idea behind BDD is that it’s driven to prevent communication gaps, that is having everyone in the team communicating more often, better and based on real world examples and not on abstract and imperative requirements. Thus we all end up with meaningful tests that are portable, easy to read and easy to verify.