Skip to content
Martin Hauner edited this page Jan 5, 2013 · 16 revisions

Cucumber Grails Plugin Guide

Content

Introduction

grails-cucumber is a Grails plugin for Cucumber based on Cucumber-JVM. Cucumber-JVM is the JVM implementation of cucumber and it supports many JVM languages. Groovy is one of them.

grails-cucumber is a functional test plugin for grails. It is not meant to implement tests on the unit test level. It is only available in the functional test phase.

The plugin runs cucumber inside a running grails application which allows us to use the grails api in the cucumber step implementations. We can call GORM stuff like dynamic finders, services or even controllers.

Plugin Installation

grails-cucumber is a normal grails plugin. To use it in your grails application just add it to the plugins configuration block in BuildConfig.groovy like this (using the latest availabe version of the plugin):

plugins {
   test ":cucumber:0.7.0"
}

.feature Files Location

The only convention regarding cucumber .feature files is that they should be in the test/functional directory. Inside it you can use any layout you like to structure the features.

The plugin will tell Cucumber-JVM to look for features in this directory and Cucumber-JVM will scan it recursivly.

If you need to you can override this path. See Plugin Configuration.

Step Implementations Location

The step implementations follow the same convention as the .features. They should be in test/functional and inside it you can use any layout you like to structure the steps.

The plugin will tell Cucumber-JVM to look for the steps in this directory and Cucumber-JVM will scan it recursivly.

Note that you should not mix cucumber groovy scripts with other groovy scripts. Cucumber-JVM will run all groovy scripts it will find in the given path. Chances are high that this will fail and is probably not what you want anyway.

If you need to you can override this path. See Plugin Configuration.

Step Implementations

This section does contain some basic information for implementing steps: What is possible at all and how do I use specific grails functionality.

calling GORM

There is nothing special about using GORM, just use it as in production code. Having a simple domain class Book

package books

class Book {
    String author
    String title
}

we can call dynamic finders as usual:

When (~"^I add \"([^\"]*)\"\$") { String bookTitle ->
   def book = Book.findByTitle (bookTitle)
   ...
}

calling Services

To create a Service in a cucumber step call appCtx.getBean ("<bean name>") like this:

Given (~"^I have already added \"([^\"]*)\"\$") { String bookTitle ->
    def bookService = appCtx.getBean ("bookService")
    // do something with your service
}

calling Controllers

We can create & use Controllers in the same way as in a normal grails controller integration test. We just have to add some setup & cleanup that we get automatically when we implement normal integration tests by extending GroovyTestCase. That is, setting up the mock request , response and session objects.

It is just a few lines you have to call from from the cucumber Before and After hooks.

since 0. 6.0
Alternatively to adding the two hooks manually we can also add a simple configuration block into a support file (like env.groovy) which will create the two hooks.

import static grails.plugin.cucumber.Hooks.hooks

hooks {
    request ("@req")
}

The integration setting takes a cucumber tag expression as parameter and adds a Before & After hook with the code in the next section passing the tag expression to the hooks.

Before & After Code

Here is the required code to put in the Before and After hooks to get controller support in the step implementations:

import org.codehaus.groovy.grails.test.support.GrailsTestRequestEnvironmentInterceptor

this.metaClass.mixin (cucumber.runtime.groovy.Hooks)


GrailsTestRequestEnvironmentInterceptor scenarioInterceptor

Before () {
    scenarioInterceptor = new GrailsTestRequestEnvironmentInterceptor (appCtx)
    scenarioInterceptor.init ()
}

After () {
    scenarioInterceptor.destroy ()
}

calling Geb

See Testing-Grails-with-Cucumber-and-Geb for a complete tutorial.

Before & After Code

Transactions

Apart from a single constellation the plugin does/can not provide any support to wrap a scenario into a transaction to automate the cleanup of the database. We will have to provide Before and After hooks to setup and cleanup the database (see cucumber & Grails: Transaction Rollback). There are two options:

  • re-create the database schema on each scenario
  • restore the original database state with update/delete statements

