The final step of the BDD process is to take scenarios that have been captured from the collaborative conversation and automate them to help guide development. Let's take a look at an example:

Automating an acceptance test

For this guide we are going to go through the Outside in Development flow and create our first automated acceptance test based of the following captured Gherkin scenario:

Scenario: Create a booking in Hotel Booking
  Given a user wants to make a booking
  When the booking is submitted by the user
  Then the booking is successfully stored

Getting setup

Before we start automating our acceptance test we have a couple of things to get setup:

  1. An automation framework to run our feature files 
  2. Access to our features files created by Behave Pro

Setting up a framework

For this automated acceptance test we are going to create a framework that uses two main libraries for framework Cucumber-JVM and Selenium-WebDriver. We'll do this via the cucumber-archetype plugin by running the following in your terminal or command window:

mvn archetype:generate                      \
   -DarchetypeGroupId=io.cucumber           \
   -DarchetypeArtifactId=cucumber-archetype \
   -DarchetypeVersion=2.3.1.2               \
   -DgroupId=behaveprodemo                  \
   -DartifactId=behaveprodemo               \
   -Dpackage=behaveprodemo                  \
   -Dversion=1.0.0-SNAPSHOT                 \
   -DinteractiveMode=false

Once built, you should have a maven project named behaveprodemo that you can navigate into.

Accessing our feature files

Our next step is to populate our framework with feature files we have created in Behave Pro. We can do this by integrating Behave Pro with a GitHub repository that contains your framework code. Meaning every time a feature file is created or updated, your framework is updated, giving us greater control of maintaining our automated acceptance tests.

To start with, create a new GitHub repository and then clone it to your local machine:

git clone git@github.com:<url-to-repo>.git

Next copy the contents of behaveprodemo into your cloned folder and commit them to GitHub

git add .
git commit -m "Adding in Behave Pro demo"
git push origin master

With our framework committed to our repository the final step is to configure our JIRA project to connect to our repository. Simply do this by heading to Your project > Project Settings > BDD Integration and following the wizard, ensuring you select:

  • Your organisation
  • Your repository
  • A branch you want to work on, such as master 
  • And set the feature directory to /src/test/resource/behaveprodemo which is where Cucumber-JVM will expect the feature files to live

Once everything has been setup go back to your locally cloned repository and run git pull origin to pull down the feature files that Behave Pro is now storing in your GitHub repository.

Creating your first automated acceptance test

Now that we are setup we can start creating our automated acceptance test that will attempt to interact with our feature and fail because the feature doesn't exist.

Generate step definitions

First of all we need to create step definitions that will trigger our automation code. Step definitions match to the natural language steps that are defined in a Gherkin scenario. So as a scenario is run it will find the matching step definition to the step it's running and execute the code within it.

To create the code navigate into the root folder of your repository and run mvn test to get output similar to this:

Notice how the annotated Given, When and Thens at the top of the declared methods match the Gherkin scenario. This is what we mean by matching step definitions to the natural language steps.

Since Cucumber-JVM has helpfully created us the code we need, we can copy this code directly into src/test/java/behaveprodemo/Stepdefs.java and then run mvn test again:

Notice how the output has now changed. This is because the step definitions we pasted in are now being triggered during the run and the first step is returning a pending exception.

Filling in the step definitions

Now that our step definitions are configured, our next step is to add in our failing automation code, which we will do using Selenium-WebDriver. To use Selenium we will need to add a new dependency to our pom.xml:

<dependency>
  <groupId>org.seleniumhq.selenium</groupId>
  <artifactId>selenium-java</artifactId>
  <version>3.14.0</version>
  <scope>test</scope>
</dependency>

We will also need to download the Chromedriver binary for Selenium to interact with which can be found here: https://chromedriver.storage.googleapis.com/index.html?path=2.41/

With everything setup let's update our step definitions to the following:

private WebDriver driver;

@Given("^a user wants to make a booking$")
public void a_user_wants_to_make_a_booking() throws Exception {
    System.setProperty("webdriver.chrome.driver", "chromedriver");
    driver = new ChromeDriver();

    driver.navigate().to("file://index.html");
}

@When("^the booking is submitted by the user$")
public void the_booking_is_submitted_by_the_user() throws Exception {
    driver.findElement(By.id("firstname")).sendKeys("Behave Pro");
    driver.findElement(By.id("lastname")).sendKeys("Rocks");
    driver.findElement(By.id("checkin")).sendKeys("2018-01-01");
    driver.findElement(By.id("checkout")).sendKeys("2018-01-03");
    driver.findElement(By.id("submit")).click();
}

@Then("^the booking is successfully stored$")
public void the_booking_is_successfully_stored() throws Exception {
    String bookingEntry = driver.findElements(By.cssSelector("tr")).get(1).getText();

    assertThat("Behave Pro Rocks 2018-01-01 2018-01-03", is(bookingEntry));

    driver.close();
}

With our code updated, let's run it with mvn test to receive an error message similar to the one below:

The run fails because it cannot find the feature we want to the test to operate. Meaning that we are ready to build our production code to make the test pass.

Making our acceptance test pass

With our failing automated acceptance test in place we can now write production code to make the test pass. So let's create an index.html file and paste in the following code and save:

<html>
  <head>
    <script>
      addBooking=function(){var e=document.getElementById("bookings").insertRow(1);e.insertCell(0).innerHTML=document.getElementById("firstname").value,e.insertCell(1).innerHTML=document.getElementById("lastname").value,e.insertCell(2).innerHTML=document.getElementById("checkin").value,e.insertCell(3).innerHTML=document.getElementById("checkout").value};
      </script>
  </head>
  <body>
    <table id="bookings">
      <tr>
        <td>
          <input type="text" id="firstname" placeholder="Firstname" />
        </td>
        <td>
          <input type="text" id="lastname" placeholder="Lastname" />
        </td>
        <td>
          <input type="text" id="checkin" placeholder="Check in" />
        </td>
        <td>
          <input type="text" id="checkout" placeholder="Check out" />
        </td>
        <td>
          <button id="submit" onclick="addBooking()">Add</button>
        </td>
      </tr>
    </table>
  </body>
</html>

With our production code created, update the driver.navigate.to()method in our test to point to where the index.html is located. Then finally run mvn test one more time:

Congratulations, we now have a passing test!

Refactoring your code

Now that we have a passing green acceptance test we have a clear indication that:

  1. We have completed the work we need to do
  2. The feature we have created matches the described behaviour in captured scenario

In addition to this, we now have the capacity to refactor our production code in confidence. As we refactor we can run the green acceptance test and if it fails we can tell that our refactor is causing our feature to drift away from the expected behaviour defined in the scenario.

Going further

The example that you have just gone through is following a pattern within BDD that is known as Outside in Development. By creating a failing automated acceptance test a developer can comfortably create production code that makes the automated acceptance test pass. This guides the developer towards delivering the right thing for the business as well telling them that they are done. Finally, with passing tests in place, developers are free to refactor their code knowing if their refactor accidentally breaks something.

In this example we've given you a taste of what you can do with the Outside in Development approach and Behave Pro and there is a lot more to learn about the approach.

Further reading:

In addition to the theory there are many other practical tricks and approaches you can leverage to improve your automation, for example:

Did this answer your question?