Marcin Erdmann

Groovy, Grails, Geb...

Including and excluding Spock specifications from execution using a configuration file

It's a common requirement to be able to execute just a subset of your tests in a given situation. Or just run the quick tests locally and run everything on CI. And Spock being an excellent testing framework obviously supports it.

In the past I used Spock's @IgnoreIf and @Require built-in extensions to exclude/include certain specs under given conditions. An example usage for marking some tests to be only run as a part of the CI build could be:

@Require({System.properties.containsKey('ciBuild')})
class SlowSpec extends Specification { ... }

@Require annotation takes a closure. When the closure evaluates to true the annotated specification will be executed otherwise it will be ignored. As you might expect it becomes pretty cumbersome to have to copy that closure body all over the place if you have several specifications that you wish to annotate. Not to even mention what would you have to do if the logic in the closure had to change. What I came up with in the past was to create a class that extends from Closure and implements doCall() just as the javadoc for Closure class suggest.

@InheritConstructors
class CiBuild extends Closure<Boolean> {
    Boolean doCall() {
        System.properties.containsKey('ciBuild')
    }
}

@Require(CiBuild)
class SlowSpec extends Specification { ... }

It turns out that there is an easier way of doing this. Spock has a configuration mechanism - by default it looks for a SpockConfig.groovy script in classpath. In that script you can configure the test runner to include and exclude specifications based on how they're annotated as well as on what class they're extending. So given an annotation class:

@Retention(RetentionPolicy.RUNTIME)
@Target([ElementType.TYPE, ElementType.METHOD])
@Inherited
public @interface Slow {
}

And an annotated spec:

@Slow
class SlowSpec extends Specification { ... }

If we create a resource file called SpockConfig.groovy with the following contents:

runner {
    if (!System.properties.containsKey('test.include.slow')) {
        exclude Slow
    }
}

Then by default the SlowSpec will be excluded. On the other hand if you set test.include.slow system property for test execution then all your tests will be executed. You can also be more specific in what you want to skip by only applying the annotation to certain feature methods.

If you don't want to use annotation but want to explicitly exclude some specifications in the configuration file you can use specification class or base class:

runner {
    if (!System.properties.containsKey('test.include.slow')) {
        exclude SlowSpec
    }
}

The only documentation I could find on how to use the configuration file is in javadoc for RunnerConfiguration class. Spock is very powerful but its documentation could use some love...

Using Remote Control plugin to log in into a Grails application with Spring Security backed authentication

In my previous post I wrote about how much I like using grey box testing as a technique for writing functional tests. One common scenario where you could use it is to log in into the application in your tests without having to go to the login page and filling the credentials every single time you need to test something that is available only to logged in users of your system.

Some people will argue that you shouldn't be logging in for every single test that needs the user to be authenticated to be performed. They will use different ways not to have to do so like stepwise Spock specifications or not clearing cookies between tests. But I don't agree with that and I'm happy to pay the price of that little bit of overhead. By starting every single tests from always the same, clear, consistent state, setting up all prerequisites and then clearing cookies and your database afterwards you avoid test bleed which is often hard to track and can lead to flakey tests.

On the other hand it doesn't mean that you shouldn't be smart about the way you're setting up your tests to save time. Not going through the frontend every single time but logging in programmatically is one way to achieve it. A thing to remember here is that because you're not testing it indirectly when using this technique you should always have a test that verifies that authenticating using the frontend works as expected.

The most popular Grails authentication plugin is Spring Security Core Plugin. All that you need to do to programmatically log in in a test into an application that is using Spring Security Core plugin is to authenticate and then drop a JSESSIONID cookie in your browser:

class AuthenticatedSpec extends GebSpec {

    RemoteControl remote = new RemoteControl()

    void setup() {
        def sessionId = remote {
            ctx.springSecurityService.reauthenticate('user', 'password')
            RequestContextHolder.requestAttributes.request.session.id
        }

        if (!driver.currentUrl.startsWith(config.baseUrl)) {
            to LoginPage
        }

        driver.manage().addCookie(new Cookie('JSESSIONID', sessionId))
    }
}

Thanks to the fact that we have access to main application context in remote control closures (via ctx) we can retrieve the springSecurityService bean and call reauthenticate() on it as suggested by Burt Beckwith in this post. Session id can be retrieved from RequestContextHolder. Finally, we make sure before dropping the cookie that the browser is pointing at the tested domain as it won't allow you to drop a cookie for a domain that it's not pointing at - this will only be the case for the first test or if a test ends up outside of the domain you're testing.

