(Quick Reference)

1 Introduction - Reference Documentation

Authors: Erik Pragt (jWorks.nl), Marcin Erdmann, John Engelman

Version: 2.0.3

Table of Contents

1 Introduction

The Fitnesse plugin provides a integration point between the popular Open Source testing framework Fitnesse:http://www.fitnesse.org and Grails applications.

This guide documents the usage of the plugin and provides an easy starting point to get you up to speed with the plugin as well as with Fitnesse.

Note that the SLIM version of Fitnesse is supported. FIT, the older Fitnesse protocol, is not yet supported, nor will it be supported in the near future.

Release History

  • April 26, 2012
    • 2.0.3 Release!
      • Small bugfix in the _Events.groovy, due to conflicts in closure name with Functional test plugin.
      • Another small bugfix in the _Install.groovy. The .donotdelete file for the fitnesse directory was created in the wrong dir.
  • April 23, 2012
    • 2.0.2 Release!
      • Small bugfix in the _Install.groovy. Thanks to Nicolas Vinet for reporting!
  • April 16, 2012
    • 2.0.1 Release!
      • Implemented better feedback
      • Fixed some bugs in the documentation, most notably the quickstart.
      • Enabled PDF support for documentation
      • Enabled bundled example project
  • April 12, 2012
    • 2.0 Release!
      • After a long time of inactivity, there's a new release, thanks to John Engelman. Thanks for the great work John!
      • JUnit Test Reports implemented
      • Included latest Fitnesse (20111025)
  • June 10, 2011
    • 1.0 Release!
      • Feature: Support for GivWenZen
      • Bugfix: Fixed the tutorial documentation (thanks Pierre D. Tremblay!)
      • Bugfix: Fixed the dependency resolution of libraries (thanks Steef de Bruijn)
      • Bugfix: Fixed plugin scopes (thanks Steef de Bruijn)
  • May 18, 2011
    • 0.95 Release
      • Feature: Enabled easy mapping of enums classes
      • Improvement: Improved Query Fixture DSL to allow dotted notation
      • Improvement: Enhanced reloading of application
  • March 22, 2011
    • 0.9 Release
      • We upped the version number to 0.9 because the plugin is quite feature complete now, and is almost stable enough to be a 1.0.
      • Feature: Introduced @Fixture annotation, so fixtures can now be given any name (they don't have to be suffixed with Fixture), as long as they are annotated with the annotation.
      • Feature: Added Transaction support
      • Bugfix: Fixed JSON conversion for domain classes and collections
      • Bugfix: Fixed reloading classes and fixtures that use inheritance
      • Bugfix: Fixed grails test-app
      • Bugfix: Fixed issues in the documentation
  • March 1, 2011
    • 0.5 Release
      • Feature: Fitnesse testrunner created. Grails applications can now be tested using: grails test-app integration:fitnesse "FrontPage.GrailsTestSuite.SlimTestSystem?suite"
      • Feature: Fitnesse integrated. Fitnesse can now be started using: grails run-fitnesse
      • Feature: Fitnesse can be disabled by setting the grails.plugin.fitnesse.disabled property to true
      • Improvement: Internal Fitnesse upgraded to the newest Fitnesse version
      • Improvement: Naming of configuration parameters have changed to be more consistent. *Beware: the 'plugins' configuration option has changes to 'plugin' (without the 's')
      • Improvement: Bundled testproject in Github
      • Improvement: Fixture classes are now Spring beans
      • Bugfix: Fixed lazyloadingexception
      • Bugfix: Fixed exception message when a given constructor is not found for a fixture
      • Bugfix: Fixed reloading of services to give errors in Fixtures
      • Bugfix: Marcin's surname is fixed in the documentation!
  • November 16, 2010
    • 0.4 Release, thanks to Marcin Erdmann!
      • Complete refactoring of the plugin thanks to Marcin Erdmann (ie using Artefacts, Artefact Templates, JSON Code to enable complex objects, and more!)
      • Important: All fixtures should now be end with the suffix 'Fixture', as in 'CalculateFixture'. In the Wiki you can still refer to them as 'Calculate', but the plugin adds a Fixture suffix when looking for the class.
      • Improved error messages
      • You can now create complex objects from within Fitnesse by using JSON syntax.
      • More documentation!
      • Fixed some bugs in documentation (thanks Olivier Hedin for reporting!)
  • October 12, 2010
    • 0.3 Release.
      • Added more documentation (configuration options, quickstart), refactored the internals
      • Added verbose logging switch
      • Fixed a Grails reloading bug, which caused ports to be opened twice. Now the plugin closes all ports, and reopens them whenever Grails forces a restart
      • You can now throw StopTest Exceptions from Fixture constructors (which is not possible in the Java Fitnesse)
  • September 19, 2010
    • 0.2 release. First public release. Includes lots of documentation, including a tutorial with 3 fixture types.
  • September 15, 2010
    • initial 0.1 release.

1.1 Features

The Fitnesse plugin supports some additional features besides the standard Fitnesse functionality.

Moved Fitnesse to it's own Phase/Type (since 2.0)

You can now use grails test-app fitnesse:fitnesse. The phase runs in integration mode

Integration with JUnit reports (since 2.0)

The Fitnesse output, which is written to target/test-reports/fitnesse, will now be parsed to create JUnit Test objects. This allows the JUnit Reporting framework to output the .txt file and the JUnit .xml file. This also allows Fitnesse test results to participate in the Grails Test Report HTML file.

Support for GivWenZen (since 1.0)

Since version 1.0, we support the GivWenZen library. GivWenZen allows a user to use the BDD Given When Then vocabulary and plain text sentences to help a team get the words right and create a ubiquitous language to describe and test a business domain. See the GivWenZen website for more information.

To use GivWenZen in Grails Fitnesse, import the fitnesse.grails package and use the GivWenZenForGrails fixture in a script table, as can be seen in the example below:

|import|
|fitnesse.grails|

|script| |start|giv wen zen for grails|

|script| |given|the number 5| |when|incrementing it by 3| |then|the result is 8|

|script| |given|the number 1| |when|incrementing it by 2| |and|incrementing it by 3| |then|the result is 6|

To make this test work, you'll need a step class like the one below:

import org.givwenzen.annotations.DomainStep
import org.givwenzen.annotations.DomainSteps

@DomainSteps class GivWenZenSupportSteps { private int number

@DomainStep("the number (\\d+)") void setNumber(int number) { this.number = number }

@DomainStep("incrementing it by (\\d+)") void incrementNumber(int by) { number += by }

@DomainStep("the result is (\\d+)") boolean expect(int result) { number == result } }

Automatic Enum mapping (since 0.95)

Since version 0.95, it's possible to automatically map enum values. Just specify the value of the enum in the table, and you're done.

An example:

class MyEnumFixture {
    Color color
}

enum Color { RED, GREEN, BLUE }

By specifying the name of the enum value in the test (see below), the mapping is automatically done:

|my enum     |
|color|color?|
|RED  |RED   |

Nested property mapping for Query Fixtures (since 0.95)

It was already possible (since version 0.4) to create a simple Query Fixture using the Query Fixture DSL. This DSL has been extended by also allowing nested properties using a dotted (.) notation, as can be seen below:

class NestedPropertyKeyValueQueryFixture {
    static queryFixture = true

static mapping = ["name":"author.name", "birthYear":"author.birthYear", "title":"title"]

def queryResults() { return [new Book(title:'Grails in Action', author: new Author(name:"Peter Ledbrook", birthYear: 1980))] } }

Fixture annotation (since 0.9)

Since version 0.9, it's possible to annotate Fixture classes with the @Fixture annotatation. This means that fixtures can now be given any name (ie. they don't have to be suffixed with Fixture), as long as they are annotated with the @Fixture annotation.