Running Cucumber Features

The plugin integrates cucumber as a grails test type into the grails test infrastructure. You can run the cucumber features via the grails test-app command and the test results will be included in the normal grails test reports.

Currently the plugin registers the cucumber test type only to the functional test phase. To run the cucumber features you call grails by one of the following commands:

grails test-app functional:cucumber
grails test-app :cucumber

Or, if you do not use a second functional test plugin you can also use:

grails test-app functional:

Command Line Options

@tag filter

since 0.6.0 If the command line contains :cucumber, @tag parameters are evaluated to filter execution of features or scenarios. Standard cucumber syntax applies without the --tags option keyword. Setting tags on the comand line will overwrite CucumberConfig.groovy:

    grails test-app :cucumber @foo,~@bar @zap

Test Reports

In JUnit we have test suites and tests. In Cucumber we have features, scenarios and steps. The plugin maps features to test suites and scenarios to tests. There is no direct mapping for steps. The steps will be reported as part of their scenario.

Grails does only distinguish between failures and errors and knows nothing about undefined steps. Undefined steps will be therefore reported as failure which makes the scenario fail too.

The plugin integrates into grails test reporting. The normal cucumber output can be found in the html or plain test reports in target/test-reports.

Plugin Configuration

Convention over Configuration

The plugin does use a couple of default settings that can be overriden by CucumberConfig.groovy if you need to. If a setting is not given in the configuration file the default will be used.

The defaults in CucumberConfig.groovy notation are:

cucumber {
    tags = []
    
    features = ["test/functional"]
    glue = ["test/functional"]
}

The hardcoded test/cucumber path used in the plugin before version 0.4.0 is now deprecated. If you still like to use it you can add it to the features and steps setting in CucumberConfig.groovy.

cucumber {
    features = ["test/cucumber"]
    glue = ["test/cucumber"]
}

Location

The plugin will read the configuration from grails-app/conf/CucumberConfig.groovy. It is a a standard config slurper file.

We can adjust the paths where cucumber will look for .feature files and step implementations so putting the configuration along the cucumer files does not work.

Options

Tags

Cucumber tags can be set using the tags configuration option:

cucumber {
    tags = ["@implemented", "~@ignored"]
}

tags is a list of strings where each item corresponds to a single cucumber --tags option. See the cucumber documentation to read more about the --tags switch.

.feature File Location

To override or extend the locations where cucumber will search for .feature files you can use the features option:

cucumber {
    features = [
        "test/functional/features",
        "test/functional/featuresOfCurrentSprint"
    ]
}

features is a list of paths where each path is relative (below) the grails application root directory.

Note that settings this option will override the default test/functional path. If you want to keep it you have to add it to the features path list.

Step Implementation Location

To override or extend the locations cucumber will search for groovy scripts with gherkin steps or hooks you can use the glue option:

cucumber {
    glue = [
        "test/functional/steps",
        "test/functional/hooks"
    ]
}

glue is a list of paths where each path is relative (below) the grails application root directory.

Note that settings this option will override the default test/functional path. If you want to keep it you have to add it to the glue path list.

Standard Hooks

since 0.6.0
The plugin provides a couple of standard hooks that can be enabled using the hooks configuration block. It should be placed in a groovy file on the glue path:

import static grails.plugin.cucumber.Hooks.hooks

hooks {
    integration ("@i9n")
}

The integration setting enables grails integration test support which we will get automatically in normal integration tests by extending GroovyTestCase. It will simply create a Before and a After hook pair with the given tag expression to set up and clean up grails integration testing. Note that this is only usefull for ui-less testing.

The following hooks are supported:

FAQ & Pitfalls

  • The plugin fails when I try to run features in a non-english language.

    If cucumber does not recognize the # language: <language code> comment at the beginning of a feature file it is probably because of a byte order marker (BOM). Remove it and try again.

Clone this wiki locally