Verifying that Groovy Remote Control endpoint is exposed in your application

I'm a big fun of grey box functional testing of web applications. I understand grey box testing as setting up your test (for example bootstraping data in db that the test requires) programmatically instead of via the UI. Sometimes you will also want to do parts of your verification in this way.

Some people use fixture endpoints for that but I'm not a fan of this solution for two reasons: the fixture code lives along your production code and fixture endpoints are a nightmare to maintain - what people end up doing is to have one endpoint with a lot of setup for all the tests which bootstraps a lot of data that is not essential to every single test... Oh, and there is one more reason - you want your test setup to live as close to your test as possible.

There is a better solution to this problem available for JVM apps - Groovy Remote. It provides an endpoint that allows you to send groovy closures to the remote application that get executed in the JVM of that application. It ships with a servlet class and also a class that starts up a simple http server with the endpoint so you can use it in a variety of scenarios - for both container and standalone apps. There is a Grails plugin available and I also created a Gaelyk compatible version.

Quite often when using Groovy Remote you want to be able to manually verify that the endpoint is exposed under a certain url and that it isn't exposed when deployed to production. I will show how it can be done using curl when using Grails Remote Control.

To get a Groovy Remote endpoint in your Grails app all you need to do is install the plugin via BuildConfig.groovy:

plugins {
    compile ":remote-control:1.4"
}

Assuming that we called our Grails app remote-control-test the remote control url will be http://localhost:8080/grails-remote-test/grails-remote-control. Let's start the application in dev mode, grails run-app, and verify that the endpoint is not exposed via a simple curl POST:

'curl -i --data "" -s http://localhost:8080/grails-remote/grails-remote-control | head -n 1'

We should get the following as the result:

HTTP/1.1 404 Not Found

When running the app in prod environment (grails prod run-app) we should get the exact same result. On the other hand if we are expecting the endpoint to be exposed like for example when running in test environment (grails test run-app) we can use a slightly different curl command:

'curl -i --data "" -s http://localhost:8080/grails-remote-test/grails-remote-control | egrep "(HTTP/1.1 415 Unsupported Media Type|Only remote control commands can be sent)" -o'

The expected result is:

HTTP/1.1 415 Unsupported Media Type

Only remote control commands can be sent

Only remote control commands can be sent

By default the Remote Control endpoint is only exposed in test environment. You can enable it for other environments by adding the following to your Config.groovy:

environments {
    qa {
        remoteControl.enabled = true
    }
}

Then run your app using grails -Dgrails.env=qa run-app and verify that the endpoint is exposed using the previously mentioned curl commands.

New in Gradle 1.6: task ordering

Recently Gradle 1.6 has been released. I was lucky enough to get a lot of support from the Gradle team in the means of implementation guidance and code reviews for contributing a new feature: task ordering. Currently it's an icubating feature (see here what it means) and only "must run after" ordering is supported, though it's highly likely that other rules, like for example "should run after" with a slightly less restrictive contract, are coming.

Let's look at a trivial example:

task a
task b {
    mustRunAfter a
}

Executing gradle b will only execute b but executing gradle b a will first execute a and then b. So if both a and b are in the task graph for a given build run then b will run after a (just like if b depended on a) but requesting to run b won't pull a into the task graph (contrary to what would happen if b depended on a).

"Must run after" ordering is useful if you want to specify an ordering between two tasks but only if both of them are in the graph - the fact that the task that must run after another task is in the graph doesn't automatically mean that the task it must run after will be. This comes handy for example when you want to run unit tests before integration tests as there is usually no point in running integration tests if unit tests fail, but still being able to run integration tests on their own. Luke Daley came up with a more sophisticated use case - running all verifications (e.g. checkstyle, tests) on all projects (if they are to be executed in this build) before uploading anything. e.g. gradle clean build uploadArchives will only upload after all projects have been built and tested, but gradle uploadArchives will upload archives without running the tests:

allprojects {
    tasks.withType(Upload) {
        allprojects {
            mustRunAfter tasks.matching { it instanceof VerificationTask }
        }
    }
}

To specify "must run after" ordering between tasks you should use the Task.mustRunAfter() method which accepts a task instance, a task name or any other input from this list.

Gradle Golo Plugin released!

I'm happy to announce the first public release of Gradle Golo Plugin. The plugin allows to build and run code written in Golo using Gradle.

You can have a look at the docs and the example project to learn how to use it.