Matt RaibleMatt Raible is a Web Architecture Consultant specializing in open source frameworks.

10+ YEARS


Over 10 years ago, I wrote my first blog post. Since then, I've authored books, had kids, traveled the world, found Trish and blogged about it all.

Testing GWT Applications

Last week, I did some research on GWT, how to test it and code coverage options for tests that extend GWTTestCase. The reason I did this is because I've found that most of the GWT tests I write have to extend GWTTestCase and I'd like to have code coverage reports. Read below for more information on my findings for testing GWT classes.

There are quite a few articles about testing GWT applications. Here are a few samples:

The main gist of these articles is that you should structure your code to make the core functionality of your application testable without having to depend on GWTTestCase.

All of them also advocate using an MVC or MVP (Model View Presenter) pattern. Currently, I'm using GXT and its MVC Framework. Unfortunately, GXT's MVC doesn't have much documentation. The good news is there is a good article that explained enough that I was able to refactor my project to use it.

The unfortunate side of this refactoring was I discovered that classes that extend GXT's MVC Framework have to be tested with GWTTestCase. The downside to extending GWTTestCase is there is it's difficult to create code coverage reports.

GWT's issue 799 has some patches that should make code coverage possible. I tried to implement code coverage with Eclipse and EclEmma using this README, but failed. In the process, I discovered an issue with Eclipse 3.4 and JUnit on OS X. Reverting to Eclipse 3.3 solved this problem, but I was still unable to make EclEmma work with GWT.

After failing with Eclipse, I tried to use the emma-maven-plugin. I was also unable to get this to work, with my findings documented in this thread.

Finally, I did have some luck with getting IDEA's built-in code coverage feature working. However, after getting it to work once, it failed to work for the rest of the day and I haven't had success since.

Code Coverage and GWT
Because of these issues with GWT 1.5 and code coverage, I think I'll wait until GWT 1.6 to worry about it. The good news is 1.6 M1 was released last Friday. If continuing to use GWTTestCase becomes an issue, I may write my own MVC Framework that doesn't use classes that call native JavaScript. Hopefully GXT MVC's framework will provide a good example.

In addition to trying to get code coverage working, I used the internets to figure out how run GWT tests inside of Eclipse and IDEA. I don't remember the resources I used, but hopefully this up-to-date documentation will help others. The nice thing about using an IDE to run these tests is they typically execute much faster.

Running GWT Tests in Eclipse
You should be able to run most of your GWT tests from within Eclipse using the following steps.

  1. Right-click on a test that extends GWTTestCase and go to Run As > JUnit Test. It's likely you will see the error message below.
    Invalid launch configuration: -XstartOnFirstThread not specified.
    
    On Mac OS X, GWT requires that the Java virtual machine be invoked with the
    -XstartOnFirstThread VM argument.
    
    Example:
      java -XstartOnFirstThread -cp gwt-dev-mac.jar com.google.gwt.dev.GWTShell
    
  2. To fix this error, go to Run > Open Run Dialog. Click on the Arguments tab and add the following values. The 2nd value is to increase the amount of memory available to the test and avoid an OOM error.
    -XstartOnFirstThread -Xmx512M
  3. When you re-run the test, you will probably see the following error:
    com.google.gwt.junit.JUnitFatalLaunchException: The test class 'org.richresume.client.home.HomeControllerGwtTest' 
    was not found in module 'org.richresume.client.Application'; no compilation unit for that type was seen
      at com.google.gwt.junit.JUnitShell.checkTestClassInCurrentModule(JUnitShell.java:193)
      at com.google.gwt.junit.JUnitShell.runTestImpl(JUnitShell.java:628)
      at com.google.gwt.junit.JUnitShell.runTest(JUnitShell.java:150)
      at com.google.gwt.junit.client.GWTTestCase.runTest(GWTTestCase.java:219)
    
  4. To fix this, open the Run Dialog again, click on the Classpath tab and click on User Entries. Click on the Advanced button and select Add Folders. In the Folder Selection dialog, select your source and test directories (e.g. src/main/java and src/test/java).
  5. Run the test again and you should see a green bar in your JUnit tab.
  6. To create a JUnit configuration that runs all tests, duplicate the previously mentioned run configuration. Then change the name to "All Tests" and select the 2nd radio button to run all tests in the project.
  7. Click Run to execute all the tests in the project.

Running GWT Tests in IDEA
You should be able to run your GWT tests from within IDEA using the following steps.

  1. Right-click on a test that extends GWTTestCase and go to Run "TestNameGwtTes...". It's likely you will see the error message below.
    Invalid launch configuration: -XstartOnFirstThread not specified.
    
    On Mac OS X, GWT requires that the Java virtual machine be invoked with the
    -XstartOnFirstThread VM argument.
    
    Example:
      java -XstartOnFirstThread -cp gwt-dev-mac.jar com.google.gwt.dev.GWTShell
    
  2. If you get a compiler error instead, you may need to add the GWT Facet to your project. To do this, right-click on your project's top-most folder in the left pane. Select Module Settings > Facets and enable GWT for your module.
  3. To fix the -XstartOnFirstThread issue, go to Run > Edit Configurations. Add the following values to the VM Arguments field. The 2nd value is to increase the amount of memory available to the test and avoid an OOM error.
    -XstartOnFirstThread -Xmx512M
    NOTE: If you still get a compiler error, see this page for a possible solution.
  4. Run the test again and you should see a green bar in your Run tab.
  5. To create a JUnit configuration that runs all tests, duplicate the previously mentioned run configuration. Then change the name to "All Tests" and change the Test configuration to search for tests in the whole project.
  6. Run the new configuration to execute all the tests in the project.

