Since several weeks i planned to prepare an simple example for an upcoming talk about Acceptance Test Driven Development (ATDD). I decided to play with Cucumber as it seems to be the most adopted ATDD framework in the wild.
As Cucumber is a Ruby framework and i would like to use it in Java together with Maven I had a look at cuke4duke which should bring those 2 worlds together. I tried several examples but already failed to setup a very basic one. While looking around for an solution i came across an blog post from Thomas Sundberg. he pointed to the successor project of cuke4duke which is named cucumber-jvm. It's a pure Java implementation :-) of cucumber and supports several other languages like Ruby, Groovy, Python etc. From my point of view is has several advantages in contrast to cuke4duke:
- easy setup
- It took me less than 5 minutes to setup the basic example.
- faster
- cucumber-jvm provides a custom JUnit Runner to execute tests. No need to trigger maven to execute your integration test. Thus the startup time is drastically reduced.
- less magic
- Features and their implementation are linked via @Feature annotations. No need to scan your complete project anymore
As cucumber-jvm isn't available as stable version it must be resolved from a snapshot repo:
pom.xml:
pom.xml:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>net.ludeke.examples</groupId>
<artifactId>cucumber-jvm-example</artifactId>
<version>0.0.1-SNAPSHOT</version>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.6</source>
<target>1.6</target>
</configuration>
</plugin>
</plugins>
</build>
<dependencies>
<!-- JUnit -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.8.2</version>
<scope>test</scope>
</dependency>
<!-- Cucumber -->
<dependency>
<groupId>info.cukes</groupId>
<artifactId>cucumber-junit</artifactId>
<version>1.0.0-SNAPSHOT</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>info.cukes</groupId>
<artifactId>cucumber-java</artifactId>
<version>1.0.0-SNAPSHOT</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>info.cukes</groupId>
<artifactId>cucumber-picocontainer</artifactId>
<version>1.0.0-SNAPSHOT</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.picocontainer</groupId>
<artifactId>picocontainer</artifactId>
<version>2.10.2</version>
<scope>test</scope>
</dependency>
</dependencies>
<repositories>
<repository>
<id>sonatype-snapshots</id>
<url>https://oss.sonatype.org/content/repositories/snapshots</url>
</repository>
</repositories>
</project>
CarMaintenance.feature:
Feature: Daily car maintenance
Cars need maintenance
Scenario: Fuelling
Given a car with 10 litres of fuel in the tank
When you fill it with 50 litres of fuel
Then the tank contains 60 litres
Car.java:
package net.ludeke.example;
public class Car {
private Integer fuelLevel;
public Car(int initialFuelLevel) {
fuelLevel = initialFuelLevel;
}
public void addFuel(int addedFuel) {
fuelLevel = fuelLevel + addedFuel;
}
public int getFuelLevel() {
return fuelLevel;
}
}
FuelCarTest.java:
package net.ludeke.example;
import cucumber.annotation.en.Given;
import cucumber.annotation.en.Then;
import cucumber.annotation.en.When;
import cucumber.junit.Cucumber;
import cucumber.junit.Feature;
import net.ludeke.example.Car;
import org.junit.runner.RunWith;
import static org.hamcrest.core.Is.is;
import static org.junit.Assert.assertThat;
@RunWith(Cucumber.class)
@Feature(value = "CarMaintenance.feature")
public class FuelCarTest {
private Car car;
@Given("^a car with (\\d*) litres of fuel in the tank$")
public void createCar(int initialFuelLevel) {
car = new Car(initialFuelLevel);
}
@When("^you fill it with (\\d*) litres of fuel$")
public void addFuel(int addedFuel) {
car.addFuel(addedFuel);
}
@Then("^the tank contains (\\d*) litres$")
public void checkBalance(int expectedFuelLevel) {
int actualFuelLevel = car.getFuelLevel();
assertThat(actualFuelLevel, is(expectedFuelLevel));
}
}
From my point of view this solution is much more straight forward for (at least) Java developers than cuke4duke.
This seems to be pretty similar to JBehave. Why would one use this one instead of the other?
AntwortenLöschenHey I have an issue following what you have said above. The thing is I am quite naive to maven/repository world , therefore by I have only been able to install maven and create a test project with mvn create . Could you please tell me what exactly I need to do step by step in order to get going with Cucumber-jvm...
AntwortenLöschenHi
AntwortenLöschenI separated the steps from the glue in the FuelCarTest.java. It all runs fine, but I wanted to know why the results of the test state 4 tests run.
As far as I can tell its one feature, ending with one assertion.
Results :
Tests run: 4, Failures: 0, Errors: 0, Skipped: 0