Good Base Test Case
From Software By Jeff
Here's a fine test to start with for making sure all of your JUnit tests are exceuted. It comes with a test to ensure that all of your tests are included. Simply extend AllLocalTests with your tests in the same package, and you're good to go. If you forget to add your new test to AllLocalTests.suite(), the testEnsureAllLocalTestsAreIncluded() will notify you of your oversight. Then simply execute the one test, AllLocalTests, and all of the tests in your project would be excuted.
Additionally, as this test class is expected to be extended by all of your tests, it is an excellent place to set up your pre-test environment (attach to a database, for example) add additional methods that might be helpful throughout your tests (notice there's an AssertEquals(Object, Object), but not AssertNotEquals(Object, Object) in JUnit's TestCase?
The recommended use is to put this class in the root of your test's package tree. If you have separate groups of tests, put multiple copies of this base class in separate "root" points in your test packages, and include the tests in those trees in the appropriate instance of this test.
For example, if our packages included com.softwarebyjeff.packageA and com.softwarebyjeff.packageB, we could put this in com.softwarebyjeff to cover both packageA and packageB. Alternatively, if we had cause for making separate test cores (perhaps one is purely local while the other requires an application server to be running), we'd put two copies of this class, one in packageA containing only tests there and deeper, and one in packageB.
import java.util.Arrays;
import java.util.Collection;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.Vector;
import junit.framework.Test;
import junit.framework.TestCase;
import junit.framework.TestSuite;
import junit.runner.LoadingTestCollector;
import junit.textui.TestRunner;
/**
* Use this as a base class for local tests to ensure complete coverage
*/
public class AllLocalTests extends TestCase
{
/**
* Start and run the JUnit tests as an application
*
* @param args
*/
public static void main(String args[])
{
TestRunner.run(suite());
}
/**
* Add all of the tests here
*
* @return suite of all tests to run
*/
public final static Test suite()
{
TestSuite suite = new TestSuite();
// Recommend leaving this last for console output
suite.addTestSuite(AllLocalTests.class);
return suite;
}
/**
* Test to Ensure All Local Tests Are Included
*
* @throws Exception
*/
public void testEnsureAllLocalTestsAreIncluded() throws Exception
{
System.out.println("Verifying all test classes extend AllLocalTests and are in AllLocalTests.suite()");
// Only put tests here that might extend AllLocalTests although they don't have executable tests
Collection excludedClassNames = Arrays.asList(new Object[] { "AllLocalTests" });
// Should just reflect and steal the list, but we'll be nice...
Collection currentTests = new Vector();
TestSuite testSuite = (TestSuite) (AllLocalTests.suite());
for (int i = 0; i < testSuite.testCount(); i++)
{
TestSuite testSuiteAt = (TestSuite) (testSuite.testAt(i));
String className = testSuiteAt.getName();
currentTests.add(className);
}
// Iterate through each class in classpath and ensure they're correctly implemented
Collection missingTests = new Vector();
Collection incorrectlyImplemented = new Vector();
String packageName = this.getClass().getPackage().getName();
Enumeration enumeration = new LoadingTestCollector().collectTests();
while (enumeration.hasMoreElements())
{
String object = enumeration.nextElement().toString();
if ((object != null)
&& (object.indexOf(packageName) == 0)
&& (!excludedClassNames.contains(object.substring(object.lastIndexOf(".") + 1))))
{
if (AllLocalTests.class.isAssignableFrom(Class.forName(object)))
{
if (!currentTests.contains(object))
missingTests.add(object);
}
else if (Test.class.isAssignableFrom(Class.forName(object)))
{
incorrectlyImplemented.add(object);
}
}
}
// Loop through failure collections to list failures
if (!missingTests.isEmpty())
{
System.err.println("Not all classes that extend AllLocalTests are in AllLocalTests.suite():");
Iterator missingTestsIterator = missingTests.iterator();
while (missingTestsIterator.hasNext())
{
String className = missingTestsIterator.next().toString();
System.err.println("Missing test: " + className);
}
}
if (!incorrectlyImplemented.isEmpty())
{
System.err.println("Not all test classes extend AllLocalTests:");
Iterator incorrectlyImplementedIterator = incorrectlyImplemented.iterator();
while (incorrectlyImplementedIterator.hasNext())
{
String className = incorrectlyImplementedIterator.next().toString();
System.err.println("Incorrectly implemented test: " + className);
}
}
// Redbar if failures
assertTrue(
"Check the console output for a complete list of errors",
missingTests.isEmpty() && incorrectlyImplemented.isEmpty());
// Log compliance if success
System.out.println("All classes extend AllLocalTests and are in AllLocalTests.suite()");
}
}