aboutsummaryrefslogtreecommitdiff
path: root/src/main/java/org/junit/runner/manipulation/Filter.java
blob: c0f31b0b40c42caf629b63dcb04d3ca81f362cf1 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
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}.
 */
public abstract class Filter {
	/**
	 * A null <code>Filter</code> that passes all tests through.
	 */
	public static 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();
			}
		};
	}
}