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:
@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
expect(stackPathConstructor.constructPathsForJavaScriptStack("core")).andReturn([])
expect(coreStack.getStacks()).andReturn([])
expect(coreStack.getStylesheets()).andReturn([])
expect(coreStack.getInitialization()).andReturn(null) JSONObject
expected = new JSONObject("{\"activate\":[\"$expectedFieldId\"]}")
linker.setInitialization(InitializationPriority.NORMAL, expected)
replay() def jss = new JavaScriptSupportImpl(linker, stackSource,
stackPathConstructor) cls jss jss.commit() verify() } @Test void
simple_autofocus() { autofocus_template "fred", { it.autofocus
FieldFocusPriority.OPTIONAL, "fred" } } @Test void
first_focus_field_at_priority_wins() { autofocus_template "fred", {
it.autofocus FieldFocusPriority.OPTIONAL, "fred" it.autofocus
FieldFocusPriority.OPTIONAL, "barney" } } @Test 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.

--
Posted By Howard to Tapestry Central at 8/19/2010 03:11:00 PM

Reply via email to