Poll: unit tests source code layout / GWTTestCase vs. EasyMock

187 views
Skip to first unread message

Thomas Broyer

unread,
Sep 14, 2009, 5:29:07 AM9/14/09
to Google Web Toolkit, rj...@google.com
[Ray, I'm CC'ing you because I believe you have an opinion/answer on
the matter]

Hi all,

Here's dilemma I believe many of us are facing, namely how to organize
the source code of unit tests when you have both GWTTestCase and "pure
java" JUnit tests using EasyMock (or any other mocking lib).

The problem:
I place my unit tests in the same package as the classes under test
(that's common practice, and it helps for some tests to have package-
scope methods on your class-under-test); this means that I might have
in the same package (or within subpackages of the same *.client
package) both GWTTestCase and pure-JUnit tests using EasyMock.
That's not really a problem, tests run OK, *but* because they're all
in the 'client' source path of the same GWT module, I have warnings
when the GWTTestCase's run (when GWT compiles the module; it finds the
EasyMock classes and signals that it cannot find the source code so it
discards it and the JUnit test). Again, this is only just warnings,
because the JUnit tests using EasyMock won't be run by GWT (so the
optimization phase would have discarded them).
But I find those warnings a bit annoying; distracting at best.

So here's my question: what are you doing in your projects?

And here are possible answers:
1. just ignore the warnings; only pay attention to the tests success/
failures
2. use a <super-source/> with dummy EasyMock implementations (it works
very well, all methods throwing UnsupportedOperationException, just in
case)
3. separate the tests into two source "branches" (instead of src/...
and test/... as you can see in GWT for instance, use src/..., test/...
and gwt-test/...) and do not include pure-JUnit tests when running GWT
tests (this means running GWTTestCase and pure-JUnit tests separately,
in two runs of JUnit)
4. use a naming convention (MyClassJavaTest vs. MyClassGwtTest) and
use a <source path="client" exclude="**/*JavaTest.java" /> (tested,
works very well too)
5. Another approach, please detail!


Here's an (adapted) excerpt from my code (note: I'm using JUnit 4
here, but that doesn't change much thing to the issue, except that
you'll have warnings with JUnit 4's classes too). You'll see how I
test the same class using both EasyMock (for the major part) and
GWTTestCase (when I hardly have the choice).

package com.atolcd.gwt.place.client;
...
public class PlaceManagerImpl {
@Inject
public PlaceManagerImpl(EventBus eventBus) {
...
if (GWT.isClient()) {
History.addValueChangeHandler(new ValueChangeHandler<String>
() {
public void onValueChange(ValueChangeEvent<String> event)
{
onHistoryChange(event.getValue());
}
});
}
}
...
/* package */void onHistoryChange(String newToken) {
...
}
}
...
package com.atolcd.gwt.place.client;
...
public class PlaceManagerImplJavaTest {
@Test
public void testFiresPlaceChangeEventOnHistoryChange() {
EventBus bus = createMock(EventBus.class);
...
replay(bus);

PlaceManagerImpl pm = new PlaceManagerImpl(bus);
...
// simulates an history change
pm.onHistoryChange("test");
...
verify(bus);
}
}
...
package com.atolcd.gwt.place.client;
...
public class PlaceManagerImplGwtTest extends GWTTestCase {
@Override
public String getModuleName() {
return "com.atolcd.gwt.place.Place";
}

public void testHistoryIsBeingUpdatedOnPlaceChange() {
...
assertEquals("test", History.getToken());
}
}

Daniel Wellman

unread,
Sep 15, 2009, 8:01:56 AM9/15/09
to Google Web Toolkit
We chose #3 - two separate source folders for tests and GWTTestCases.
This also meant that we could easily run all the fast tests when we
wanted quick feedback about a change.

If you wanted to remove the need for the GWTTestCase, could you create
an interface that wraps the History object? I don't know enough about
how your code works, but perhaps you could inject a mock
implementation of the History object and ensure that it gets invoked
with the right state; in your example it looks like it wants to be
notified with the token "test". However, if there's other stuff going
on in that method, then this approach might not work.

Dan
Reply all
Reply to author
Forward
0 new messages