Automated tests for GSP views in Grails

Friday 26th February, 2010

Test-driven development (TDD) is handy if used sensibly, and we’re feeling the need to make our automated tests a little broader. The Grails site has great documentation on setting up tests for Controllers and Services, but I couldn’t find a decent explanation of how to set up tidy automated tests for GSPs… so without further ado this is what I did.

I want tests to be:

  • Easy to write (and hence read)
  • Low maintenance, i.e. I don’t want to have to update tests whenever I make changes that aren’t important to the test
  • Good at picking up unexpected behaviour rather than changes to HTML structure

Running your GSP from TestApp

Grails ships with a handy class called GroovyPagesTestCase which allows your test to get the output of a given GSP file given a defined input, like this:

def file = new File("grails-app/views/myview.gsp")
def model = [someVariable:12345]
def htmlString = applyTemplate( file.text, model )

We’re passing in the text from the GSP file as a template, along with a model comprised of whatever variables and mock objects the view should need.

Now I’ve got a string containing a bunch of HTML, okay, that’s the right direction but my lazy gene is not satisfied yet.

Note 1: If your template calls other templates then it makes life easier to use absolute URLs, e.g. templateUrl"/>

Note 2: This method assumed you’ll specify an explicit model for each sub-view, e.g. myObj:myObj]}"/>

From a sticky HTML mess to something useful

The easiest way to get from unparsed HTML to a useful searchable structure seems to be Groovy’s XMLSlurper. It parses XML rather than HTML by default, but you can instantiate it with a more HTML-friendly parser like TagSoup like so:

def slurper = new XmlSlurper( new org.ccil.cowan.tagsoup.Parser() )
def parsedHtml = slurper.parseText(text)

Easy.

Pulling it all together

import grails.test.GroovyPagesTestCase
import org.ccil.cowan.tagsoup.Parser

class GspXyzTests extends GroovyPagesTestCase
{
	boolean transactional = false
	def slurper = new XmlSlurper( new Parser() )

	// This test looks for a specific thing in the resulting parsed HTML
	void testSomeImportantOutput() {

		//Open file containing GSP under test
		def file = new File("grails-app/views/myfolder/template.gsp")
		assertNotNull(file)

		//Obtain result of GSP page
		def text = applyTemplate(file.text, [
			pagenumber:123,
			pagesize:10,
			someMockObject:[
				foo:"bar",
				nestedMockObject:[
					[id:12345],
					[id:67890]
				]
			]
		])

		def html = slurper.parseText( text )

		// test some aspect of the parsed structure, the trick would be to make the test resilient to a degree of cosmetic change
		assertEquals 1, html.head.meta.list().findAll{ it.@name?.text().toLowerCase() == "robots" }.size()

	}

}

Making QA easier with Selenium

Friday 13th June, 2008

Earlier this week I wrote a summary of a few ways you can automate and test your Javascript, including the use of the Selenium platform by OpenQA. I say platform because there are several very different ways you can use the Selenium family of programs. In this post I’ll expand on the ones I’ve used.

Developer and Regression Testing

Lets face it, testing *that* screen for the 14th time in a row can get pretty tedious, especially if you have to start from a fresh session and go through half a dozen screens on the way there.

That’s where Selenium IDE comes in. SIDE is a Firefox extention that saves you time by allowing you to record a test once in your browser, and save it. You can then replay that test whenever you like, sitting back while Firefox speeds through your test for you. You can also build assertions into your test so that specific conditions will make it fail.

If you build up a library of tests you can run them all as a batch, while you get on with something else.

Continuous Integration Testing

SIDE is great for when you’ve got a developer or tester sitting in front of a browser, but what about automated tests? In a Continuous Integration environment, checking new code into source control triggers a automated build to happen, usually with associated unit tests. That’s all great for classes and modules that suit unit testing, but what about higher-level testing?

