The Google Web Toolkit (GWT) provides a base testing class called GWTTestCase which enables testing of JavaScript code inside a headless hosted mode browser. However, GWTTestCases are fairly slow to start up, as they compile your module's code and start up and shut down a browser before every test method.
So when should you use a GWTTestCase to test your view code, and when should you refactor to a design which doesn't require the GUI components at all?
When the time comes to test the view, take a moment to consider what you're testing. Should the test ensure that clicking a widget generates a click event? That would confirm that GWT behaves as expected, but I believe it was J.B. Rainsberger who said, “Don't test the framework”. What about if a widget is the right shade of blue? This is subjective and a human is much better at this sort of judgment. However, a behavior that seems worth testing is that the color switches from the “OK” color to the “Error” color when a problem occurs. Another useful test would be to check that a display string is assembled properly from its underlying data.
Ultimately, all the scenarios test application logic, and these are easily testable. Here are a few strategies:
Put the logic in the model. Since the data required by the logic is usually available in the model itself, it makes sense to place it there. This is often appropriate for display-specific strings; you'll need to make sure that your widgets use this new display String, but that may be checked visually.
Put the display logic in the presenter or another testable helper. If you start getting too many view-specific methods on the model object, you can move this functionality to the Presenter itself or a display helper object. This also might be a good place for the logic that calculates a display color given an object state.
Don't use an automated test. Sometimes things are too simple to break, and you can rely on some targeted exploratory testing. For example, displaying a person's name as the display value for a radio button by using the Person object's getName() method is a pretty trivial bit of code. Whether this is acceptable to you or not depends on how worried you are that it will break. If you're worried, a test is probably warranted.
Use a GWTTestCase to instantiate the component and test its contents. While GWTTestCases can't deal with event propagation, they can handle simple widget state tests – in fact, many of the test cases for GWT itself rely on this strategy. Many people recommend avoiding writing any widget-based GWT tests, and their concern is valid – these tests are slow and depend heavily on the GWT internals. However, for a few small, targeted cases this worked well for my team. This may be the only choice if you're building a reusable widget for a component library and want to make sure that it behaves as expected.
Here are some excellent references for designing GUIs for Testability:
- Martin Fowler's bliki on GUI Architectures
- Michael Feathers' "The Humble Dialog Box"
- Jeremy D. Miller's articles on Building your own CAB for .NET
- Rob van Maris demonstrates the Supervising Controller pattern for GWT
Comments
You can follow this conversation by subscribing to the comment feed for this post.