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!