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.

Dienstag, 4. Oktober 2011

Hosting P2 Repositories with Nexus OSS

Since a long time i had a look at Nexus and was a little bit disappointed that the P2 repository features aren't available in the open source version. Fortunately that has been changed within the last weeks:

https://docs.sonatype.org/display/Nexus/Nexus+OSGi+Experimental+Features+-+P2+Repository+Plugin

With some manual effort it's now possible to expose osgi bundles from your nexus as p2 repository which makes it much easier to consume them from within eclipse or tycho.

To install the new experimental plugins in nexus 1.9.2.3 download the following plugins from the sonatype nexus repository:

Please ensure that you download the *-bundle.zip files and not the *.jar files. Extract them afterwards into the sonatype-work/nexus/plugin-repository folder of your nexus installation. Finally restart nexus to activate those plugins.

Now its time to play a little bit around to speed up and simplify our maven tycho build. Thanks sonatype for this great improvement.