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:
- Test-First GWT
- Test driven development for GWT UI code
- Test driven development for GWT UI code with asynchronous RPC
- Enabling Test Driven Development in GWT client code
- JUnit tests for widgets - thread about which components to test.
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.
- 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
-
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
- 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)
- 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
andsrc/test/java
). - Run the test again and you should see a green bar in your JUnit tab.
- 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.
- 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.
- 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
- 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.
- 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. - Run the test again and you should see a green bar in your Run tab.
- 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.
- 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.