Beginning BDD with Django - Part One
Part one of a two-part tutorial on Behaviour Driven Development. In this part we scope and write a Gherkin feature file.
For the last year I’ve been learning Django by building Connect. Part of this journey has been to explore various automated testing methods and tools. Behaviour Driven Development (BDD) is one technique that really spoke to me and was surprisingly simple to integrate into my application.
This article is the first of two parts that aim to pass on what I have learnt so far. It is not an in-depth exploration of the philosophy or best-practice application of BDD, but rather a highly practical example to get you started.
By the end of both articles, I hope you will be able to answer the following questions:
- Why should I consider using BDD?
- What are the key concepts?
- How can I use it to test my app?
Let’s do it!
Contents
Why BDD
I’m not going to go into why you should test your application. I assume that by reading this article you’re already sold on the benefits of testing. Instead I’m going to focus on why you should specifically consider BDD for your next app.
To do this, we need to step back and ask ourselves why are we building software in the first place and how we can assess the success of our application.
In a great talk titled building the minimum badass user, Kathy Sierra argues that a successful application is one that people want to use and tell their friends about. The key to delivering this? Making our user awesome:
“People aren’t using the app because they like the app or they like you. They’re doing it because they like themselves.”
Kathy argues that users will endure less than perfect design, or technical implementation if the app makes them more awesome at the task at hand.
For developers, the key take-away is that we need to be constantly thinking about how we can empower our users.
How BDD Can Help
BDD sits at the cusp of user experience and development, as it forces us to frame the software we’re developing in the context of the user.
It helps us step back from the technical implementation and focus on these questions:
- Who am I?
- What can I do?
- What benefits can I derive from my action?
A common template for defining this is:
This template also accounts for scenarios where the role is not a user, but rather a system or process (for example, an API).
An Example
To illustrate how we can transition from user-centered design thinking to writing test code and developing our application, we’re going to walk through an example from Connect; a social application that helps users connect with each other based on common interests and location.
Let’s imagine that we’ve built most of the app, but are yet to develop one of the most important features: filtering users by interests.
Using the pattern defined earlier, we might describe this feature as:
Feature Files
BDD can be segmented into two parts: the feature file, where we describe the behaviour we are going to build, and the code (in our case Python) where we test our application.
First we’ll need to write our feature file. Feature files use the Gherkin syntax and are saved as <featurename>.feature
:
example.feature
Lines 1-3: Defining the Feature
Technically, only the feature name is required here.
However, I also like to describe the feature using the As a, I want, So that
pattern established earlier.
This keeps our user’s needs front of mind.
Lines 5-7: Setting Up the Background
A feature’s Background
outlines the contextual information we need for the scenarios that follow.
For our example, we’re going to need Interests
and Users
in the database so we can filter our users.
Not all features will require a background, so this section is entirely optional.
Lines 9-12: Writing Scenarios
Finally, we outline the different scenarios our users might face.
For our example, we need to consider what will happen when the user filters by one, or multiple interests. We also need to account for when there are no users that match the request.
Each Scenario contains three types of steps:
Given
: Defines the state of the systemWhen
: Defines the action the user or system wants to takeThen
: Defines the outcome of the action
More complex scenarios can also include And
or But
keywords. For example:
activate_account.feature
Putting It All Together
Here’s our filter users
feature written as a Gherkin feature file:
filter_users.feature
Refactoring
You’ve probably noticed that our scenarios use a common pattern. They’re also a little vague.
To fix this we can include more context in our Background
and refactor our three scenarios into one Scenario Outline
:
filter_users.feature
First we define the interests and users in the background using tables. This makes our data easy to read, whilst providing hooks that we’ll use later in our Python code.
Next, we compile our scenarios into one Scenario Outline
, specifying the skills and number of users based on the information defined in our new Background
.
When we run our tests, a Scenario
will be created out of each (non heading) line in the example table. So, the first line would become…
… and so on.
Conclusion
That’s it! We’ve defined our feature and written our feature file!
In the next post we’ll explore how we can write Python code to utilise our feature file and run it as an automated test.