Separate the different kinds of test suites

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

Problem

You have different kinds of tests—Programmer Tests, Customer Tests, End-to-End Tests—and you want to collect all the tests of a particular type to run them as a sin- gle suite.

Background

As your project increases in size and in scope, you will build many different kinds of tests. Most commonly, you will have Programmer Tests and Customer Tests.

You will want to be able to build a test suite from just the Programmer Tests because they generally execute more quickly and tend not to rely much on exter- nal resources (such as a database) that may not always be available. You will want to be able to build a test suite from just the Customer Tests when you want to ver- ify that your team is progressing in the direction that the customers or end users need. There are a number of ways to keep the two separate, and this recipe explores a few techniques that have worked well.

Recipe

You have several options are your disposal, which we highlight here and then dis- cuss in detail in the next section:

■ Maintain separate IDE projects for each kind of test. This is supported very well by most Java IDEs, but if you’re using CVS you have to work harder to coordinate changes across the CVS module boundary.

■ Maintain a separate test source tree for each kind of test, but in the same CVS module. While Ant supports this complex project structure, Eclipse (for one) does not.

■ Classify each individual test case class and then use RecursiveTestSuite and TestFilter (see recipe 4.5, “Scan the file system for tests”) to collect the test case classes that fit each classification. An easy way to differentiate Customer Tests from the rest is have them implement a tag interface called CustomerTest.14

14A tag interface is a Java interface with no methods. You can use these tag interfaces and simple instanceof checks to classify your classes. The most commonly used tag interface is java.io.Serializable.

TE AM FL Y

Team-Fly®

121 Separate the different kinds of test suites

There are likely others, but one of these three will satisfy your needs.

Discussion

Your first option is to maintain separate test source trees, just as we recommend in chapter 3. It is easy to use RecursiveTestSuite to collect all the tests in the Pro- grammer Tests source tree without worrying about the tests in the Customer Tests source tree. If you are using a project-based IDE such as Eclipse, then keep the dif- ferent kinds of tests in different projects. In such an environment, this is the source code layout that we recommend. This option’s one downfall is that you may need to coordinate changes to multiple projects in your source control repos- itory, particularly if you use CVS. Each project is stored in its own CVS module, and CVS does not directly support versioning multiple modules together. To simulate this, you need to tag the modules with the same tag name to signify that those ver- sions of the various projects go together. If you are using Subversion, which sup- ports global versioning, this is not an issue; but until Subversion releases version 1.0, CVS will likely continue its dominance in the source control arena.15 What should you do, then, if you need to coordinate changes across all the different kinds of tests you write and you are using a system such as CVS?

You can have multiple source trees within the same CVS module: there is cer- tainly nothing to stop you; however, some IDEs do not support building from mul- tiple, different source trees into different destination directories. (Fortunately, Eclipse does support this feature, although you have to enable it on a project-by- project basis.) You could move to Subversion, which supports global versioning, but there is another, less drastic solution that may be right for your project.16

The last solution we recommend is one we have used with success: identify each test case class as a Programmer Test or a Customer Test or an Integration Test (or whatever kind of test) by implementing a tag interface. Specifically, we recom- mend that your Customer Test case class implement the interface CustomerTest, and the other test case classes follow suit. You can then build your test suite using GSBase’s RecursiveTestSuite utility and its accompanying TestFilter. (See rec- ipe 4.5, “Scan the file system for tests,” for details on using RecursiveTestSuite.) In this case, the test filter you build accepts test classes that implement the desired tag interface. Listing 4.4 shows an example of collecting all the Customer Tests, assuming that you identify them with a tag interface called CustomerTest.

15Subversion was nearing version 1.0 as we wrote this and more than likely has been released by the time you read this.

16Nothing against Subversion, but old habits die hard.

122 CHAPTER 4 Managing test suites

import junit.framework.Test;

import com.gargoylesoftware.base.testing.RecursiveTestSuite;

import com.gargoylesoftware.base.testing.TestFilter;

public class AllCustomerTests {

public static Test suite() throws Exception {

return new RecursiveTestSuite("classes", new TestFilter() { public boolean accept(Class eachTestClass) {

return (

CustomerTest.class.isAssignableFrom(

eachTestClass));

} });

} }

The standard Java class Class provides the method isAssignableFrom() to answer the question, “Can I refer to an instance of that class through a reference to this class?”17 For example, List is assignable from ArrayList, because we can assign an ArrayList to a List reference.18 The choice of method names is a little clunky, in our opinion. If we had an instance of the test case class, we could have asked the simpler question, “Is testObject instanceof CustomerTest?” Still, you cannot fault GSBase for wanting to filter out unwanted test case classes before any instances of them are created, so we’re stuck with a slightly more unwieldy way of filtering out the test case classes that are not Customer Tests. If it annoys you more than it annoys us, then simply change RecursiveTestSuite. That’s what open source is all about.19

Related

■ 4.5—Scan the file system for tests

Listing 4.4 Collecting tests that implement the CustomerTest interface

17It’s worth noting that MyClass.class.isAssignableFrom(object.getClass()) is the same as objectinstanceofMyClass.

18In object-oriented shorthand, an ArrayList is-a List.

19That is, the freedom to change software that doesn’t work as you need it to, not randomly throwing away other people’s hard work.

Does eachTestClass implement CustomerTest?

123 Control the order of some of your tests

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

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

(753 trang)