To use CoverageDecorator on existing set of unit tests I
wrote a separate file called CoverageTest.java, which
contains just a suite() and main() methods. Where
CoverageTest.suite() construct a set of
CoverageDecorators into a suite.
Why?
1. Allows me to run unit tests with or without coverage.
More often I use naked tests during development.
2. Tests do not have hansel dependency and can be ran
by people who has no hansel installed, just junit
3. This way I can add coverage testing to existing tests
without source modification.
It would be nice to further develop that approach
of "optional" coverage decoration. One step can be
reuse of suite() methods of Test classes.
Sometimes we need to decorate a test with another
decorators, like junit.extensions.TestSetup. In this
scenario it does not work CoverageDecorator, because
CoverageDecorator calls new TestSuite(testClass) to
construct a TestSuite. The same way it does not work
with non-standard TestCases, like
junit.extensions.ExceptionTestCase, because new
TestSuite() could not be constructed.
Alternatively it can invoke testClass.suite() by using
reflection. This way if test class has suite() method
already decorated they all would work together.
There are two caveats:
1. What if there is no suite() defined in test class. Then
we will can continue with new TestSuite().
2. What if suite() contains CoverageDecorator. We can
come to an infinite loop. One way to detect it is to set a
lock on test class object and check it before calling suite
()
The above approach can be also used with in-test class
coverage decoration, not only "optional". In that case
we can have two methods:
suite(), which can have other decorators and
coverageSuite(), which will be something like usual:
{
return new CoverageDecorator(testclass, new Class[]
{testee});
}
If someone need to run tests with coverage all the time,
they can use in main:
{
junit.textui.TestRunner.run(testClass.coverageSuite());
}
It should work transparently for all current users of
CoverageDecorator, but you can create a separate
class, like
org.hansel.CoverageDecoratorThatCallsSuite. It would
satisfy my needs equally. Thank you very much.
Logged In: YES
user_id=52085
What do you think about doing this the other way round:
suite() still returns a CoverageDecorator, but
CoverageDecorator uses the Suite returned by coveredSuite(),
if available:
public class SomeTest extends TestSuite {
public Test suite() {
return new CoverageDecorator(SomeTest.class, ...);
}
public Test coveringSuite() {
TestSuite result = new TestSuite();
result.addTest(...);
...
return result;
}
}
This way a coverage test is always performed for this class.
Requiring the user to use
junit.textui.TestRunner.run(testClass.coverageSuite());
to start the coverage test is imho not a very good idea,
because with many test runners (for example ant) you just
specify the names of the tests to be run ("run *Test.java").
I think in that case the only place that needs to be changed is
CoverageDecorator.createInstrumentedTest() (line 88):
[pseudocode]
Class clazz = cl.loadClass(testClass.getName());
if (clazz.hasMethod("coverageSuite")) {
return invokeMethod("coverageSuite");
}
return new TestSuite(clazz,
clazz.getName() + appendToName);
Is this approach ok with you?