Adding a Test Suite
Consider a similar TestCase that we wrote to test the functionality of the Product class:
package junittest; //import the //junit.framework package import junit.framework.*; // extend the // TestCase class public class ProductTest extends TestCase { private Product aProduct; /** * Constructs a ProductTest with the specified name. * @param name Test case name. */ public ProductTest (String name) { super(name); } /** * Sets up the test fixture. * Called before every test case method. */ protected void setUp() { aProduct = new Product("Product 1", 4, 20.05); } /** * Tears down the test fixture. * Called after every test case method. */ protected void tearDown() { aProduct = null; } /** * Tests creating a product */ public void testProductCreate() { Product newProduct = new Product("Product 2", 2, 10.56); assertNotNull(newProduct); } /** * Tests equality of products */ public void testProductEquals() { Product newProduct = new Product("Product 1", 4, 20.05); assertEquals(newProduct, aProduct); } /** * Tests the total value of all units of the product */ public void testProductTotalValue() { Product newProduct = new Product("Product 1", 4, 25.00); assertEquals(newProduct.getTotalPrice(), 100.00, 0 ); } /** * Tests adding units of the product */ public void testProductAddQuantity() { int prevCount = aProduct.getQuantity(); aProduct.addQuantity(10); assertEquals(aProduct.getQuantity(), prevCount+10 ); } /** * Tests deleting units of the product */ public void testProductDeleteQuantity() { int prevCount = aProduct.getQuantity(); aProduct.deleteQuantity(10); assertEquals(aProduct.getQuantity(), prevCount-10 ); } /** * Hook to define test cases to junit * * @param args Optional list of tests to execute. * @return List of tests to execute. */ public static Test suite(String[] args) { if (args.length == 0){ // run all tests defined in class. return new TestSuite(ProductTest.class); } else{ TestSuite testsToRun = new TestSuite(); for (int i = 0; i < args.length; i++){ testsToRun.addTest(new ProductTest(args[i])); } return testsToRun; } } /** * Main program for external invocation in command line mode * @param List of tests to execute via suite() */ public static void main(String args[]) throws ClassNotFoundException{ junit.textui.TestRunner.run(suite(args)); return; } }
The ProductTest defines all the test methods for the Product class. Notice that the testProductDeleteQuantity() method is not logically complete because the quantity should never be less than zero (we will ignore this for the sake of this exercise). Suffice it to say, once you get into the habit of writing these test cases, you are bound to catch logical errors such as the above in the cycle of testing and development.
Now that we have defined two separate TestCase classes, how do we ensure that going forward we can easily assemble these into comprehensive test suites? This is where we shall create a composite test suite by combining individual TestCase classes.
package junittest; import junit.framework.Test; import junit.framework.TestSuite; public class CatalogAppTestSuite { /** * Assembles a test suite containing all known tests. * As new TestCases are defined they can be easily added * to this class * @return A non-null test suite. */ public static Test suite(String[] args) { TestSuite suite = new TestSuite(); // CatalogTest suite.addTest(CatalogTest.suite(args)); // ProductTest suite.addTest(ProductTest.suite(args)); // Add new TestCases here return suite; } /** * Runs the test suite. */ public static void main(String args[]) { junit.textui.TestRunner.run(suite(args)); } }
Figure 6 shows how the CatalogAppTestSuite runs the tests included in both the CatalogTest and the ProductTest classes.
Figure 6 Console output for CatalogAppTestSuite.