5 Tutorials - Reference Documentation
Authors: Erik Pragt (jWorks.nl), Marcin Erdmann, John Engelman
Version: 2.0.3
5 Tutorials
5.1 Integration testing
This tutorial describes the creation of a simple application and how to test it.1. Create your Grails application.
$ grails create-app bookstore $ cd bookstore
2. Install the plugin.
$ grails install-plugin fitnesse
3. Start the Grails server.
$ grails run-app
4. Start the Fitnesse server.
Since Fitnesse is bundled with the plugin, there's no need to download anything.The following will extract Fitnesse and start it on the default port, 9090.$ grails run-fitnesse
5. Create the test
Open a web browser and point it to http://localhost:9090 . The Fitnesse front page will show up.Click on Edit, and add the following to the text area:^BookStoreTest
. Press Save.You will now have a text with a question mark next to it. Click on the question mark to create a new page.In the new page, remove the contents of the text area and replace it by the following:!define TEST_SYSTEM {slim}
!define COMMAND_PATTERN {echo}|import|
|bookstore||create book inventory|
|author|title|amount|
|Stephen King|IT|3|
|Dean Koontz|Chase|5||script|buy book scenario|
|customer buys|2|books with title|IT|
|customer buys|1|books with title|Chase||query:check book inventory|
|author|title|amount|
|Stephen King|IT|1|
|Dean Koontz|Chase|4|
The COMMAND_PATTERN should (currently) have a dummy value! I have chosen 'echo' since I'm on a Mac, but for Windows users you need to create a batch file, for example, echo.bat, without any contents. The reason for doing this is that Fitnesse normally starts a Slim Server itself. However, in our case, our Grails application starts the Slim Server for us. So, to prevent starting the server, we use a dummy command pattern.In this test, you've used 3 kinds of Test tables:
- a Decision Table (
create book inventory
) used to setup the data - a Script Table (
buy book scenario
) to execute the test - a Query table (
check book inventory
) to verify the results of the test
Could not invoke constructor for CreateBookInventory[0]
. This is because no Fixtures have been created yet. This way of working is in line with the 'Red-Green-Refactor' TDD mantra; our test clearly is red (or yellow, in this case), so we need to focus on getting the test green. To make the test pass, we need to create the fixtures.6. Creating the Fixtures
We'll start by creating the first Fixture mentioned in the error message, which is theCreateBookInventory
Fixture. To create the Fixture, use the Grails task @create-fitnesse-fixture. You can involve the script by typing the following:$ grails create-fitnesse-fixture CreateBookInventory
in the
grails-app/fitnesse/bookstore@ directory.Because the Fitnesse plugin will reload the Fixtures automatically, pressing the Test* button in the Wiki will already show that the Fixture has been loaded correctly, and the cell is colored green by Fitnesse. If for some reason this doesn't work, please restart the Grails application, and try again.Now, we'll have to create the author, title and amount properties in the Fixture and the corresponding Book domain class.Note, Grails might crash due to the Fixture missing the domain classes. Whenever this happens, please restart Grails.
6.1 The Decision Table
The Fixture to support the Decision Table should look like this:class CreateBookInventoryFixture { String author String title int amount def bookService CreateBookInventoryFixture() { Book.list()*.delete() } void execute() { amount.times { bookService.addBook(new Book(author: author, title: title)) } } }
execute
method. This method is called after input parameters have been set, but before any output parameters are requested. This allows us to have a place to do something with the input, and prepare the output.The Book class like this:class Book { String author String title }
class BookService { static transactional = true def addBook(book) { book.save() } def buyBook(title) { Book.findByTitle(title).delete() } def checkInventory() { Book.executeQuery("select b.title, b.author, count(*) from Book b group by title, author") } }
6.2 The Script Table
The Script Fixture to execute the Script Table should look like this:class BuyBookScenarioFixture {
def bookService void customerBuysBooksWithTitle(int amount, title) {
amount.times {
bookService.buyBook(title)
}
}
}
Note that this implementation is very simplistic. In this example, I simply delete the books from the inventory instead of assigning them to a customer or a basket.
6.3 The Query Table
Finally, to verify if our assertions match the execution of our code, we need to check the results of our actions. We do this by using a Query Table.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 is used here to map the column names to the position of the values returned by the queryResults method. For more information, please check the 'Query DSL' part in the 'Features' documentation.Now, when running the Test again in Fitnesse, everything should be green, and you have your first test running. Not you can refactor your code if you want, and check if the result is still valid by rerunning the Tests!