Behaviour Driven Development

Behaviour Driven Development(BDD) combines the principles of Test Driven Development with the ideas of Domain Driven Design. The basic idea is to allow non-programmers to specify desired Behaviour as simple user stories. These stories should be written as real sentences. Here’s an example from wikipedia:

Scenario 1: Refunded items should be returned to stock
Given a customer previously bought a black sweater from me
And I currently have three black sweaters left in stock
When he returns the sweater for a refund
Then I should have four black sweaters in stock

JBehave is a popular BDD framework for Java. Let’s try it with our selenium-webdriver.

Prerequisites

  1. Follow the steps in our last tutorial.

  2. To register JBehave, add this to the dependencies in the pom:

<dependency>
    <groupId>org.jbehave</groupId>
    <artifactId>jbehave-core</artifactId>
    <version>4.0.4</version>
</dependency>
  1. And add this to plugins:
<plugin>
     <groupId>org.jbehave</groupId>
     <artifactId>jbehave-maven-plugin</artifactId>
     <version>4.0.4</version>
     <executions>
         <execution>
             <id>run-stories-as-embeddables</id>
             <phase>integration-test</phase>
             <configuration>
                 <includes>
                     <include>**/*Scenarios.java</include>
                 </includes>
                 <ignoreFailureInStories>true</ignoreFailureInStories>
                 <ignoreFailureInView>false</ignoreFailureInView>
             </configuration>
             <goals>
                 <goal>run-stories-as-embeddables</goal>
             </goals>
         </execution>
     </executions>
 </plugin>
 <plugin>
 <groupId>org.apache.maven.plugins</groupId>
 <artifactId>maven-dependency-plugin</artifactId>
 <version>2.10</version>
 <executions>
     <execution>
         <id>copy</id>
         <phase>package</phase>
         <goals>
             <goal>copy</goal>
         </goals>
         <configuration>
             <artifactItems>
                 <artifactItem>
                     <groupId>org.springframework</groupId>
                     <artifactId>springloaded</artifactId>
                     <version>1.2.3.RELEASE</version>
                     <type>jar</type>
                     <overWrite>false</overWrite>
                     <destFileName>springloaded.jar</destFileName>
                 </artifactItem>
             </artifactItems>
             <outputDirectory>${project.build.directory}</outputDirectory>
         </configuration>
         </execution>
         <execution> 
             <id>unpack-jbehave-site-resources</id>
             <phase>generate-resources</phase> 
             <goals> 
                 <goal>unpack</goal> 
             </goals> 
             <configuration> 
                 <overwriteReleases>false</overwriteReleases> 
                 <overwriteSnapshots>true</overwriteSnapshots> 
                 <artifactItems> 
                     <artifactItem> 
                         <groupId>org.jbehave.site</groupId> 
                         <artifactId>jbehave-site-resources</artifactId> 
                         <version>3.3</version> 
                         <type>zip</type>
                         <outputDirectory> ${project.build.directory}/jbehave/view</outputDirectory> 
                     </artifactItem> 
                 </artifactItems> 
             </configuration> 
         </execution> 
         <execution> 
             <id>unpack-jbehave-reports-resources</id>
             <phase>generate-resources</phase> 
             <goals> 
                 <goal>unpack</goal> 
             </goals> 
             <configuration> 
                 <overwriteReleases>false</overwriteReleases> 
                 <overwriteSnapshots>true</overwriteSnapshots> 
                 <artifactItems> 
                     <artifactItem> 
                         <groupId>org.jbehave</groupId> 
                         <artifactId>jbehave-core</artifactId> 
                         <version>4.0.4</version> 
                         <outputDirectory>${project.build.directory}/jbehave/view</outputDirectory> 
                         <includes>**\/*.css,**\/*.ftl,**\/*.js</includes> 
                     </artifactItem> 
                 </artifactItems> 
             </configuration> 
         </execution> 
    </executions>
</plugin>

Implementing the Test

  1. Open the project “IntegrationTest General Client Code”

  2. Create a new File “dukescript_behaviour_story.story” in test resources. It will contain our simple story:

Scenario: I click the "Start" button

Given The page is loaded
When I click the button start
Then button stop should be enabled
And 6 words should .rotate
  1. Now let’s create a “New File” -> “Java” -> “Java Class” that implements the Steps.

  2. Name it “DukeScriptSteps”:

public class DukeScriptSteps extends Steps {

    private static WebDriverFX driver;
    private static Data testModel;

    @Given("The page is loaded")
    public void givenThePageIsLoaded() throws Exception {
        driver = new WebDriverFX(FileLocator.findURL("pages/index.html"));
        driver.executeAndWait(new Runnable() {
            @Override
            public void run() {
                testModel = new Data("Hello World from DukeScript !", false);
                testModel.applyBindings();
            }
        });
    }

    @When("I click the button $item")
    public void whenIPushAnItem(String item) {
        WebElement button = driver.findElement(By.id(item));
        button.click();
    }

    @Then("button $button should be $state")
    public void thenIShouldCount(String button, String state) {
        WebElement target = driver.findElement(By.id(button));
        String attribute = target.getAttribute("enabled");
    }

    @Then("$number words should $css")
    public void thenIShouldCount(int number, String css) {
        List<WebElement> findElements = driver.findElements(By.cssSelector(css));
        Assert.assertEquals(number, findElements.size());
    }
}
  1. Now we need to create a JUnit test. It derives from JUnitStory:
public class DukescriptBehaviourStory extends JUnitStory {
    @Override 
    public Configuration configuration() { return new MostUsefulConfiguration(); }

    @Override
    public InjectableStepsFactory stepsFactory() {
        return new InstanceStepsFactory(configuration()
                                      , new DukeScriptSteps());   
    }
}
  1. That’s it, you can now run it as a JUnit test. Simply right click it and select “Test File” from the context menu.

Have fun with Behaviour Driven Development!