Using BDD for good
By: Alex Ivanova
Tags: Testing, Codeception, Bdd, QA, Engineering

How complicated would it be for you to explain to a 3-year-old child how the web browser works? The same challenge applies to software development as the client domain can be pretty difficult to understand.

We need examples to understand what the client needs. Working with real-world examples helps us to communicate better because we’re able to relate to the problem more easily. To do that, we can use a method called Behavior Driven Development (aka BDD).

Using BDD to create the examples is amazing!

It’s amazing because it turns human scenarios into tests. Behavior Driven Development encourages exploration and debate in order to formalize the examples describing the requirements for the features that need to be implemented. It is a common language for all team members to use during the development process so you can check that the examples make sense to everyone in the team.

Ok. So how do we do this?

We describe a specific feature of an application, with a set of scenarios and examples describing this feature.

The feature file is written in a Gherkin format. Basically Gherkin is a plain-text language with a little extra structure. Each sentence is then connected to a set of instructions in your automation code that needs to be executed in order to complete the step.

The idea of a BDD test can be narrowed down to:

describe a feature in scenarios using a formal text

use examples to make abstract things concrete

write actual code implementing each step of the scenario

In our examples here we’re going to use Codeception but you are free to use any BDD framework that suits your technology stack. Codeception can generate a feature file for you. We can place our feature files in a bdd directory and create a search feature file:

codecept generate:feature bdd search

This template can be fulfilled by setting actor and goals:

As a(n) actor

I want to do a certain action

In order to achieve a certain goal

In our example, we are going to use the search feature on the OpenClassrooms.com website.

Feature: Search

As a visitor

I want to search for paths

In order to find the one that I am interested in

We now need to write the scenario that we are going to use for our automation. Scenarios are written in a step-by-step manner using the Given-When-Then approach.

Here is the template for writing BDD test cases

Given a certain scenario

When an action takes place

Then this should be the outcome

Continuing on our example we can write a scenario that looks like this:

Scenario Outline: Visitor can find a path

Given I am a visitor

When I am on the "search" page

And I filter by <category>

And I search by <keyword>

Then I see the correct <path> Examples:

| category | keyword | path |

| "paths" | "dev" | "Web Developer" |

| "paths" | "ai" | "AI Engineer" |

Here we are using an advanced technique where by using a Scenario Outline we can set up Examples in order to run our test multiple times with different parameters. The values are replaced with the placeholders <category> , <keyword> and <result> , which are filled by the Examples table. Each set of values is executed as a different test.

In Codeception we can test this scenario by executing it in dry-run mode:

codecept dry-run bdd search.feature

We should now define the scenario steps easily by executing:

codecept gherkin:snippets bdd

To match steps from a feature file to PHP code we use annotations which are then added to methods. Steps can also be matched with regex expressions and parameters can also be passed in non-regex strings using the : params placeholder.

Here is an example using the steps defined in our scenario:

/**

* @Given I am a visitor

*/ /**

* @When I am on the :page page

*/ /**

* @When I filter by :category

*/ /**

* @When I search by :keyword

*/ /**

* @Then I should see the correct :path

*/

Steps are defined in Context files. The default context is an actor class, i.e. for the bdd testing suite, the context is BddTester class. You can define the context in a bdd.suite.yml file like so:

gherkin:

contexts:

default:

— BddTester

We then connected the annotations to pre-existing methods in our automation framework based on Codeception. Re-using existing code is always great 👍

Here are a couple of examples:

/**

* @Given I am a visitor

*/

public function iAmAVisitor()

{

$this->setLocale('en');

} /**

* @When I am on the :page page

*/

public function iAmOnThePage($page)

{

$this->amOnPage($page);

} /**

* @When I filter by :category

*/

public function iFilterByCategory($category = 'all')

{

$this->searchPage->addCategoryFilter($category);

}

Photo by Paul Hanaoka

How specific should we get?

There is a big debate on what exactly should a BDD test look like. The question is how detailed it should be in order to be specific, yet understandable. We also want it to be useful to everyone.

Based on my experience, whether you’re using BDD as a sole solution for creating your test automation framework or you’re using it in only a few end-to-end tests, it is better to make your steps as readable as possible. For the most part, this means being less specific and getting into the details only in your methods (back in the code base of your automation) but not in your BDD feature files.

At OpenClassrooms we use BDD to create some long end-to-end scenarios. While keeping shorter and more specific tests using pure Codeception framework. Some examples of end-to-end tests on our platform include:

Visitor can sign up and become a self-paid student.

Student can get their projects validated and finish their path.

Mentor can create a mentorship session and evaluate their student’s progress.

Assessor can create a presentation sessions and evaluate student’s project.

Admin can create a new course.

To BDD or not to BDD?

Making the decision how many of your test cases to create using this approach is very subjective. So far in OpenClassrooms we are still experimenting and trying to figure out just how many of them we are going to need. We started by creating 10 end-to-end BDD test cases and in the process, we’ll find out just how useful they’re going to be for our team.



Testing just what’s useful takes nuance and experience. There is a lot of subtlety in figuring out what’s worth testing and what’s worth automating. Using BDD can be a double-edged sword and you need to be careful! Always have in mind what your goal is, what you’re gaining by using this approach, what you’re sacrificing and most of all.. do your own experiments and introduce BDD gradually to your workflow.

Benefits of using BDD

It can reach a wider audience. Promotes better communication between members of the team. Defines acceptance criteria prior to development.

Disadvantages of BDD

If the requirements are not properly specified BDD may not be effective. Testers using BDD need to have sufficient technical skills. It is less flexible than pure code. It adds additional complexity to your framework.

Summary

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 requirements.

I know it’s not a magic bullet but I’m really hopeful it will improve the requirements gathering and testability of our application.

PS

I created an example code available on GitHub for the purpose of this article. It contains the code shown here.

For more information on setting up your own BDD automation framework with Codeception, you can go to the BDD Codeception documentation.

For more information on the paths and courses available on the OpenClassroms platform, you can search for your favorite topics at the OpenClassrooms search page.