|
1 package org.junit.runner.notification; |
|
2 |
|
3 import java.util.ArrayList; |
|
4 import java.util.Iterator; |
|
5 import java.util.List; |
|
6 |
|
7 import org.junit.runner.Description; |
|
8 import org.junit.runner.Result; |
|
9 |
|
10 /** |
|
11 * If you write custom runners, you may need to notify JUnit of your progress running tests. |
|
12 * Do this by invoking the <code>RunNotifier</code> passed to your implementation of |
|
13 * {@link org.junit.runner.Runner#run(RunNotifier)}. Future evolution of this class is likely to |
|
14 * move {@link #fireTestRunStarted(Description)} and {@link #fireTestRunFinished(Result)} |
|
15 * to a separate class since they should only be called once per run. |
|
16 */ |
|
17 public class RunNotifier { |
|
18 private List<RunListener> fListeners= new ArrayList<RunListener>(); |
|
19 private boolean fPleaseStop= false; |
|
20 |
|
21 /** Internal use only |
|
22 */ |
|
23 public void addListener(RunListener listener) { |
|
24 fListeners.add(listener); |
|
25 } |
|
26 |
|
27 /** Internal use only |
|
28 */ |
|
29 public void removeListener(RunListener listener) { |
|
30 fListeners.remove(listener); |
|
31 } |
|
32 |
|
33 private abstract class SafeNotifier { |
|
34 void run() { |
|
35 for (Iterator<RunListener> all= fListeners.iterator(); all.hasNext();) { |
|
36 try { |
|
37 notifyListener(all.next()); |
|
38 } catch (Exception e) { |
|
39 all.remove(); // Remove the offending listener first to avoid an infinite loop |
|
40 fireTestFailure(new Failure(Description.TEST_MECHANISM, e)); |
|
41 } |
|
42 } |
|
43 } |
|
44 |
|
45 abstract protected void notifyListener(RunListener each) throws Exception; |
|
46 } |
|
47 |
|
48 /** |
|
49 * Do not invoke. |
|
50 */ |
|
51 public void fireTestRunStarted(final Description description) { |
|
52 new SafeNotifier() { |
|
53 @Override |
|
54 protected void notifyListener(RunListener each) throws Exception { |
|
55 each.testRunStarted(description); |
|
56 }; |
|
57 }.run(); |
|
58 } |
|
59 |
|
60 /** |
|
61 * Do not invoke. |
|
62 */ |
|
63 public void fireTestRunFinished(final Result result) { |
|
64 new SafeNotifier() { |
|
65 @Override |
|
66 protected void notifyListener(RunListener each) throws Exception { |
|
67 each.testRunFinished(result); |
|
68 }; |
|
69 }.run(); |
|
70 } |
|
71 |
|
72 /** |
|
73 * Invoke to tell listeners that an atomic test is about to start. |
|
74 * @param description the description of the atomic test (generally a class and method name) |
|
75 * @throws StoppedByUserException thrown if a user has requested that the test run stop |
|
76 */ |
|
77 public void fireTestStarted(final Description description) throws StoppedByUserException { |
|
78 if (fPleaseStop) |
|
79 throw new StoppedByUserException(); |
|
80 new SafeNotifier() { |
|
81 @Override |
|
82 protected void notifyListener(RunListener each) throws Exception { |
|
83 each.testStarted(description); |
|
84 }; |
|
85 }.run(); |
|
86 } |
|
87 |
|
88 /** |
|
89 * Invoke to tell listeners that an atomic test failed. |
|
90 * @param failure the description of the test that failed and the exception thrown |
|
91 */ |
|
92 public void fireTestFailure(final Failure failure) { |
|
93 new SafeNotifier() { |
|
94 @Override |
|
95 protected void notifyListener(RunListener each) throws Exception { |
|
96 each.testFailure(failure); |
|
97 }; |
|
98 }.run(); |
|
99 } |
|
100 |
|
101 /** |
|
102 * Invoke to tell listeners that an atomic test was ignored. |
|
103 * @param description the description of the ignored test |
|
104 */ |
|
105 public void fireTestIgnored(final Description description) { |
|
106 new SafeNotifier() { |
|
107 @Override |
|
108 protected void notifyListener(RunListener each) throws Exception { |
|
109 each.testIgnored(description); |
|
110 }; |
|
111 }.run(); |
|
112 } |
|
113 |
|
114 /** |
|
115 * Invoke to tell listeners that an atomic test finished. Always invoke |
|
116 * {@link #fireTestFinished(Description)} if you invoke {@link #fireTestStarted(Description)} |
|
117 * as listeners are likely to expect them to come in pairs. |
|
118 * @param description the description of the test that finished |
|
119 */ |
|
120 public void fireTestFinished(final Description description) { |
|
121 new SafeNotifier() { |
|
122 @Override |
|
123 protected void notifyListener(RunListener each) throws Exception { |
|
124 each.testFinished(description); |
|
125 }; |
|
126 }.run(); |
|
127 } |
|
128 |
|
129 /** |
|
130 * Ask that the tests run stop before starting the next test. Phrased politely because |
|
131 * the test currently running will not be interrupted. It seems a little odd to put this |
|
132 * functionality here, but the <code>RunNotifier</code> is the only object guaranteed |
|
133 * to be shared amongst the many runners involved. |
|
134 */ |
|
135 public void pleaseStop() { |
|
136 fPleaseStop= true; |
|
137 } |
|
138 |
|
139 /** |
|
140 * Internal use only. The Result's listener must be first. |
|
141 */ |
|
142 public void addFirstListener(RunListener listener) { |
|
143 fListeners.add(0, listener); |
|
144 } |
|
145 |
|
146 public void testAborted(Description description, Throwable cause) { |
|
147 fireTestStarted(description); |
|
148 fireTestFailure(new Failure(description, cause)); |
|
149 fireTestFinished(description); |
|
150 } |
|
151 } |