Tips & Tricks Tutorials

Upgrade Your Testing with Behavior-Driven Development

BDD? Why should I care?

Back in the day, I used to write terrible code. I’m probably not the only one who started out writing terrible PHP scripts in high school that just got the job done. For me, the moment that I started to write better code was the moment that I discovered unit testing. Testing forced me to properly organize my code, and keep classes simple enough that testing them in isolation would be possible. Behavior-Driven Development (BDD) testing has the potential to do the same at a program level rather than individual classes.

A common problem when making software is that different people have different opinions on what the software should do, and these differences only become apparent when someone is disappointed in the end. This is why in large software projects, it’s commonplace to spend quite a bit of effort getting the requirements right.

If you’re making a small personal project, BDD can help you by forcing you to write down what you want your program to do before you start programming. I speak from experience when I say this helps you finish your projects. Furthermore, in contrast to regular unit testing you get separation of concerns between your test scenario and your test code. What programmer doesn’t become excited about separation of concerns? This one sure does 😀

The real value of BDD arises for those of you who do contract work for small businesses, and even those with small to medium-sized open source projects, wouldn’t it be useful to have a simple way to communicate exactly what the software should do to everyone involved?

Okay, so how do I get better software?

Behavior-driven development is just that: development which is driven by the behavior you want from your code. Those of you who do Agile probably know the “As a <user>, I want <behavior>, so that <benefit>” template. In BDD, a similar template is proposed: “In order to <benefit>, as a <user>, I want <behavior>”. In this template the goal of your feature is emphasized, so let’s do some truth in advertising here:

In order to show off PyCharm’s cool support for BDD

As a Product Marketing Manager at JetBrains

I want to make a reasonably complex example project that shows how BDD works

This is still rather vague, so let’s come up with an actual example project:

Feature: Simulate a basic car

To show off how BDD works, let’s create a sample project which takes the  classic OO car example, and supercharges it. 

The car should take into account: engine power, basic aerodynamics, rolling  resistance, grip, and brake force.

To keep things somewhat simple, the engine will supply constant power (this is not realistic, as it results in infinite Torque at zero RPM)

A key element of BDD is using examples to illustrate the features, so let’s write an example:


Scenario: The car should be able to brake

The UK highway code says that worst case scenario we need to stop from 60 mph (27 m/s) in 73 m

Given that the car is moving at 27 m/s

When I brake at 100% force

And 10 seconds pass

Then I should have traveled less than 73 meters


By writing this example, it becomes clear that our code will need to be aware of time passing, keep track of the car’s speed, distance traveled, and the amount of braking that is applied at a given point in time.

If you have complex examples, or want to check a couple of similar examples, you can use ASCII tables in your feature file to do this. To keep this blog post to a reasonable length, I won’t discuss those, but you can check the code on GitHub to see an example, or read more in the behave docs.

Feature files and steps

In BDD, you first write a feature file which describes the feature, with examples that outline how the feature is supposed to behave in certain cases. Using BDD tools, you should then be able to test the scenarios in these feature files automatically.

To make the scenarios testable, they need to be structured in a specific way:

Given a precondition

When an action

Then a postcondition

So let’s take our feature from above, add some scenarios, and create a feature file which we will put in a ‘features’ directory in our project. As always, you can follow along with the code on GitHub.

Most BDD tools also support starting a sentence in the scenario with ‘And’ which will behave the same way as the sentence before it, so ‘Given, And’ will behave just like ‘Given, Given’.

Next you define steps in code, which execute the test. For this, we need a BDD tool. In Python a good choice of tool is behave. An important note here, the newest version of Behave at the time of writing (Behave 1.2.5) is not compatible with Python 3.6, so please use Python 3.5!

If you’re a pytest user, you may want to give pytest-bdd a shot: check out our blog post on pytest-bdd.

If at this point we run behave, it will detect our feature and scenarios, but tell us that all of our steps are still undefined. So let’s have a look at how we can make the scenario testable. Let’s implement the “car should be able to brake” scenario:

