Skip to content

grails testing tips

alxndrsn edited this page Oct 18, 2011 · 2 revisions

# Grails testing tips

Running tests in Grails is not very quick, so anything that can be done to speed up the tests is helpful - both for the original implementer of a test and the corresponding code, and for others running the test suite later.

N.B. we use Spock and Geb for Grails testing, and some of these tips may be specific to those frameworks.

## Write the simplest tests possible Unit tests are faster than integration tests, and integration tests are faster than functional tests. So only write a functional test if you are testing specific workflows, and only write an integration test if you need interactions between multiple classes or GORM methods (criteria, dynamic finders etc.).

Run as few test classes as possible

If you're implementing code to pass a test, or trying to fix a test you've broken, there's no need to run the whole test suite.

Running a specific phase

You can restrict a test run to a specific phase (e.g. test, unit, integration) like so:

grails test-app unit:

Running a specific test class

You can run a specific test class like so.

grails test-app Inbox

Note that we did not need to write InboxTests or InboxSpec, as test classes have these suffixes by convention.

Run multiple test classes

You can run multiple test classes by specifying each of them:

grails test-app Inbox Outbox

Running all tests in a package

To run all tests in a package you can use wildcards:

grails test-app frontlinesms2.message.*

More wildcards

You can be even more cunning with wildcards, e.g. to run all Controller tests:

grails test-app *Controller

Being more specific

You can combine multiple test matchers to restrict phase and test class(es), e.g.

grails test-app functional: frontlinesms2.message.*
grails test-app unit: *Controller

Run as few test methods as possible

If there are a number of tests within the class that you're running, but you're currently only interested in one specific test method, you can prevent others in that class from running by applying the @spock.lang.IgnoreRest annotation:

class MySpec extends GebSpec {
	def 'test one'() { ... }

	@spock.lang.IgnoreRest
	def 'test two'() { ... }

	def 'test three'() { ... }
}

Now to run only MySpec.'test two'():

$ grails test-app functional: My

Check your assumptions

When running functional tests, it's easy to make assumptions about why they might be failing, but it's worth actually running the application and manually following the steps in the test to see what happens. It's also useful sometimes to carefully watch the automated tests playing out - this way you can sometimes spot race conditions in asynchronous JavaScript calls, bad JavaScript syntax (using the FireFox Error Console) or broken GSPs which might not otherwise be reported.

Don't sleep!

It's a code smell if you see calls to sleep() in functional tests. Instead, you should be using waitFor.

waitFor the right event

In functional tests with asynchronous JavaScript, make sure that the assertion(s) in your waitFor closure are checking the last thing that the previous action should have triggered, rather than the first, as otherwise you are opening yourself up to potential race conditions.

Further reading

For more info on grails testing, RTFM