Putting test data in its place

Posted by Chris Ramsdale - Thursday, February 11, 2010 at 2:13:00 PM

Inevitably, as your app grows, you will find areas that involve consuming large amounts of textual data and performing some action as a result. You may be handling a JSON response, a serialized GWT RPC payload, or HTML that has been rendered on the server. In any case, you're a test-driven developer and you know that you have a handful of automated tests just wanting to be applied. The example below is one way of constructing such tests. And while it's not rocket science per say, it's so simple and useful that we felt compelled to tell others about it.

So let's say you're doing some server-side rendering, and somewhere in your code you most likely have a permutation of the following:

DOM.createDiv().setInnerHTML(foo);

Once inserted, you might apply some style, inject some values into the resulting HTML, etc.. Basically with the DOM structure in place, the rest of your app can move and do its thing. And "its thing" is often the more complex part, which begs for a test case. You want to make sure the "thing" it's doing is the right thing.

So at this point you happily code up a few GwtTestCase(s) and suddenly realize two things. One, "foo" can be really long, is a pain to maintain in code, and is ultimately polluting your test cases. Two, "foo" is most likely to change as your app grows, whereas your test cases shouldn't. Wouldn't it be nice if you could abstract "foo" away into a file that you load into your test cases, just as you do with other non-GWT test cases? Well, the good news is that you can. Much like other resources (e.g. ImageResource, CssResource, etc...), GWT has a mechanism for embedding text files into your app by specifying an associated TextResource within a ClientBundle. For example:

public interface TestResources extends ClientBundle {

  @Source("com/google/gwt/example/test/ExampleTest.dat")
  TextResource foo();

}

Here Example.dat would contain the HTML that I want load into my test case, and given that it's strictly for testing purposes you'll notice that I've added it under the "example/test" folder. At this point we have a ClientBundle from which we can grab the contents of our Example.dat file. In order to do something meaningful with this, we'll use it in a newly constructed GwtTestCase:

public class ExampleTest extends GWTTestCase {

  TestResources resources;

  public String getModuleName() {
    return "com.google.gwt.example.Example";
  }

  public void gwtSetUp() {
    resources = GWT.create(TestResources.class);
  }

  public void testFoo() {
    DOM.createDiv().setInnerHTML(resources.foo().getText());
    /*
     * insert complex code to be tested
     *
     */
    }
  }
}

Using this technique we've managed to keep our test cases clean, and centralized any test data changes within ExampleTest.dat rather than the ExampleTest source code. So clean, so simple, and hey, it even works when you want to load up some JSON data to test with.

No comments: