blob: 0287351f47df782b08e83786c56259c4c166de6b [file] [log] [blame]
package org.junit.runner.manipulation;
import org.junit.runner.Description;
import org.junit.runner.Request;
/**
* The canonical case of filtering is when you want to run a single test method in a class. Rather
* than introduce runner API just for that one case, JUnit provides a general filtering mechanism.
* If you want to filter the tests to be run, extend <code>Filter</code> and apply an instance of
* your filter to the {@link org.junit.runner.Request} before running it (see
* {@link org.junit.runner.JUnitCore#run(Request)}. Alternatively, apply a <code>Filter</code> to
* a {@link org.junit.runner.Runner} before running tests (for example, in conjunction with
* {@link org.junit.runner.RunWith}.
*
* @since 4.0
*/
public abstract class Filter {
/**
* A null <code>Filter</code> that passes all tests through.
*/
public static final Filter ALL = new Filter() {
@Override
public boolean shouldRun(Description description) {
return true;
}
@Override
public String describe() {
return "all tests";
}
@Override
public void apply(Object child) throws NoTestsRemainException {
// do nothing
}
@Override
public Filter intersect(Filter second) {
return second;
}
};
/**
* Returns a {@code Filter} that only runs the single method described by
* {@code desiredDescription}
*/
public static Filter matchMethodDescription(final Description desiredDescription) {
return new Filter() {
@Override
public boolean shouldRun(Description description) {
if (description.isTest()) {
return desiredDescription.equals(description);
}
// explicitly check if any children want to run
for (Description each : description.getChildren()) {
if (shouldRun(each)) {
return true;
}
}
return false;
}
@Override
public String describe() {
return String.format("Method %s", desiredDescription.getDisplayName());
}
};
}
/**
* @param description the description of the test to be run
* @return <code>true</code> if the test should be run
*/
public abstract boolean shouldRun(Description description);
/**
* Returns a textual description of this Filter
*
* @return a textual description of this Filter
*/
public abstract String describe();
/**
* Invoke with a {@link org.junit.runner.Runner} to cause all tests it intends to run
* to first be checked with the filter. Only those that pass the filter will be run.
*
* @param child the runner to be filtered by the receiver
* @throws NoTestsRemainException if the receiver removes all tests
*/
public void apply(Object child) throws NoTestsRemainException {
if (!(child instanceof Filterable)) {
return;
}
Filterable filterable = (Filterable) child;
filterable.filter(this);
}
/**
* Returns a new Filter that accepts the intersection of the tests accepted
* by this Filter and {@code second}
*/
public Filter intersect(final Filter second) {
if (second == this || second == ALL) {
return this;
}
final Filter first = this;
return new Filter() {
@Override
public boolean shouldRun(Description description) {
return first.shouldRun(description)
&& second.shouldRun(description);
}
@Override
public String describe() {
return first.describe() + " and " + second.describe();
}
};
}
}