Tuesday, December 23, 2008

Lest We Forget

I have been working on a German web application for the past 2 years, so that means I end up dealing with message keys a lot. Where possible it is nice to have these resources in the markup file and not cluttering up the java code (unless the text has some dynamic component to it). The designer can move the text around and style it as they please.

In Apache Wicket we can happily use tags in the markup to fetch the localised message text. That is all good until you deploy it to production and someone has forgotten or mistyped the message key. The default Apache Wicket settings mean you won't get an error message, instead default text in the tag will be shown. If your developers have been putting in text that is almost right, you might not notice the problem. If they have used rude jokes, well, let's hope you notice them.

Or we could go for a Test-Driven Development approach. Let's make the application fail quickly in development if the message key is missing. No more forgetting.

First, we can create a jUnit test here /src/test/java/[package]/MissingResourcesTestPageTestCase.java

import java.util.MissingResourceException;

import org.apache.wicket.PageParameters;
import org.apache.wicket.WicketRuntimeException;
import org.apache.wicket.util.tester.WicketTester;
import org.junit.Before;
import org.junit.Test;

public class MissingResourcesTestPageTestCase {

private WicketTester tester;

@Before
public void setup() {
tester = new WicketTester(new WicketApplication());
}

@Test(expected = MissingResourceException.class)
public void testMissingResourcePage() throws Throwable {
try {
tester.startPage(MissingResourcesTestPage.class, new PageParameters());
}
catch (final WicketRuntimeException wre) {
throw wre.getCause();
}
}
}
We could have changed the test to expect a WicketRuntimeException, but these can occur for many different reasons, such as the markup not existing at all. We want the test to fail if the resource could not be found.

Sometimes I prefer creating the basic page first. Just the constructor so we can reference it from the unit test. The MoreUnit plugin for Eclipse can even create the jUnit test from the page with a keyboard shortcut. We can write this test first then use our IDE to create the /src/test/java/[package]/MissingResourcesTestPage.java file

import org.apache.wicket.markup.html.WebPage;

public class MissingResourcesTestPage extends WebPage {

public MissingResourcesTestPage() {
//do nothing to test markup rendering
}
}
Running the test now will fail because the markup does not exist. You can create an empty file called /src/test/java/[package]/MissingResourcesTestPage.html and re-run the tests and it should still fail.

Finally, add the markup

<html>
<body>
<wicket:message key="this.resource.key.is.missing">this message resource is missing for testing purposes</wicket:message>
</body>
</html>
and run the test again. red. Wicket is working correctly and displaying the default text. So let's change it to start throwing exceptions.

Alter your /src/main/java/[package]/WicketApplication.java to override the init() method as follows:

public class WicketApplication extends WebApplication {
@Override
protected void init() {
super.init();
getResourceSettings().setUseDefaultOnMissingResource(false);
getResourceSettings().setThrowExceptionOnMissingResource(true);
}
}

setUseDefaultOnMissingResource(false) will mean Wicket won't try to use the default text inside the wicket:message tag when it can't find the resource key. Now it will just display nothing, which won't help our future tests. To cause an exception to be thrown you need to call setThrowExceptionOnMissingResource(true).

Run the test. Yay, green bar!
Done, done, done!

Anytime in the future that one of our developers creates a page and makes a typo, forgets to add the resource key, deletes a key, renames the resource file etc they will get a nice failed message when they run the tests. As long as they create tests to render the page. All developers do that, don't they?

Pretty Source Code

Ok, I have set up the syntax highlighter so I can display code like this

public class Abc {
public Abc() {
int xyz = 10;
}
}

Monday, December 22, 2008

First Post!

I have got to get this first post out of the way so I can start talking about more interesting things. So here goes...

I thought I would start a blog to share my experiences over the past few years with Test-Driven Development (TDD) and Apache Wicket. No doubt it will wander off into other areas such as Agile, Scrum, and Continuous Integration.

Ok, first post is done. done. done!