1 package org.junit.runner.manipulation;
2
3 import org.junit.runner.Description;
4 import org.junit.runner.Request;
5
6 /**
7 * The canonical case of filtering is when you want to run a single test method in a class. Rather
8 * than introduce runner API just for that one case, JUnit provides a general filtering mechanism.
9 * If you want to filter the tests to be run, extend <code>Filter</code> and apply an instance of
10 * your filter to the {@link org.junit.runner.Request} before running it (see
11 * {@link org.junit.runner.JUnitCore#run(Request)}. Alternatively, apply a <code>Filter</code> to
12 * a {@link org.junit.runner.Runner} before running tests (for example, in conjunction with
13 * {@link org.junit.runner.RunWith}.
14 *
15 * @since 4.0
16 */
17 public abstract class Filter {
18 /**
19 * A null <code>Filter</code> that passes all tests through.
20 */
21 public static final Filter ALL = new Filter() {
22 @Override
23 public boolean shouldRun(Description description) {
24 return true;
25 }
26
27 @Override
28 public String describe() {
29 return "all tests";
30 }
31
32 @Override
33 public void apply(Object child) throws NoTestsRemainException {
34 // do nothing
35 }
36
37 @Override
38 public Filter intersect(Filter second) {
39 return second;
40 }
41 };
42
43 /**
44 * Returns a {@code Filter} that only runs the single method described by
45 * {@code desiredDescription}
46 */
47 public static Filter matchMethodDescription(final Description desiredDescription) {
48 return new Filter() {
49 @Override
50 public boolean shouldRun(Description description) {
51 if (description.isTest()) {
52 return desiredDescription.equals(description);
53 }
54
55 // explicitly check if any children want to run
56 for (Description each : description.getChildren()) {
57 if (shouldRun(each)) {
58 return true;
59 }
60 }
61 return false;
62 }
63
64 @Override
65 public String describe() {
66 return String.format("Method %s", desiredDescription.getDisplayName());
67 }
68 };
69 }
70
71
72 /**
73 * @param description the description of the test to be run
74 * @return <code>true</code> if the test should be run
75 */
76 public abstract boolean shouldRun(Description description);
77
78 /**
79 * Returns a textual description of this Filter
80 *
81 * @return a textual description of this Filter
82 */
83 public abstract String describe();
84
85 /**
86 * Invoke with a {@link org.junit.runner.Runner} to cause all tests it intends to run
87 * to first be checked with the filter. Only those that pass the filter will be run.
88 *
89 * @param child the runner to be filtered by the receiver
90 * @throws NoTestsRemainException if the receiver removes all tests
91 */
92 public void apply(Object child) throws NoTestsRemainException {
93 if (!(child instanceof Filterable)) {
94 return;
95 }
96 Filterable filterable = (Filterable) child;
97 filterable.filter(this);
98 }
99
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 }