Mittwoch, 5. Oktober 2011

Getting started with ATDD and Cucumber JVM

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
Ok now its time to check my litlle example project:

project structure:
As cucumber-jvm isn't available as stable version it must be resolved from a snapshot repo:
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.

3 Kommentare:

  1. This seems to be pretty similar to JBehave. Why would one use this one instead of the other?

    AntwortenLöschen
  2. Hey 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öschen
  3. Hi

    I 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

    AntwortenLöschen