@Fixture
class BuyBook {
    // contents here
}

Transaction support (since 0.9)

Transaction support provides three fixtures called BeginTransaction, Commit and Rollback. To use you need to import the fitnesse.grails package, i.e. in SetUp or SuiteSetUp:

|import|
|fitnesse.grails|

The transaction support was introduced mainly for scenarios where test pages via fixtures modify the database and you don't want that modifications to be persisted after the end of the test page execution. It means that the test page can be run multiple times without the need of cleaning up the database afterwards and it doesn't affect other tests by database contamination. To run a test page within a rolledback transaction simply add begin transaction and rollback tables to your test page:

|begin transaction|

--some test tables--

|rollback|

If you wish to run all of your test pages contained within a suite in rolledback transactions simply add begin transaction and rollback tables to SetUp and TearDown pages respectively for the given suite.

Templates (since 0.4)

You can now easily create Fixtures by typing:

grails create-fitnesse-query-fixture <name of fixture>

Or

grails create-fitnesse-fixture <name of fixture>

This will create a fixture in the grails-appfitnesse directory, which should give you a head start on how to create a Fixture.

Complex objects (since 0.4)

You can now create complex objects from within Fitnesse. This uses the JSON format, since it's easy to read and write, and is becoming quite a standard.

An example can be seen below:

Wiki

|create book inventory                     |
|book                               |amount|
|{author: Stephen King, title: IT}  |     3|
|{author: Dean Koontz, title: Chase}|     5|

This JSON code in the test is mapped to the following Fixture and Domain class:

Fixture

class CreateBookInventoryFixture {
    Book book

int amount

def bookService

CreateBookInventoryFixture() { Book.list()*.delete() }

void execute() { amount.times { book.id = null bookService.addBook(book) } } }

