Archive for the ‘Behaviour Driven Development’ Category

6
May 13

Functional Testing Using JBehave, Jetty and Maven

JBehave
JBehave is a java-based functional testing framework which allows tests written in human readable text to be automatically executed.
Functionality is defined at the user story level and broken down into a number of scenarios. Each scenario should capture a unique piece of functionality or behavior.
The format of the JBehave stories are given below:

Narrative: In order to ….. As a ….. I want to …..

Scenario: …..

Given …..
When …..
Then …..

The Narrative defines the functionality we are trying to test in user story form.
Following the narrative is a number of scenarios.
The Given clause defines a set of pre-conditions to set up the context of the test.
The When clause defines one or more actions to be performed to trigger the functionality that we are testing.
The Then clause is then use to test the state is as expected following the action.
A concrete example for a “happy path” scenario is given below:

Narrative:
In order to buy a product
As a customer
I want to register an account

Scenario: register an account

Given no account exists with email tester@test.com
And no account exists with username tester
When I create an account with email tester@test.com, username tester and date of birth 11/12/1981
Then I receive a succesful response
And the account is created in the database

Each line of this scenarios can then be mapped to a Java “Step” using annotations:

@Given(“no account exists with email $email”)
public void checkEmailDoesNotExist( String email ) {
userRepository.deleteByEmail(email);
}

@When(“I create an account with email  $email, username $user and date of birth $dob”) {
public void create Account( String email, STring username, Date dob ) {
Account account = new Account(email, username, dob);
response = restTemplate.postForEntity(url, account,Account.Class);
}

@Then(“I receive a succesful response”)
public void checkSuccesfulResponse( String response ) {
assertThat(response.getStatusCode(), is (200) );
}

Test can be run a number of ways. The easiest way is through JBehaves JUnit integration which allows annotation driven configuration. It also integrates nicely with Spring. For example:

@RunWith(SpringAnnotatedEmbedderRunner.class)
@Configure()
@UsingSpring
public class RegistrationTests() {

}

I recommend downloading the JBehave Eclipse plugin which performs syntax highlighting and linking from textueal steps to code.

Behaviour Driven Development

Behavior-driven development is a specialized version of test-driven development which focuses on behavioral specification of software units.
The tests are defined first. JBehave will mark these tests “Pending” until the implementation is complete. Preferably, these tests will be defined collaboratively between the developers, testers and business in which case they form the acceptance criteria for the user story.
The developer then implements the functionality required so that the tests pass. At this stage the developer may discover alternative scenarios that may form further acceptance criteria. For example:

Scenario: I must use a unique email

Given an account already exists with email tester@test.com
And no account exists with username tester
When I create an account with email tester@test.com, username tester and date of birth 11/12/1981
Then I receive a bad request error with message “Email must be unique”

Scenario: My Date of Birth Must be in the past

Given no account exists with email tester@test.com
And no account exists with username tester
When I create an account with email tester@test.com, username tester and date of birth 11/12/2081
Then I receive a bad request error with message “Date of birth must be in the past”

Again these stories should be a product of the collaboration between developers, testers and project stakeholders. In this way the stories not only provide acceptance criteria forming a functional contract regarding what functionality the application will provide, but also provides regularly validated “Living Documentation” specifying exactly what an application does at any point in time.

Integrating into the build process using Maven and Jetty

Your functional tests could be run against your application at various levels:

Directly against the code
Against a test container running the code (for example using spring mvc integration tests)
Against a deployed application at the http level (below the GUI)
Over the GUI (Using a tool such as Selenium).

I prefer the third option as I want to test as much as possible without the fragility that GUI testing often brings. When testing REST services this level is particularly appropriate.
A lightweight container such as Jetty provides a simple way to expose your application as part of the build lifecycle as follows:

pre-integration-test: Start Jetty containing deployed application
integration-test: Run JBehave tests using the JBehave Maven plugin
post-integration-test: Shutdown Jetty

This lifecycle can easily be set up in the plugin section of your POM:

<plugins>
<plugin>
<groupId>org.mortbay.jetty</groupId>
<artifactId>maven-jetty-plugin</artifactId>=
<configuration>
<executions>
<execution>
<id>start-jetty</id>
<phase>pre-integration-test</phase>
<goals>
<goal>run</goal>
</goals>
<configuration>
<daemon>true</daemon>
</configuratin>
</execution>
<execution>
<id>stop-jetty</id>
<phase>post-integration-test</phase>
<goals>
<goal>stop</goal>
</goals>
</execution>
</executions>
</configuration>
</plugin>

<plugin>
<groupId>org.jbehave</groupId>
<artifactId>jbehave-maven-plugin</artifactId>
<executions>
<execution>
<id>unpack-view-resources</id>
<phase>process-resources</phase>
<goals>
<goal>unpack-view-resources</goal>
</goals>
</execution>
<execution>
<id>embeddable-stories</id>
<phase>integration-test</phase>
<goals>
<goal>run-stories-with-annotated-embedder</goal>
</goals>
<configuration>
<includes>
<include>**/*Strories.java</include>
</includes>
</configuration>
</execution>
</executions>
</plugins>

JBehave as part of a continuous delivery pipeline

When using continuous delivery it is often preferable to run your JBehave tests directly against the application deployed in a test environment, this way your testing the configuration and deployemnt process in addition to the code.
A typical deployment pipeline will consist of the following steps

  • Build binaries
  • Deploy to test environment
  • Run acceptance tests against test environment
  • Promote to UAT
  • ….

As the tests are running directly against an app server we don’t strictly need to run jetty anymore, however it is often worth keeping it in to run a restricted set of smoke tests in the buid phase to validate the build. JBehave supports meta tags so that you can mark a restriced set of tests as smoke tests:

Scenario: Simple smoke test

Meta: @Theme smoke

Given…..

When you instruct JBehave to run the tests, you can inform it to run only the smoke tests, or to exclude the smoke tests.

@UsingEmbedder(metaFilters= {“+theme smoke”})

or

@UsingEmbedder(metaFilters= {“-theme smoke”})

If you configure your acceptance tests so that you can specify endpoints and databases connection details externally you can point your acceptance tests to the test environments .