Class Modifiers


The problem is that SessionTest, an abstract class, contains a number of definitions for test methods. The methods are intended to be executed as part of SessionTest subclasses; thus, you did not previously add SessionTest to a suite. You need to modify SuiteBuilder to ignore abstract classes.

Create a test class that is abstract and extends from TestCase.

 package sis.testing.testclasses; abstract public class AbstractTestClass       extends junit.framework.TestCase {    public void testMethod() {} } 

Then modify the test to ensure that it isn't collected.

 public void testGatherTestClassNames() {    SuiteBuilder builder = new SuiteBuilder();    List<String> classes = builder.gatherTestClassNames();    assertTrue(classes.contains("testing.SuiteBuilderTest"));    assertFalse(classes.contains("testing.testclasses.NotATestClass"));    assertFalse( classes.contains("testing.testclasses.AbstractTestClass")); } 

Run the test and ensure that it fails. Only then should you go on to correct the code in SuiteBuilder. You are following a testing pattern: If you release code that fails either in production or in an acceptance test (a customer-defined test that exercises code from an end user's standpoint), it means that it was inadequately unit-tested. Your job is to add the missing test code and ensure that it fails for the same reason that the acceptance test failed[8].

[8] [Jeffries2001], p. 163.

Never depend solely on one level of testing. Ensure you have a layer above unit testing to ferret out "holes" in your unit tests.


Now that you've seen the test fail, you can add code to SuiteBuilder that corrects the defect:

 public List<String> gatherTestClassNames() {    TestCollector collector = new ClassPathTestCollector() {       public boolean isTestClass(String classFileName) {          if (!super.isTestClass(classFileName))             return false;          String className = classNameFromFile(classFileName);          Class klass = createClass(className);          return             TestCase.class.isAssignableFrom(klass) &&             isConcrete(klass);       }    };    return Collections.list(collector.collectTests()); } private boolean isConcrete(Class klass) {    if (klass.isInterface())       return false;    int modifiers = klass.getModifiers();    return !Modifier.isAbstract(modifiers); } 

If a type (Class represents both interface and class types) is an interface, it is not concrete. You can determine that using the Class method isInterface.

The isConcrete method also uses the Class method getModifiers. The method getModifiers returns an int that embeds a list of flags, each corresponding to a possible class modifier.[9] Some of the modifiers you have seen include abstract, static, private, protected, and public. A utility class java.lang.reflect.Modifier (you'll need to add an appropriate import statement to SuiteBuilder) contains a number of static query methods to help you determine the modifiers that are set within the modifiers int.

[9] Methods and fields also have modifiers and use the same int-flag construct.

You can now delete all of your AllTests classes!



Agile Java. Crafting Code with Test-Driven Development
Agile Javaв„ў: Crafting Code with Test-Driven Development
ISBN: 0131482394
EAN: 2147483647
Year: 2003
Pages: 391
Authors: Jeff Langr

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net