Collect all the tests in a package

Một phần của tài liệu Manning JUnit recipes practical methods for program (Trang 142 - 145)

4.3 Collect all the tests in a package

Problem

You have a number of test case classes in a package and would like to run them all at the same time, but the test runners ask you to specify a single test case class name. You need a way to collect all the tests in a package into a single test suite.

Background

JUnit makes it easy to run the tests in a single test case class: simply pass the name of a test case class as a command-line parameter to the test runner. Because JUnit automatically builds a test suite from your test case class, it is not obvious how to collect the tests from multiple test case classes together into a single suite. Because you didn’t have to do anything special to run all the tests in a single test case, how could you possibly know how to collect multiple test case classes together into one big test suite?

You may be tempted to move all those test methods into a single test case class.

Don’t. It makes navigating your test source code much more difficult. Different

112 CHAPTER 4 Managing test suites

tests operate on different fixtures and so should be separated into different test case classes (see recipe 3.7, “Move special case tests to a separate test fixture”).

Some day you will want to run one test case class’s tests on their own. When that happens, don’t copy the test methods back into a separate test case class! Follow this recipe instead.

Recipe

To collect all the tests in a package, you build a custom test suite just as we describe in recipe 4.2, “Collect a specific set of tests,” but rather than adding indi- vidual tests to the suite, add the suites from each test case class in your package.

There are essentially two different ways to add a test suite to a larger test suite.

The following example, taken from the class junit.tests.AllTests, shows both:

public static Test suite() {

TestSuite suite= new TestSuite("Framework Tests");

suite.addTestSuite(TestCaseTest.class);

suite.addTest(SuiteTest.suite());

suite.addTestSuite(TestListenerTest.class);

suite.addTestSuite(AssertTest.class);

suite.addTestSuite(TestImplementorTest.class);

suite.addTestSuite(NoArgTestCaseTest.class);

suite.addTestSuite(ComparisonFailureTest.class);

suite.addTestSuite(DoublePrecisionAssertTest.class);

return suite;

}

We call this the AllTests pattern. The two methods you can use to add one test suite to another are addTestSuite() and the familiar addTest(). The first auto- matically extracts a test suite from the test case class you specify. The second uses the test case class’s custom test suite method. In what must be called an unfortu- nate flaw in JUnit’s design, you need to know when you build a suite of suites whether to use a test case’s custom suite method or JUnit’s automatic test suite extraction feature.10 The only way to know this is to know the source code of the other test case classes in your package. Fortunately, the odds are high that you already do.

There are a few common conventions related to this technique:

■ Name the package-level test suite class AllTests.

■ Create one AllTests class per package.

10The method TestSuite.addTestSuite(Class testClass), for example, does not bother to look for a custom suite() method at all, even though the test runners do.

Add the default TestSuite Add a custom TestSuite

113 Collect all the tests in a package

■ Collect the test suite from each package’s AllTests into a larger AllTests class one level up in the package hierarchy. This is the way to build a suite for the entire system. See recipe 4.4, “Collect all the tests for your entire sys- tem” for details.

Discussion

The method TestSuite.addTestSuite() is simply shorthand for writing suite.addTest(new TestSuite(MyTestCase.class)), as you can see by its imple- mentation. (Look at the source!) JUnit practitioners had been writing this code so often in their AllTests classes that it became apparent a refactoring was in order to remove this duplication. You can now simply call addTestSuite() to extract a test suite from a test case class automatically and then add that suite into a larger one.

We mentioned in recipe 4.2, “Collect a specific set of tests,” that you can invoke addTest() to add any Test object to a test suite, whether a single test or another test suite. In this case, AllTests includes SuiteTest’s custom test suite: first it invokes SuiteTest.suite(), returning a TestSuite object; then it adds that TestSuite object to its own, larger test suite. Use this technique to build up suites of custom test suites. If you know that MyTestCase collects its tests using the suite() method, then you should collect its tests by invoking addTest(MyTest- Case.suite()).

Finally, note that the class that declares a suite() method does not have to be a subclass of TestCase. Such a class is typically just a collector for other test suites and does not define any tests of its own. In particular, one look at the source of junit.framework.AllTests reveals that it is just a regular Java class—not a descen- dant of junit.framework.TestCase. Although it is common for a test case class to provide its own custom suite() method, any class can collect tests into a suite() method.11 This is another of those subtle parts of JUnit that even many experi- enced practitioners do not realize. In JUnit, an amazingly small amount of code can have its own nuances.

Related

■ 4.1—Let JUnit build your test suite

■ 4.2—Collect a specific set of tests

■ 4.4—Collect all the tests for your entire system

11Refer back to the discussion of arbitrary suites of tests in recipe 4.2.

114 CHAPTER 4 Managing test suites

Một phần của tài liệu Manning JUnit recipes practical methods for program (Trang 142 - 145)

Tải bản đầy đủ (PDF)

(753 trang)