/** * Copyright 2006 Jukka Zitting * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.HashSet; import java.util.Iterator; import java.util.regex.Pattern; import junit.framework.TestCase; /** * Test case that can be exluded from a test run using system properties. * This is especially useful for known issues or similar test cases that * are expected to fail, but should not flag the entire test run as a * failure. *
* This class overrides the {@link #runBare()} method to check whether
* the test should or should not be run. This decision is based on the
* junit.excludes and junit.includes system
* properties. If defined, these properties are interpreted as
* whitespace-separated sets of test identifiers to exclude
* or include. Normally each test is included in the test run, but identifying
* a test in junit.excludes will exclude that test. The exclusion
* can be overridden by identifying the test in junit.includes
* which again overrides the exclusion.
*
* Each test is identified by a set of test identifiers. The default * identifiers of a test are: *
org.example.test.ExampleTestCase)
* ExampleTestCase)org.example.test)org.example.test.ExampleTestCase#testSomething)
* ExampleTestCase#testSomething)
* testSomething)
* The set of identifiers of a test can be extended using the
* {@link #addIdentifier(String)} method. A common use case for this
* would be for example to include the issue tracker identifier for the
* known issue for which the test case was written.
*/
public abstract class ExcludableTestCase extends TestCase {
/**
* Whitespace pattern for splitting the system property strings
* to sets of test identifiers.
*/
private static final Pattern WHITESPACE = Pattern.compile("\\s+");
/**
* The set of test identifiers to be excluded from the test run.
*/
private static final Collection EXCLUDES = new HashSet(Arrays.asList(
WHITESPACE.split(System.getProperty("junit.excludes", ""))));
/**
* The set of test identifiers to be included in the test run even if
* the test would otherwise be excluded.
*/
private static final Collection INCLUDES = new HashSet(Arrays.asList(
WHITESPACE.split(System.getProperty("junit.includes", ""))));
/**
* Identifiers of this test.
*/
private final Collection identifiers = new ArrayList();
/**
* Creates an excludable test case without a name.
*/
public ExcludableTestCase() {
super();
}
/**
* Creates an excludable test case with the given name.
*
* @param name test name
*/
public ExcludableTestCase(final String name) {
super(name);
}
/**
* Adds an identifier to this test.
*
* @param identifier test identifier
*/
public final void addIdentifier(final String identifier) {
identifiers.add(identifier);
}
//------------------------------------------------------------< TestCase >
/**
* Runs the bare test sequence unless the test has been excluded.
* Determines the exclusion by comparing the set of test identifiers
* to the contents of the junit.excludes and
* junit.includes system properties. If the test is not
* excluded, then the standard {@link TestCase#runBare()} method is
* invoked.
*
* @throws Throwable if any exception is thrown by the test
*/
public final void runBare() throws Throwable {
// Add default test identifiers
String className = getClass().getName();
addIdentifier(className);
String testName = getName();
if (testName != null) {
addIdentifier(className + "#" + testName);
addIdentifier(testName);
}
int dot = className.lastIndexOf('.');
if (dot >= 0) {
String localName = className.substring(dot + 1);
addIdentifier(localName);
if (testName != null) {
addIdentifier(localName + "#" + testName);
}
if (dot > 0) {
addIdentifier(className.substring(0, dot));
}
}
// Check for inclusion
boolean include = true;
for (Iterator i = identifiers.iterator(); include && i.hasNext();) {
include = !EXCLUDES.contains(i.next());
}
for (Iterator i = identifiers.iterator(); !include && i.hasNext();) {
include = INCLUDES.contains(i.next());
}
if (include) {
super.runBare();
}
}
}