Connecting a hierarchy of tests and test suites for an entire application, in JUnit
Testing software became a whole lot easier for me once I absorbed the Zen of Test Driven Development; instead of writing a huge application and wondering afterward how to test all the cases, missing some, being bored and generally hating life I now run a suite of automated tests that were created as the code was developped, that cover all the possibilities.
I use the JUnit testing framework (one of the XUnit testing frameworks, written to test Java code).
Using JUnit, several simple tests are collected into a test case - I create one test case for each Java class that I am developing. For example,
public class Test_RSSParserFactory extends TestCase
{
public Test_RSSParserFactory( String s )
{
super( s );
}
public void testFactoryRetursCorrectClassFor091() throws Exception
{
…
}
public void testParserInterface_v091() throws Exception
{
…
}
public void testParserInterface_v092() throws Exception
{
…
}
}
Every java package that contains classes has a sub package containing the tests. JUnit allows tests to be grouped into test suites, allowing a number of TestCase classes to be run automatically. FOr example, all the SAX parsing tests were collected together to form the SAX Parsing Test Suite
public class SAXParsingTestSuite
{
public static Test suite() throws Exception
{
TestSuite suite = new TestSuite( “SAX Parsing Test Suite” );
// XML Parsing
suite.addTestSuite( Test_RSSSAXParser_v091.class );
suite.addTestSuite( Test_RSSSAXParser_v092.class );
return suite;
}
}
Or, the general tests for the RSS generation
public class GeneralTestSuite
{
public static Test suite() throws Exception
{
TestSuite suite = new TestSuite( “General Test Suite” );
// Data storage
suite.addTestSuite( Test_RSSChannel_v091.class );
suite.addTestSuite( Test_RSSChannel_v092.class );
// XML Generation
suite.addTestSuite( Test_RSSChannelRenderer_v091.class );
suite.addTestSuite( Test_RSSChannelRenderer_v092.class );
// XML Parsing
suite.addTestSuite( Test_RSSParserFactory.class );
return suite;
}
}
The missing piece of my puzzle was how to collect these test suites together as I didnt want to maintain another long list of test cases forming the overall complete test suite for the application.
I found that it was impossible to add a test suite (that is, a class containing the single static suite() method) to an overall test suite - JUnit complained that the class contained no tests. Quite true: the class itself didnt contain tests, but it did point the way to where tests could be found. Thankfully JUnit itself comes with an extensive test suite, and the answer was found therein.
To add a test suite to another suite, and thereby gain a hierarchy of tests for an entire class library or Java application, I needed to call the static suite() method and add the returned test to my suite:
public class CompleteTestSuite
{
public static Test suite() throws Exception
{
TestSuite suite = new TestSuite( “Complete test suite” );
// General test suite
suite.addTest( com.caffeinatedbliss.rss.test.GeneralTestSuite.suite() );
// XML parsing test suite
suite.addTest( com.caffeinatedbliss.rss.sax.test.SAXParsingTestSuite.suite() );
return suite;
}
}
The end result was exactly what I was looking for: a hierarchy of tests and test suites for an entire application, neatly packaged as close as possible to the code they are trying to test, without the overhead of maintining multiple lists of test cases.