Behavior Driven Development (BDD): Value Through Collaboration (Part 4: Automation)

This post is part of the “Behavior Driven Development (BDD): Value Through Collaboration” series.

Automation

medium_8127187751The first 3 posts explored the process to define project requirements as behaviors. Once you have mastered writing BDD stories you are ready to start the journey towards the automation of scenarios.

Execution of BDD scenarios can be accomplished using many different frameworks. Some of them are JBehave (Java),  Cucumber (Ruby), RSpec (Ruby), SpecFlow (.Net), and Jasmine (JavaScript). This post will use examples from JBehave. With slight modifications, they can be applied to any other framework. The above-mentioned frameworks provide installation instructions and documentation on how to write code that supports BDD. This article focuses mostly on the best practice and ways to avoid some of the common pitfalls. For detailed installation instructions and documentation, please consult the website of the selected framework.

Decision on which framework to choose should be based on which technology your team is most comfortable with, as well as the support it provides for the implementation of the phases described below. Next post in this series will provide comparison of different BDD frameworks.

Successful implementation of the BDD automation should be done in three phases.

  1. Create library of normalized steps.
  2. Combine steps into composites.
  3. Empower scenarios with examples tables.

You should start with the first phase. As soon as enough steps have been created to support the first scenario, you can start with execution of the other two phases. From there on, work on all three phases should be done in parallel.

Phase #1: Create library of normalized steps

There are several things to bear in mind when creating the library of normalized steps.

Separate the scenarios from the code

If BDD is used to its full potential, everyone working on the project (business stakeholders, developers, testers, etc) should be able to use stories. Some frameworks, like Jasmine, have BDD steps mixed in with the code implementation. For the purpose of using BDD as a substitute for unit testing, this approach works well. However, if non-coders are to be involved, clearer separation is needed. Other frameworks like JBehave provide that separation. Stories are written in the plain text format and each step is tied to one method. The main job of BDD frameworks is to make a match between the step text and the corresponding code. For example:

[Java code]
...
@When("user clicks the $id button")
public final void clickButton(final String id) {
  // Code that clicks the button with specified ID
}
...

[BDD story]
...
When the user clicks the login button
...

This allows us to write stories without programming skills and they can be understood by anyone. When working on scenarios, all you need is to write given, when and then steps.

Build the steps library

It can be very time-consuming to write code for every single step someone writes in scenarios. In most cases, the number of different actions or verifications that can be done in an application is limited. For example, in Web applications you can click an element, verify that the value of an element is as expected, select a drop-down list option, etc. These steps can be created in advance and used when writing scenarios.

One suggested approach is to create a separate class for each type of application developed within the company. There can be a separate class for Web steps, database steps, API steps, operations steps, etc. All these classes should be part of one common class containing steps that can be used by each of these applications as well as helper methods. Later on, if different products use the same application type, there might be the need for steps specific to that product. In that case, more classes should be created and they should extend the class created for that application type.

An example class structure could look something like this:

CommonSteps - WebSteps        - MyWebSiteSteps
                              - BackOfficeSteps
            - DatabaseSteps   - OracleSteps
                              - MySQLSteps
                              - DB2Steps
            - APISteps        - JSONSteps
                              - WebServiceSteps
            - OperationsSteps - ShellSteps
                              - WindowsSteps
                              - TelnetSteps

Following the same example, CommonSteps would have steps and methods that handle the declaration of variables, logging, setup, and teardown, etc. WebSteps would have steps that provide actions to click different web elements, validate whether the text of an element is correct, etc. MyWebSiteSteps would have steps that are specific to the internet site and cannot be applied to other applications based on Web (for example, back office). The number of steps in this class is usually small. In many cases it would not have a step, but be used solely as a place to define composites (explained later on).

Create small atomic steps

Simple code is always better than complicated code. Maintenance of the code behind scenarios is an important issue and the necessary steps should be taken to make it as easy as possible. It is tempting to create one new step that provides functionality that can be described using a number of smaller, more atomic steps. By having atomic steps that perform very specific functions, the amount of code will be limited. Complicated operations can be done with combinations of those steps. For example, step “When user logs in” has very little reusability. The same functionality can be accomplished by combining smaller steps, such as:

[BDD Story]
When the visitor types john.doe@example.com into the email field
When the visitor types mysecret into the password field
When the visitor clicks the register button

In this example we used two different steps that can be reused in many other cases. One is to type some text in a field (When the visitor types $text into the $id field) and the other is to click a button (When the visitor clicks the $id button). By combining these steps, the same functionality is accomplished as if the new step “When the user logs in” had been used. There was no need to write any additional code.

Standardize steps format

A lot of time can be lost trying to find out which one of many predefined steps you should use. This can be avoided by having a simple set of rules about how the steps should be written. For example, all steps that should click some element could be written as “When [PRODUCT] user clicks the $id [TYPE]”. Using this template we could have following steps:

[BDD Story]
When the Web user clicks the $id element
When the Web user clicks the $id link
When the Back office user clicks the $id button

