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
-
Follow the steps in our last tutorial.
-
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>
- 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
-
Open the project “IntegrationTest General Client Code”
-
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
-
Now let’s create a “New File” -> “Java” -> “Java Class” that implements the Steps.
-
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());
}
}
- 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());
}
}
- 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!