001 package org.junit.runner.manipulation;
002
003 import org.junit.runner.Description;
004 import org.junit.runner.Request;
005
006 /**
007 * The canonical case of filtering is when you want to run a single test method in a class. Rather
008 * than introduce runner API just for that one case, JUnit provides a general filtering mechanism.
009 * If you want to filter the tests to be run, extend <code>Filter</code> and apply an instance of
010 * your filter to the {@link org.junit.runner.Request} before running it (see
011 * {@link org.junit.runner.JUnitCore#run(Request)}. Alternatively, apply a <code>Filter</code> to
012 * a {@link org.junit.runner.Runner} before running tests (for example, in conjunction with
013 * {@link org.junit.runner.RunWith}.
014 *
015 * @since 4.0
016 */
017 public abstract class Filter {
018 /**
019 * A null <code>Filter</code> that passes all tests through.
020 */
021 public static final Filter ALL = new Filter() {
022 @Override
023 public boolean shouldRun(Description description) {
024 return true;
025 }
026
027 @Override
028 public String describe() {
029 return "all tests";
030 }
031
032 @Override
033 public void apply(Object child) throws NoTestsRemainException {
034 // do nothing
035 }
036
037 @Override
038 public Filter intersect(Filter second) {
039 return second;
040 }
041 };
042
043 /**
044 * Returns a {@code Filter} that only runs the single method described by
045 * {@code desiredDescription}
046 */
047 public static Filter matchMethodDescription(final Description desiredDescription) {
048 return new Filter() {
049 @Override
050 public boolean shouldRun(Description description) {
051 if (description.isTest()) {
052 return desiredDescription.equals(description);
053 }
054
055 // explicitly check if any children want to run
056 for (Description each : description.getChildren()) {
057 if (shouldRun(each)) {
058 return true;
059 }
060 }
061 return false;
062 }
063
064 @Override
065 public String describe() {
066 return String.format("Method %s", desiredDescription.getDisplayName());
067 }
068 };
069 }
070
071
072 /**
073 * @param description the description of the test to be run
074 * @return <code>true</code> if the test should be run
075 */
076 public abstract boolean shouldRun(Description description);
077
078 /**
079 * Returns a textual description of this Filter
080 *
081 * @return a textual description of this Filter
082 */
083 public abstract String describe();
084
085 /**
086 * Invoke with a {@link org.junit.runner.Runner} to cause all tests it intends to run
087 * to first be checked with the filter. Only those that pass the filter will be run.
088 *
089 * @param child the runner to be filtered by the receiver
090 * @throws NoTestsRemainException if the receiver removes all tests
091 */
092 public void apply(Object child) throws NoTestsRemainException {
093 if (!(child instanceof Filterable)) {
094 return;
095 }
096 Filterable filterable = (Filterable) child;
097 filterable.filter(this);
098 }
099
100 /**
101 * Returns a new Filter that accepts the intersection of the tests accepted
102 * by this Filter and {@code second}
103 */
104 public Filter intersect(final Filter second) {
105 if (second == this || second == ALL) {
106 return this;
107 }
108 final Filter first = this;
109 return new Filter() {
110 @Override
111 public boolean shouldRun(Description description) {
112 return first.shouldRun(description)
113 && second.shouldRun(description);
114 }
115
116 @Override
117 public String describe() {
118 return first.describe() + " and " + second.describe();
119 }
120 };
121 }
122 }