Having a clearly defined steps format will mean scenarios can be written more quickly because the time spent looking for the appropriate step or second guessing what to write will be reduced. In the above example, all click actions follow the same format. You only need to know the product (Web, Back office, etc) and the type of element that should be clicked (link, button, web element, etc). The product from this format should reflect the organization of steps described in the “build the steps library” section.

Externalize parameters

It might be tempting to write a scenario similar to following:

[BDD story]
Given the Web user is using a Firefox browser
Given the Web user opened http://www.google.com
When the Web user types behavior driven development in the search field
Then the first result is Behavior-driven development - Wikipedia, the free encyclopedia

The problem with this scenario is that it will only work with Firefox. If the same set of steps is run against other browsers like Chrome and Internet Explorer, the same scenario would need to be duplicated. A better way would be to use the parameters set during the execution of stories. In Java, we could have a System parameter webDriver that could be set to one of the supported browsers. In that case, the first step could be:

[BDD story]
Given the Web user is using selected browser

The code behind that step would read the system property webDriver and open the appropriate browser.

Avoid repeated code with aliases

Often there are different steps that perform the same action or verification. For example, in a Web page you can click a link, button, div element, etc. For the sake of clarity, there could be different steps for each of these types of elements. However, the code behind all those actions should be the same. Repeated code can be avoided by using aliases.

[Java code]
@When("Web user clicks the $id element") // Generic step that can be used with any Web element
@Aliases(values={
    "Web user clicks the $id button",
    "Web user clicks the $id link"
}
public final void clickElement(final String id) {
    ...
}

This example would enable scenarios to have different ways of expressing the same action: click a Web element.

Phase #2: Combine steps into composites

Having a library of atomic steps speeds makes it easier to build the code that supports scenarios and reduces maintenance costs. However, scenarios using these steps are often too long and can be hard to understand by business analysts and customer representatives. The need for both atomic and higher level steps can be fulfilled with composites. They are a way to create groups of steps. For example, in some cases details about the sign-on procedure might be irrelevant to the purpose of the scenario. In that case, steps:

[BDD story]
Given the user is on the home screen
When the user types john.doe@example.com into the email field
When the user types my_secret into the password field
When the user clicks the login button
Then the confirmation screen is opened
...

can be substituted by:

[BDD story]
Given the user is logged in
...

This step can be written as a composite that uses the set of predefined atomic steps.

[Java code]
@Given("user is logged in")
@Composite(steps = {
    "Given the user is on the home screen",
    "When the user types john.doe@example.com into the email field",
    "When the user types my_secret into the password field",
    "When the user clicks the login button",
    "Then the confirmation screen is opened"
}

No code was written to support this new step (excluding Java annotations). Instead, existing steps are grouped together to create the new composite step.

Phase #3: Empower scenarios with examples tables

As the number of scenarios increases, so does the repetition of scenarios. The following example from the previous post defines the variations of one scenario using the examples table.

[BDD story]
Scenario: Visitors are able to register
Given the visitor is on the home screen
Given the visitor is NOT logged in
When the visitor clicks the register button
Then the login screen is loaded
When the visitor types the email <email>
When the visitor types the password <password>
When the visitor types the validation password <password2>
When the visitor clicks the register button
Then the text <text> is displayed

Examples:
|email                |password |password2 |text                            |
|john.doe@example.com |mysecret |mysecret  |Welcome john.doe@example.com    |
|john.doe@example.com |secret   |secret    |Password is too short           |
|john.doe@example.com |mysecret |something |Validation password is incorrect|
|john.doe             |mysecret |mysecret  |Email is incorrect              |

This scenario will be executed four times: once for each row in the examples table, and variables defined using < and > will be replaced by the values in the table columns.

Summary

BDD is an agile process that puts emphasis on stakeholder value. It proposes a unique set of artifacts written in natural language. Is it a way to do test-driven development with more clarity.

BDD story consists of narrative and one or more scenarios. One of the formats is:

Narrative:
In Order to [benefit]
As a [role]
I Want to [feature]

Scenario: [description]
Given [context or precondition]
When [event or action]
Then [outcome validation]

BDD narratives are NOT requirement statements. Everyone can write them.

Process of writing BDD scenarios should be:

  1. Write and discuss narrative
  2. Write and discuss short descriptions of scenarios
  3. Write steps for each scenario
  4. Repeat steps 2 and 3 during the development of the narrative

Some of the more popular tools for writing BDD stories are:

  • JBehave (Java)
  • Cucumber (Ruby / Java)
  • RSpec (Ruby)
  • Spec Flow (.Net)

Automation should follow the three steps process:

  • Create library of normalized steps
  • Combine steps into composites
  • Empower scenarios with examples tables

photo credit: salgo1960 via photopin cc

2 thoughts on “Behavior Driven Development (BDD): Value Through Collaboration (Part 4: Automation)

  1. Pingback: FEATURE TOGGLES (FEATURE SWITCHES OR FEATURE FLAGS) VS FEATURE BRANCHES | IndaSoft

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s