Skip to main content

Grails and Continuous Integration: An Essential Combo

June 23, 2009

{cs.r.title}







Grails is a fantastic framework. As well as being ultra-productive and fun to work with, it encourages good testing practices, and provides a swathe of tools to make writing unit, integration, and web tests a real pleasure. As we will see, Grails also lends itself quite well to build automation. However, Grails is not Maven. Grails has a fairly loose concept of the software development lifecycle, and is happy to let you bundle up and deploy your application as a WAR file without running all the unit and integration tests first. A Continuous Integration (CI) server can help you keep the flexibility of the Grails development process, and still ensure that your code is fully tested for each and every code change. In this article, we will take a look at how you can introduce Continuous Integration into your Grails project. More specifically, we will walk through how you can automate your Grails testing and code quality metrics with Hudson, a popular open source CI tool.

Hudson Meets Grails: Preparing Your CI Server

You can use pretty much any modern Continuous Integration server to automate your Grails builds. However, in this article, we will be using Hudson. Hudson is exceptionally easy to use, and comes with a very usable Grails plugin. To get started with Hudson, just download the latest version from the Hudson website, and run it from the command line:


$java -jar hudson.war

This will start Hudson running on the default port of 8080; go to http://localhost:8080 to check it out.

The easiest way to use Grails in Hudson is to install the Hudson Grails Plugin via the Plugin Manager screen, which you will find in the Manage Hudson screen (see Figure 1). Once the plugin has downloaded, you will need to restart Hudson for the plugin to take effect.

The Hudson Grails Plugin
Figure 1. The Hudson Grails plugin is the most convenient way to work with Grails in Hudson

Finally, you need to go to the Configure System screen and give Hudson the path of your Grails installation (see Figure 2). Hudson might manage to find Grails on the system path, but I like things to be clear and well defined, especially for a build server. Once this is done, you are ready to start.

Configuring the Grails plugin in Hudson
Figure 2. Configuring the Grails plugin in Hudson

Automating Your Grails Unit Tests

One of the most fundamental features of a Continuous Integration environment is Continuous Testing. Whenever code changes are made, the full test suite is executed to ensure that nothing has been broken by the change. Indeed, without a comprehensive set of unit and integration tests, Continuous Integration loses much of its added value. So setting up some automated unit tests in Hudson is a logical first step in our quest to automate the Grails build process.

Grails provides a clean distinction between unit tests and integration tests, and places them in separate directories. In Grails, unit tests are placed in the test/unit directory. They are designed to run fast, with no framework or database. Grails 1.1 comes with a powerful testing library (originally a plugin in Grails 1.0) that makes it easy to mock out domain objects and test everything from the domain classes to the controllers in isolation. For example, the mockDomain() method will add validation methods such as validate(), and mocked-out persistence methods such as save() and find(), so that you can easily unit test field validation and controller classes without having to load up the entire Grails application context. For example, here we verify a simple business rule that should be encoded in the Address domain class:

import grails.test.*
import static org.hamcrest.Matchers.*
import static org.hamcrest.MatcherAssert.assertThat

class AddressTests extends GrailsUnitTestCase {

  void testStreet1ShouldNotBeEmpty() {

    mockDomain(Address)

    def address = new Address(street1:'')

    assertThat address.validate(), is(false)
    assertThat address.errors.street1, is("blank")
  }
  ...
}

These libraries make coding unit tests easy, and, even better, they are lightning fast. It really is a good idea to write your tests as Grails unit tests wherever it is practical to do so. If you want to run the unit tests by themselves, you can do so by providing the -unit option when you call grails test-app:


$ grails test-app -unit

Let's set this up in Hudson. First, create a new freestyle build job (using the New Job menu). You will need to configure the Source Code Management section to work with whatever source code repository you are using, and then decide how you want the build to be triggered. If you are not sure, select Poll SCM here, and provide an appropriate frequency such as @hourly or */10 * * * *. This last value will check for changes every 10 minutes, and trigger a build if any changes are detected.

Next, let's add the build. In the build section, when you click on "Add build step," pick the Build With Grails option. This gives you a number of options, including the Grails targets to be run, as well as directory options and some command line parameters. You can invoke several targets in the same line, which is not the case when you run Grails on the command line. However, you do need to enclose each command, including its arguments and options, in double quotes.

Adding a build step for the Grails unit tests
Figure 3. Adding a build step for the Grails unit tests

The actual Grails command we are invoking here is the following:


$ grails test-app -unit --non-interactive

Note the --non-interactive option. Under normal circumstances, Grails builds are quite chatty, and they often prompt you for extra information, such as whether you want to upgrade one of your plugins. If this happens when your build is running on Hudson, your build will come to a grinding halt and wait until some kind soul answers its question. Which, of course, will never happen. Indeed, one of the tenets of any Continuous Integration architecture is that a build should be able to run without human intervention, using only the resources downloaded from the source code repository. The --non-interactive option, introduced in Grails 1.1, is the workaround for this issue. With this option, any queries will be automatically answered with the default option (which is usually a sensible choice), and the build will continue.

Finally, in the post-action builds, you can publish your JUnit test reports. Remember, Grails is Groovy and Groovy is Java, and the Grails testing frameworks have a solid foundation in Spring and JUnit. So all you need to do is point Hudson to the test/reports directory, and it will find everything it needs to report on your test results (see Figure 4).

