OpenEJB and some BDD


BDD is a fine way to test its code. Personally i like the way it allows to link code expert with domain experts. Here i’ll try to show how to do it with OpenEJB using two interesting BDD frameworks.

The well known Spock

Spock is known because it is used on tapestry (at least that’s the way i discovered it ;)). Here is its website http://code.google.com/p/spock/.

Using spock is pretty easy since you simply have to use its arquillian integration and OpenEJB arquillian adapter to make it running in a JEE container.

Spock is often used with groovy…you see any issue? No!

First write your code as usually (let take an hello world). Then add to your pom some code to compile groovy in java (for instance):

<plugin>
  <groupId>org.apache.maven.plugins</groupId>
  <artifactId>maven-compiler-plugin</artifactId>
  <version>2.4</version>
  <configuration>
    <compilerId>groovy-eclipse-compiler</compilerId>
    <source>1.6</source>
    <target>1.6</target>
  </configuration>
  <dependencies>
    <dependency>
      <groupId>org.codehaus.groovy</groupId>
      <artifactId>groovy-eclipse-compiler</artifactId>
      <version>2.6.0-01</version>
    </dependency>
  </dependencies>
</plugin>

Then add dependencies needed (ziplock is just used in the test as an utility method and is not mandatory):

<dependency>
  <groupId>org.codehaus.groovy</groupId>
  <artifactId>groovy-all</artifactId>
  <version>1.8.0</version> <!-- spock doesn't work with 2.0.0-rc-4 -->
</dependency>

<dependency>
  <groupId>junit</groupId>
  <artifactId>junit</artifactId>
  <version>4.10</version>
  <scope>test</scope>
</dependency>
<dependency>
  <groupId>org.apache.openejb</groupId>
  <artifactId>arquillian-openejb-embedded-4</artifactId>
  <version>4.1.0-SNAPSHOT</version>
  <scope>test</scope>
</dependency>
<dependency>
  <groupId>org.apache.openejb</groupId>
  <artifactId>ziplock</artifactId>
  <version>1.1.0-SNAPSHOT</version>
  <scope>test</scope>
</dependency>
<dependency>
  <groupId>org.jboss.arquillian.spock</groupId>
  <artifactId>arquillian-spock-container</artifactId>
  <version>1.0.0.Alpha1</version>
  <scope>test</scope>
</dependency>
<dependency>
  <groupId>org.spockframework</groupId>
  <artifactId>spock-core</artifactId>
  <version>0.5-groovy-1.8</version>
  <scope>test</scope>
</dependency>

Note: groovy is not in scope test because with the compiler configuration it can be used for the main code too.

Before going further one optional task: configuring Specification to be used instead of Test as suffix for tests classes by the surefire plugin to follow the spock convention:

<plugin>
  <groupId>org.apache.maven.plugins</groupId>
  <artifactId>maven-surefire-plugin</artifactId>
  <version>2.12</version>
  <configuration>
    <includes> <!-- we could have used *Test.java as by default but it is more consistent -->
      <include>**/*Specification.java</include>
    </includes>
  </configuration>
</plugin>

Now the pom should be fine so let’s write our test in groovy (yeah!) using the arquillian-spock integration and OpenEJB as runtime:

import org.apache.ziplock.JarLocation
import org.jboss.arquillian.container.test.api.Deployment
import org.jboss.shrinkwrap.api.ArchivePaths
import org.jboss.shrinkwrap.api.ShrinkWrap
import org.jboss.shrinkwrap.api.asset.EmptyAsset
import org.jboss.shrinkwrap.api.spec.WebArchive
import spock.lang.Specification

import javax.inject.Inject

import static org.junit.Assert.assertEquals
import static org.junit.Assert.assertNotNull

class HelloSpecification extends Specification {
    @Inject
    private Hello hello

    @Deployment
    def static WebArchive "create archive"() {
        ShrinkWrap.create(WebArchive.class)
            .addAsLibraries(JarLocation.jarLocation(GroovyObject.class))
            .addAsWebInfResource(EmptyAsset.INSTANCE, ArchivePaths.create("beans.xml"))
            .addClasses(Hello.class)
    }

    def "Hello.hi() method should return 'hi'"() {
        when:
            assertNotNull hello

        then:
            assertEquals "hi", hello.hi()
    }
}

Cucumber-jvm: the rails ruby ported to JVM languages

Cucumber is a famous testing framework in Rails world and was recently ported to JVM languages.

An OpenEJB integration is proposed.

Note: it has a little constraint which is to import log4j (was the case for old openejb version but now it should be optional – an issue was opened for it).

The idea is pretty simple: write a Gherkin feature file (the extension is feature too) and then create a kind of suite runner which will scan its package to find step defs.

Here is a runner:

import cucumber.junit.Cucumber;
import org.junit.runner.RunWith;

@RunWith(Cucumber.class)
public class CucumberTest {
    // the suite, will load automatically the features
}

Here a a feature file:

Feature: Hello

  Scenario: Say Hello
  Given A name 'foo'
  Then The bean says 'hello foo'

And here the corresponding steps:

import cucumber.annotation.en.Given;
import cucumber.annotation.en.Then;

import javax.inject.Inject;

import static org.junit.Assert.assertEquals;

public class HelloStepDef {
    @Inject
    private Hello hello;

    private String name;

    @Given("^A name '([a-z]*)'$")
    public void initName(final String name) {
        this.name = name;
    }

    @Then("^The bean says '([ a-z]*)'$")
    public void checkResult(final String result) {
        assertEquals(result, hello.hello(name));
    }
}

Note: several languagaes are available for cucumber annotations (simply switch of package to find them).

So the job is done! we can match values (even multiple ones) from the feature file then get them in the test.

It is pretty simple and efficient.

The current drawback i see is each method is counted as a test by surefire where i could have expected that a scenario is a test but well that’s a detail.

A funny and nice thing (even if it is not as nice as in Ruby) is if you forget some steps the code to write will be printed in the console :). So generally we write features, run the test and copy paste as a starting point for steps.

Conclusion

BDD is really possible today even with JEE so why wouldn’t use it?

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s