Gaelyk

Test driving development of Gaelyk applications

Agenda

Introduction

Unit testing with Gaelyk Spock Helpers

Functional testing with Geb and Gaelyk Functional Test Tools

Live TDD demo

About Me

Grails Developer at BSkyB

Groovy user since 2010

Groovy and Open Source enthusiast

Geb committer

Gaelyk committer

Contributed to other Groovy projects: Grails, Gradle and Codenarc

TDD practitioner

This-code-is-not-clean-moaner ;)

3 simple questions on Gaelyk

Gaelyk

Created by Guillaume

A lightweight Groovy toolkit for Google App Engine

Applications built using Groovlets and Groovy Templates

Own URL routing system

Lots of syntactic sugar for GAE datastore and services

So, how do I test it?

Gaelyk Spock Helpers

Initially created by Marco Vermeulen (@marcoVermeulen)

Maintained by Vladimír Oraný (@musketyr)

Provides base Spock specification classes for testing Groovlets and routes

Targeted at making it easier to write unit tests for Gaelyk applications

Uses service mocks from appengine-testing and Spock mocks where service mocks are unavailable or it's more convenient

Base specifications

GaelykUnitSpec

ConventionalGaelykUnitSpec

GaelykRoutingSpec

Basic example - code

basicGroovlet.groovy located in src/webapp/WEB-INF/groovy/

request.hello = "Hello ${params.name}!"
forward '/WEB-INF/pages/hello.gtpl'

Basic example - test

class BasicGroovletSpec extends GaelykUnitSpec {
    void setup() {
        groovlet 'basicGroovlet.groovy'
    }

    void 'hello message is constructed'() {
        given:
        basicGroovlet.params.name = 'Gaelyk'

        when:
        basicGroovlet.get()

        then:
        basicGroovlet.request.hello == 'Hello Gaelyk!'
    }
}

Basic example - conventions

class BasicGroovletSpec extends ConventionalGaelykUnitSpec {
    void 'hello message is constructed'() {
        given:
        basicGroovlet.params.name = 'Gaelyk'

        when:
        basicGroovlet.get()

        then:
        basicGroovlet.request.hello == 'Hello Gaelyk!'
        basicGroovlet.forward == '/WEB-INF/pages/hello.gtpl'
    }
}

Other GaelykUnitSpec features

Read and modify variables in Groovlet binding

Verify interactions with the response to check what was written out

Check state of the datastore and GAE services after Groovlet execution

See what has been logged

Routes example - code

get '/about', forward: '/WEB-INF/pages/about.gtpl'
post '/number/@number',
    redirect: '/number.groovy?number=@number',
    validate: { number.isNumber() }

Routes example - test

class RoutesSpec extends GaelykRoutingSpec {
    void setup() {
        routing 'routes.groovy'
    }

    void 'about route'() {
        expect:
        with get('/about'), {
            matches
            redirectionType == FORWARD
            destination == '/WEB-INF/pages/about.gtpl'
        }
    }
...

Routes example - test

...
    void 'number route for not a number'() {
        expect:
        !post('/number/NaN')
    }

    void 'number route'() {
        expect:
        with post('/number/123'), {
            matches
            variables.number == '123'
            redirectionType == REDIRECT
            destination == '/number.groovy?number=123'
        }
    }
}

What else is supported?

Verify routes for put, delete and all methods

Test ignored routes

Check email and jabber routes

Test routes with single and double star wildcards

Assert route caching

Test capability-aware routes

Verify namespaced routes

Testing the whole stack?

Why functional tests?

Template outputs

JavaScript

Integration of all layers

Everything you're not able to unit test

Running Gaelyk functional tests

Gradle GAE plugin supports running functional tests since 0.7

gradle gaeFunctionalTest

Tools

Geb

Gaelyk Remote Control

Gaelyk Functional Test Tools

Geb

It's a browser automation solution

Can be used for acceptance testing of web applications

WebDriver under the hood

JQuery-like content selection

Page Object modeling of content

Adapters for multiple test frameworks:

Gaelyk Remote Control

Allows to run arbitrary code in a remote Gaelyk application

Slightly modified version of Groovy Remote

Adds all Gaelyk specific variables to the context of commands

Installed by adding an endpoint served by RemoteControlServlet

Works only in local mode

Gaelyk Functional Test Tools

Simplifies accessing remote application with Gaelyk Remote

Easy way to clean up datastore after test execution

Provides a DSL to set up datastore state

Allows to login into the application with a single method call

Let's get our hands dirty

"Testing has to be made easy, otherwise it will never get done"

Luke Daley

Links

Questions?

Slide Notes…