unit test results
Figure 4. Hudson reports on Grails unit test results

Automating Your Integration Tests

Grails integration and functional tests are slower and more heavyweight, but also more comprehensive. During these tests, Grails creates an in-memory database, or, depending how you have set up your application, uses a proper test database. It also loads up a full Spring and Hibernate application context. And, if you are running web tests of any kind, it will start up a web server in the background for your tests, just for good measure. These tests let you exercise all the components of your application from end to end, to see how they work together. Needless to say, this all can take a bit of time. Because of this, I like to run the unit tests in a separate build job, followed by the integration tests in a subsequent step.

Like the unit tests, you can run integration tests in isolation, by using the -integration option. Maven users should note that this will run only the integration tests, not the unit tests followed by the integration tests. You can set up a Hudson build job to run your integration tests by using the -integration option in the Grails build step.


$ grails test-app -integration --non-interactive

Another approach is to run all of the tests in this second testing phase. Including the unit tests usually increases the overall time taken for these builds very marginally, and it makes it much easier to integrate accurate code coverage metrics, which we will cover further on.

Automating Functional and Web Tests

Web testing is a tricky business, but Grails goes out of its way to provide useful tools for the job. There are Grails plugins for both Selenium and Canoo Webtest, as well as the very promising Functional Test plugin. For this example, we will be using the third option, though similar integration techniques work for both the Selenium and Canoo Webtest tests. You can install the Functional Test plugin into your project as shown here:


$ grails install-plugin functional-test

This plugin is based on the HTMLUnit library, and fits in very nicely with the Grails approach. Functional test cases go in their own directory (the test/functional directory), and test results are generated in the standard JUnit format. The HTMLUnit library also makes for very clear and readable test cases. A very simple test case is shown here:


	class RegisterListingFunctionalTests extends
                 functionaltestplugin.FunctionalTestCase {
	    void testDisplayRegistrationForm() {
	        get '/listing/edit'
	        assertStatus 200
	        assertContentContains 'Sign up now!'
	    }

	    void testRegistrationPageShouldDisplaysErrorMessageIfNoFieldsEntered() {
	        get '/listing/edit'
	        click 'submit'
	        assertContentContains 'Sorry...'
	        assertContentContains 'You need to fill out all the required fields.'
	    }
	...
    }

These tests will run whenever you run the normal Grails tests. They produce normal JUnit test reports that Hudson can process. The plugin starts up your web application on a local Jetty server, running on port 8080 by default. Of course, you may need to modify this option if the port 8080 is already being used. You can do this by setting the port you want in the server.port option (see Figure 5).

Setting up integration and functional tests
Figure 5. Setting up integration and functional tests

Integrating Code Coverage Reports

Code quality metrics in the Groovy space are relatively young. One promising new project called CodeNarc provides some simple static analysis rules for Groovy (similar to Checkstyle for Java), but is not quite ready for seamless integration with Hudson just yet. Code coverage, on the other hand, is well catered for by the open source Cobertura project, which handles Groovy code just fine.

Code coverage is a very useful code quality metric that indicates how much of your code has been executed by your test cases. While it is not in itself a guarantee of high-quality testing, it is certainly very handy for determining what code hasn't been tested at all, and as a general indicator of how well testing practices are being applied.

Code coverage in Grails is easy. Just install the Test Code Coverage plugin, as shown here:


$ grails install-plugin code-coverage

Now, whenever you run your Grails tests, code coverage data will be collected, and an HTML code coverage report generated. To integrate with Hudson, however, we will need to produce XML code coverage data, using the -xml option, as shown below.


$ grails test-app -xml --non-interactive

You will also need to install the Hudson Cobertura plugin into your Hudson installation, and to tell Hudson that your build will be producing coverage data, and where to find it (see Figure 6). With this done, Hudson will produce the sort of coverage report shown in Figure 7.

Configuring code coverage reports in Hudson
Figure 6. Configuring code coverage reports in Hudson

Hudson generates very readable code coverage reports
Figure 7. Hudson generates very readable code coverage reports

Code coverage is an extremely processor-intensive task, so you don't want to use it for every build. If you want to skip the code coverage for a particular build (for example, during the unit tests build job), you can use the -nocoverage option. On a typical set of unit tests, this option can make the builds run much faster.

Conclusion

Grails is an excellent, highly productive development framework that positively encourages good development and testing practices. In this article, we have seen how to set up a Continuous Integration build job to compile and test your Grails application in Hudson. We also looked at how to separate unit tests from integration tests, and saw a few tricks of the trade that are useful to know when you automate your integration and functional/web tests. Finally, we saw how to integrate code coverage metrics into your build.

Resources


width="1" height="1" border="0" alt=" " />
John Ferguson Smart is a freelance consultant specialising in Enterprise Java, Web Development, and Open Source technologies, currently based in Wellington, New Zealand.
Related Topics >> Programming   |   Testing   |   

Comments

Thanks!

Great guide. It mostly works for me. One problem I have is that currently when a test fails the whole build is counted as failed. So I cannot distinguish failed compilations and failed tests. Do you know any way to distinguish between compilation and test failures? Best Anders