Problem solved - and I tracked it down to how I defined my testcase
constructor, which lead to a bad interaction with JUnit. My code was
like this:
public MyTestCase(String testName) {
super(new MyUISpecAdapter());
}
I did this because I was already using the "named" constructor in my
original testcase (it was coded for an older version of JUnit which
required the String arg) and because the "named" ctor in
UISpecTestCase does not set the adapter - and there is no way to set
it later. And I didn't want to use the system property method as I
will have different adapters for different testcases.
The problem with my code is that, if a named constructor (with a
String argument) is available, the JUnit framework will call it
instead of calling the anonymous (no argument) one (see
TestSuite.createTest). And since in the implementation above I do
*not* propagate testName, I ended up triggering an assertion deep
inside JUnit (which IMHO should have a reason string associated with
to make it easier on us users).
So the solution was to change the constructor to:
public MyTestCase(String testName) {
super(new MyUISpecAdapter());
setName(testName);
}
From this exercise, I would like to suggest a small change in the
UISpecTestCase implementation. Currently there are only two ways to
set the adapter: 1) through a constructor and 2) through a property.
The second one forces you to have one adapter for the entire JUnit
execution, which too limiting if you have a large suite of tests that
exercise different components (unless I am missing something too
obvious, that is).
So I believe in practical terms users will use the constructor-based
approach. But it can lead to problems like the one above (different
constructors leave the object in different states) and it also imposes
an execution flow that may not be a good match for some applications.
In my particular scenario the UI classes are implemented on top of a
threading framework that requires some initialization; to be able to
pass the adapter in the testcase constructor I had to move a lot of
logic around, from the testcase to the adapter.
Instead of the constructor-based initialization, I would add a simple
protected setter to the UISpecTestCase class to allow the user to set
the adapter later in the constructor, or even in the setUp() method.
This would support more flexible execution flows. In this case the
constructor would become:
public MyTestCase(String testName) {
super(testName);
//... initialization here if necessary
setAdapter(new MyUISpecAdapter());
}
or even better:
public MyTestCase(String testName) {
super(testName);
}
public void setUp() {
super.setUp();
//... initialization here if necessary
setAdapter(new MyUISpecAdapter());
}
Other then that, I am quite happy :-) I ported a few testcases from
Abbot to UISpec and they not only were cleaner (less code) and faster
(calls to Thread.sleep() removed) but also more powerful - for example
ListBox supports the selection of multiple indexes, while in Abbot I
had to "fake" multiple selection using shift-clicks. Everything worked
just fine!
Many thanks,
Nascif