And the very simple Domain class:

class Book {
    String author
    String title
}

Version 0.9 brings support for collections into JSON object conversion. The feature works for typed collection fixture fields but not for function parameters (because information about generics is is kept at runtime only for fields). It also works for hasMany relations in grails domain objects. Example usage is:

Wiki

|json objects conversion with collections|
|producer|models|match?|
|{name: 'Audi', models: [{name: 'A3'}, {name: 'A4'}]}|[{name: 'A3'}, {name: 'A4'}]|true|

Fixture

class JsonObjectsConversionWithCollectionsFixture {
    CarProducer producer

List<CarModel> models

boolean match() { producer.models*.name.containsAll(models*.name) } }

Domain classes

class CarProducer {
    String name
    static hasMany = [models: CarModel]
}

class CarModel { String name }

Query Fixture DSL (since 0.4)

To make writing Query fixtures much easier, we've introduced the concept of a simple mapping DSL. This means that mapping values from, let's say a services, becomes almost trivial.

Consider the following Service method:

def checkInventory() {
    Book.executeQuery("select b.title, b.author, count(*) from Book b group by title, author")
}

If you want to use this method in a Fixture, you can do by using the mapping DSL. An example can be shown below. Note that this only works for Query fixtures!

class CheckBookInventoryFixture {
    static queryFixture = true                              // indication that this is a query fixture
    static mapping   = [title: 0, author: 1, amount: 2]  // the mapping

def bookService // injected service

def queryResults() { // queryResults() method, which must be named like this! bookService.checkInventory() } }

The mapping property determines how the query results will be mapped before being sent back to FitNesse. The keys of the map are column names from the FitNesse query table for the given fixture. The values might be indexes of columns returned by the implementation of queryResults method (i.e. if they are results from a executeQuery) or property names (i.e. if queryResults returns a collection of domain objects). The mapping property can also be a list of property names if property names of the result map one to one to table column names. An example can be found below:

class BookService {
     List<Book> checkInventory() {
        return Book.list()
     }
}

class CheckBookInventoryFixture { static queryFixture = true // indication that this is a query fixture static mapping = ["title", "author", "amount"] // a different mapping

def bookService // injected service

def queryResults() { // queryResults() method, which must be named like this! bookService.checkInventory() } }

or:

class CheckBookInventoryFixture {
    static queryFixture = true                              // indication that this is a query fixture
    static mapping = ["title":"objectTitle", "author":"theAuthor", "amount":"amount"] // a different mapping, where the key is the name of the test, and the value the property name of the object

def bookService // injected service

def queryResults() { // queryResults() method, which must be named like this! bookService.checkInventory() } }

Since 0.9 you have to declare both queryFixture and mapping properties as static. It wasn't necessary before but the behaviour wasn't always consistent thus the support for non static properties was dropped.

Strings as methods

Groovy supports methods like "this is a method". The Fitnesse plugin also supports this, making some Fixtures more readable.

Example

class MyFixture {
  boolean "check if customers exists"(int customerNumber) {
     // …
  }
}

Default arguments

Groovy supports default arguments. The Grails Fitnesse plugin also supports this:

class MyFixture {
  MyFixture(boolean clearDatabase = false) {
    // …
  }
}

Wiki:

|my fixture|true|

Untyped arguments

Groovy supports untyped method arguments. The Grails Fitnesse plugin also supports this:

class MyFixture {
  boolean checkCustomer(customerNumber) {
    // …
  }
}

Note that the Fitnesse SLIM protocol only supports Strings and Lists. A result of this, is that when using untyped arguments, things could go wrong. An example of this is when using an integer. This integer is interpreted as being a String, and hence it's converted to it's value, so int 1 becomes int 49. So, if you're unsure, use types in your fixtures.

Automatic reloading of Fixtures

The Fixtures in the grails-app/fitnesse directory are automatically reloaded and injected by Grails. This enables faster testing and faster development!

Functions are getters

Fitnesse decision tables do not have getters and setters, but setters and functions. A function is the same as a getter, but without the 'get' part. (Still with me?). An example:

Normal Fitnesse

|my decision fixture|
|digit | roman?|
|1     |      I|
|5     |      V|

This would result in the following Fixture:

class MyDecisionFixture {
    int digit
    String roman

void execute() { roman = RomanNumberConverter.convertDigit(digit) }

String roman() { return roman } }

This has been improved, so that Fitnesse also looks at getters:

Improved Fitnesse

This would result in the following Fixture:

class MyDecisionFixture {
    int digit
    String roman

void execute() { roman = RomanNumberConverter.convertDigit(digit) } }

Improved Stop Test Exceptions

You can now throw StopTest Exceptions from Fixture constructors, to halt all further test execution. This is currently not handled correctly in the Java version of Fitnesse.