@given("that the car is moving at (?P<speed>\d+) m/s")
def step_impl(context, speed): = float(speed)

@when("I brake at (?P<brake_force>\d+)% force")
def step_impl(context, brake_force):

@step("(?P<seconds>\d+) seconds? pass(?:es)?")
def step_impl(context, seconds):

@then("I should have traveled less than (?P<distance>\d+) meters")
def step_impl(context, distance):
  assert_that(, less_than(float(distance)))

This code goes into a file in the /features/steps folder. By writing the test code first you’re forced to think about what you would like your eventual application code to look like. Also note that we’re using PyHamcrest (a library which provides better matchers between expected and actual values) here to define the assertions, as they give us a lot more helpful error messages than regular assertions when they fail.

Running Behave Tests

To run our Behave tests in PyCharm, we need to add a Behave run configuration. To do this, just add a run configuration like any other, but select Behave:

Add behave run configuration


You don’t need to configure anything else. If you run behave without specifying anything, Behave will execute all the feature files in your project. So let’s run it:

All tests fail

We can see that our feature is tested, using all of the scenarios that we’ve defined for our feature. As we haven’t written any code yet, all tests fail, and everything is red 🙁 So let’s write some code and see what it looks like after we finish:

All tests pass

Much better, right? Now let’s say we made a mistake, for example, if we forgot the deltaT term when adding the acceleration to the car’s speed, we will see that the acceleration tests fail. Of course PyCharm makes it easy for us to put a breakpoint in the code, and then debug our test:

Debug a test

To Conclude

BDD is a tool which has the potential to make your software better. This blog post was a very short introduction, and I hope it’s been enough to get some of you interested in giving it a shot! Please let me know in the comments if you’d like to read more about BDD in the future.

Comments below can no longer be edited.

7 Responses to Upgrade Your Testing with Behavior-Driven Development

  1. Avatar

    Jake Peters says:

    September 13, 2017

    Great article! Loved the part where you walked through it and went through the features of BDD. We too did a blog on BDD, its here to view if you would like! –

  2. Avatar

    John Kroubalkian says:

    October 26, 2017

    Nice article. You mentioned that
    An important note here, the newest version of Behave at the time of writing (Behave 1.2.5) is not compatible with Python 3.6, so please use Python 3.5!

    Can you provide a url that describes this incompatibility? I was unable to locate it from the Python Behave module page.

    Thanks again

    • Avatar

      Ernst Haagsman says:

      November 2, 2017

      See here:

      • Avatar

        John Kroubalkian says:

        November 19, 2017

        Thank you Ernst.

        I was able to use python 3.6 with `behave==1.2.6.dev0` by:

        * activating my virtualenv
        * `pip install git+`

  3. Avatar

    Shai Kubitsky says:

    December 11, 2017

    We have been using Behave for a few years now and PyCharm supports it very nicely. We decided to try another BDD tool, mostly because Behave hasn’t been very active – their last release, 1.2.5, is almost 3 years old.
    We’re trying PyTest-BDD and I wondered if PyCharm is planning to support it as well

    • Avatar

      Paul Everitt says:

      July 5, 2018

      The latest EAPs provide pytest-bdd support.

    • Avatar

      Peter Bittner says:

      August 14, 2018

      I’m sorry, Shai, that you have the impression that the Behave project is not very active. The opposite is actually true. Look at the commit log on GitHub and convince yourself that there is not a single month in the last couple of years that hasn’t seen at least a few commits.

      What is true, though, is that there are few releases. Jens Engel, the core maintainer, needs to maintain the project stable for all supported platforms, and Microsoft Windows has proven to be the most headache (I’ve been told).

      Interestingly, I think I’ve predicted saying to Jens that this would happen: Users will start to have the impression that the project is stalled, only because we have too few releases. Unfortunately, I was right.

Discover more