Ad-Hockery

ad-hockery: /ad·hok'@r·ee/, n. Gratuitous assumptions... which lead to the appearance of semi-intelligent behavior but are in fact entirely arbitrary. [Jargon File]

Testing Callbacks With Spock Mocks

I’ve been doing some work with vert.x over the last few days and trying to develop components that are test-driven. Like any asynchronous framework rather than having methods that return a value you pass a callback Closure that gets invoked at some point in the future with the result. This makes it tricky to write unit tests that mock out collaborators as you might in a traditional app.

Spock Killer Features: The ‘Old’ Method

I use Spock almost exclusively to test Groovy or Java code these days. It’s got some fantastic features that other test frameworks don’t have. Some of them aren’t that well known or documented, though.

The old method is possibly my favourite Spock feature. It’s a simple thing but really enhances test legibility. It’s also great for wowing developers new to Spock because it looks like black magic at first glance.

Semi-RESTful Scaffolded Controllers

The default Grails scaffolded controllers use a create action to render a form and a save action as the target the form will POST to. If the save action succeeds it redirects to show and if it fails due to constraint violations it re-renders the form. The same applies to editing with the edit and update actions.

There’s a slight quirk here in that a failed save will cause the URL to change from /controllerName/create to /controllerName/save. Not a particularly huge issue, after all it’s not something a search spider will see and users will be very unlikely to care. One thing I have found problematic though is when rendering a navigation element that highlights an item based on the current action.

Twitter Bootstrap & Semantics

There’s a lot to like about Twitter Bootstrap; it’s a fantastic resource for getting off the ground, particularly for getting a slick-looking admin interface up and running quickly. The recent changes to accommodate responsive layouts are really impressive. I’m particularly impressed with the way horizontal forms stack on smaller screens (failure to accommodate small screens in form design is something I’ve complained about before). However, there are some things I’m less keen on…

Optional Tag Bodies

Sometimes you may want to implement a Grails GSP tag that has an optional body. Grails tag closures take one or two arguments, the first a map of the attributes passed to the tag the second a Closure representing the tag body. Even if the tag was not invoked with a body the second argument is not null so doing this does not work:

1
2
3
4
5
6
7
def myTag = { attrs, body ->
  if (!body) {
      // render a default body
  } else {
      // render the supplied tag body
  }
}

It turns out that if the tag did not have a body the argument passed to the Closure is always the same constant, so what you can do is:

1
2
3
4
5
6
7
8
9
import org.codehaus.groovy.grails.web.pages.GroovyPage

def myTag = { attrs, body ->
  if (body.is(GroovyPage.EMPTY_BODY_CLOSURE)) {
      // render a default body
  } else {
      // render the supplied tag body
  }
}

Wiring Taglib Dependencies in Grails 2 Unit Tests

Grails 2 has made a lot of improvements in unit testing support. One of the things I always used to find particularly painful was unit testing taglibs. Now when your test class is annotated with @TestFor(MyTagLib) you can use the applyTemplate method like this:

1
2
expect:
applyTemplate('<my:tag/>') == 'the expected output'

However, one thing I found is that it’s quite tricky to wire a dependency in to the taglib instance that’s used by the applyTemplate method.

Organizing Functional Tests

I posted a few days ago about functional testing & some of my frustrations, focusing mainly on the technical issues. I did touch on test organization in terms of modelling behaviour rather than page structure. As Luke Daley has pointed out the two aren’t fundamentally in opposition and I’ve been giving this some further thought.

I think the crux of the issue is that functional tests, end-to-end tests, acceptance tests, whatever you want to call them are not the same thing as unit tests. They’re not really even just a higher level of the same thing. Yet on the projects I’ve worked on we’ve generally carried on as though they were.

Unit tests are associated almost on a one-to-one basis with units of code. When you execute grails create-controller Foo the framework generates a skeleton controller and a unit test for it. You certainly shouldn’t be slavishly beholden to the one unit test class per production class habit but it’s generally reasonable. Each unit test describes the behaviour of a single unit of the software. I don’t think the same association is appropriate for functional tests but we often end up using it anyway.

I’ve tried to distil some rules of thumb from all this.

Upgrading to Grails 2: Part 1

We’ve recently spent some time ensuring that our application is forwards-compatible with the upcoming Grails 2. Our app is broadly split into the application itself and a large plugin that forms the core of our CMS. We upgraded the plugin first as it contains the core domain classes but is also a slightly smaller task to tackle. I’ll write up our findings when we’ve completed upgrading the application itself in a follow-up to this post.

Although it took a little while I found the upgrade less painful than some previous versions. It feels like Grails is really maturing so there are fewer fundamental breaking changes and more in the way of new features. The bulk of the changes we had to make were to unit tests which are vastly improved in Grails 2. That said, I can see some of the things we ran into stumping people so I thought a write-up would make a useful reference. Some of these items may already be covered by the upgrading section of the Grails user guide but some, particularly around plugins are probably new.

Welcome to the New Ad-Hockery

I’ve finally taken the plunge and migrated Ad-Hockery from Blogger to the stupendously awesome Octopress platform as suggested to me by Andreas Arledal. The old blog will remain available and links to the old posts are maintained in the Archive section here.