Over a million developers have joined DZone.
Platinum Partner

Groovin' on the Testin'

· Java Zone

The Java Zone is brought to you in partnership with ZeroTurnaround. Discover how you can skip the build and redeploy process by using JRebel by ZeroTurnaround.

I'm at the point now where I'm writing Groovy code for (virtually) all my unit and integration tests. Tapestry's testing code is pretty densely written ... care of all those explicit types and all the boilerplate EasyMock code.

With Groovy, that code condenses down nicely, and the end result is more readable. For example, here's an integration test:

void basic_links() {
clickThru "ActivationRequestParameter Annotation Demo"

assertText "click-count", ""
assertText "click-count-set", "false"
assertText "message", ""

clickAndWait "link=increment count"

assertText "click-count", "1"
assertText "click-count-set", "true"

clickAndWait "link=set message"

assertText "click-count", "1"
assertText "click-count-set", "true"
assertText "message", "Link clicked!"

That's pretty code; the various assert methods are simple enough that we can strip away the unecessary parenthesis.

What really hits strong is making use of Closures though. A lot of the unit and integration tests have a big setup phase where, often, several mock objects are being created and trained, followed by some method invocations on the subject, followed by some assertions.

With Groovy, I can easily encapsulate that as templates methods, with a closure that gets executed to supply the meat of the test:

class JavaScriptSupportAutofocusTests extends InternalBaseTestCase
private autofocus_template(expectedFieldId, cls) {
def linker = mockDocumentLinker()
def stackSource = newMock(JavaScriptStackSource.class)
def stackPathConstructor = newMock(JavaScriptStackPathConstructor.class)
def coreStack = newMock(JavaScriptStack.class)

// Adding the autofocus will drag in the core stack

expect(stackSource.getStack("core")).andReturn coreStack



JSONObject expected = new JSONObject("{\"activate\":[\"$expectedFieldId\"]}")

linker.setInitialization(InitializationPriority.NORMAL, expected)


def jss = new JavaScriptSupportImpl(linker, stackSource, stackPathConstructor)

cls jss



void simple_autofocus() {

autofocus_template "fred", {
it.autofocus FieldFocusPriority.OPTIONAL, "fred"

void first_focus_field_at_priority_wins() {
autofocus_template "fred", {
it.autofocus FieldFocusPriority.OPTIONAL, "fred"
it.autofocus FieldFocusPriority.OPTIONAL, "barney"

void higher_priority_wins_focus() {
autofocus_template "barney", {
it.autofocus FieldFocusPriority.OPTIONAL, "fred"
it.autofocus FieldFocusPriority.REQUIRED, "barney"

That starts being neat; with closures as a universal adapter interface, it's really easy to write readable test code, where you can see what's actually being tested.

I've been following some of the JDK 7 closure work and it may make me more interested in coding Java again. Having a syntax nearly as concise as Groovy (but still typesafe) is intriguing. Further, they have an eye towards efficiency as well ... in many cases, the closure is turned into a synthetic method of the containing class rather than an entire standalone class (the way inner classes are handled). This is good news for JDK 7 ... and I can't wait to see it tame the class explosion in languages like Clojure and Scala.

The Java Zone is brought to you in partnership with ZeroTurnaround. Discover how you can skip the build and redeploy process by using JRebel by ZeroTurnaround.


Published at DZone with permission of Howard Lewis Ship , DZone MVB .

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}