That’s where Selenium RC comes in. RC stands for Remote Control, which makes sense when you understand what it does. Selemium RC is a collection of APIs for most popular programming languages that allows your code to control an actual instance of a browser (it supports Safari, IE and Firefox) and run tests against it.

You can set up a build script that runs through your library of regression tests and reports the results back to you. This means that once you’ve recorded a few different runs through one of your website processes, you can then have those tests run automatically whenever someone checks code into source control.


Automating Javascript Testing

Tuesday 10th June, 2008

If you’re putting together a software application you probably want to think about setting up build environment, and applications that use a lot of Javascript are no different. A little time invested will probably save headaches down the line. Being able to perform single-click builds of your app is really useful, as explained by Joel Spolsky.

Back in 2005 I started putting together an app (Newsdesk) for Moreover that included what turned about to be about 6000 lines of Javascript. The build environment I came up with wasn’t perfect, and could never remove the need for actual human testing, but it saved an awful lot more work than it took to build. In this article I’ll outline a few ways you can achieve something similar.

Setting up a build

If you’re reading this you should know about encapsulation, the process of restricting outside knowledge of the inner workings of a component. In large systems this is a fundamental “Good Idea”. In compiled systems it’s simple to encapsulate classes and then have them compiled into more monolithic chunks to make them easier to distribute (DLLs, JARs, EXEs, whatever). Usually your IDE/compiler will take care of this for you.

In Javascript a self-disciplined coder can do the same thing. Rather than having one or two large files, you can split your code up into encapsulated components and have them concatenated together into your final files at build-time. This build script can also serve as a platform for code hygene, unit testing, and regression testing.

The core build script

I’d recommend using ANT, (or NANT if you’re using Dot Net). ANT is a flexible, modular, and powerful build program that you can configure to do just about whatever you want. It feels a little strange to write procedural instructions in XML, but once you get over that it’s simple. Using a basic ANT script you can get the latest code from source control, compile it, move it around, rename it, run tests, send an email with the build result to your team, FTP it to your server, or pretty much anything else you can think of.

My build script did roughly this to the Javascript:

  • Iterate the build number and add it to the code’s config file
  • Running unit tests
  • Concatenating code and language files into packages
  • Running code compression on packages (removing comments, whitespace, etc)
  • Generating Javascript code reference

…but you could also include

  • Regression testing
  • Code duplication analysis
  • GZip pre-compression
  • Deploying code to specified server

Build script configuration

If you’re writing a build script you probably ought to think about running it in a couple of modes, because you usually have more than one use case for your build.

Firstly you’re going to want a relatively quick dev build that does quick testing and spits out your compiled code to a local development environment. This might also run some analysis depending on your requirements.

Secondly you might want an occasional analysis build that runs code hygene analysis, runs more in-depth tests, that sort of thing.

Lastly, you might want a deployment build, that retrieves only a specific version (latest, codebase version X, or codebase as of date Z) and outputs a zip or tarball of the compiled codebase ready to be archived and/or copied to servers.

Testing your Javascript

This might seem a bit hard to automate until you discover Rhino. Mozilla’s Rhino engine (in Java) and SpiderMonkey (in C) are invaluable for running Javascript either under a shell or embedded in other applications. Putting Rhino’s JAR file into your classpath allows your build to execute Javascript.

If you want to run JSLint over your source, you can do that. If you want to write your own code analysis tool in JS you can do that too.

This is great for unit testing, but with a UI unit testing can only get you so far. If you want to be a bit more thorough you need regression testing. This can be achieved using Selenium. Selenium is a Javascript-based regression testing engine that allows you to trigger DOM events and test assertions against the resulting DOM. Although this engine is browser-based, you can also call it from code, or ANT, using secondary tools like Selenium RC (Remote Control). There’s also a Firefox plugin that allows you (or your QA team) to build up a library of regression tests that can be run automatically on each build.

More…

I’ve tried not to get into too much detail this time. When I get round to it I might write up areas in more detail. Let me know if you’re interested in something particular.