Testing GWT applications isn't as straightforward as writing JUnit tests, but I do believe it's getting better. If you have any additional tips and tricks, please let me know.

Posted in Java at Feb 09 2009, 03:27:36 PM MST 6 Comments
Comments:

Nice tutorial!

I am currently in the process of refactoring a GWT-App that was built around "Autonomous View" (aka the big class that contains everything from event handling to rpc aka untestability in person) to "Supervising Controller" approach. It is inspired by the blog posts you mentioned. It is too bad that GWT does not have some kind of application framework that enforeces best practices. Additionally all of the examples are mostly trivial and dont show how to effectively structure your code. It is annoying that GWT does not include a "Store"-like API, but forces you to explicetly add Items to widgets. One needs special skills in writing testable UI logic to avoid writing messy, untestable code.

Logically spoken there are views with widgets, that register on controllers. The controller then adds an event listener to that widget to notify other widgets/update the model/do some RPC. Inside RPC-onSuccess a update-method of the widget is called or the model is updated which triggers the update of another widget. For that I use a Property class inspired by this here.

I have had some success so far, because most of the application logic is put into plain java classes and is therefore easy to unit test. The classes that are not taken into coverage reports are XYViewImpl-classes that basically just instantiate some widgets. I am quite ok with that, since there is no real logic in there that could fail. Although coverage would still be nice.

Posted by Sakuraba on February 10, 2009 at 01:24 AM MST #

Matt,

I'm using a GWT port of PureMVC found here:

http://code.google.com/p/purevmc4gwt

I think it's 100% Java code and the documentation is really good.

Posted by Chris on February 10, 2009 at 01:23 PM MST #

Matt,

There's definitely not much to know in the GXT MVC.

1) Model
The impl is a map (ugh?)

2) AppEvent
- This is like a bucket, you can throw anything into it
- Can be marked for history-able
- Use int for type (ugh? but I guess enum wouldn't work well across views/controllers)
- You pass AppEvent around View and Controller (and Dispatcher)

(We added our own history type so we can control history)

3) Controller
- Can be nested (Parent controller contains a list of child controllers)
- Need to register AppEvent.type in order to know if it can handle it or not (recursively ask child if parent can't do it).
- Can forward to View
- Can forward to child Controller
- main brain is handleEvent() (think of it like the dispatcher for the controller)
- RPC async-call should be handled/executed here (?)

4) View
- Can fire event (AppEvent) back to the Controller it is associated with
- I usually instantiate my widgets here
- All widgets related listener/activity/action should be around here (?)

5) Dispatcher
- This could also be a Controller I think
- The brain, the center, the master
- Add controllers to it and call dispatch()
- Most controllers send back the AppEvent to the Dispatcher and let the Dispatcher figure out the next step (fire and forget?)
- Does the history (if the AppEvent history is set).

Hope that helps.
Ed

Posted by Edwin on February 10, 2009 at 03:23 PM MST #

While we're at the topic of TDD, UI and et al. You may want to check this project:

http://code.google.com/p/google-gin/

It might be helpful for testing (or it may not be at all). The nice thing about GIN is that the project came out from Google itself (some employees decided to port Guice to GWT, could've been Guice developers themselves).

Unfortunately I'm in between TDD and non-TDD in terms of testing UI. I felt that the best way to test the UI is to do it manually and with the help of limited automation. Because by doing manually, you could catch weird errors, usability issues and other things that TDD might not be able to do so. Rich UI is hard to test, it's just the limitation of the tool.

For myself, personally I don't want to waste my time writing unit-tests that always break when someone tweaked the UI a bit. This has happened in my previous works whether it is desktop or web-app. The effort has never paid off.

Posted by Edwin on February 10, 2009 at 11:46 PM MST #

The scope of my Unit Tests in GWT are "do the surroundings of my view classes bring the data/state correctly to the views?".

I dont think you can do "user-acceptance"-tests with unit-tests, but you can create "trivial views" that dont fail that easily, because they dont care about RPC, events from other widgets etc. It then allows you to rework RPC without breaking the views or switching from Gwt-Ext to SmartGWT without having to rewrite your data access logic.

Posted by Sakuraba on February 11, 2009 at 01:23 AM MST #

Is anyone using ant to run your junit tests?

My tests work great in eclipse but can't get ant to run them: http://groups.google.com/group/google-web-toolkit/browse_thread/thread/c55919acee65c503?tvc=2

Posted by javaunixsolaris on November 19, 2009 at 01:13 PM MST #

Post a Comment:
  • HTML Syntax: Allowed