001 package org.junit.rules;
002
003 import java.util.ArrayList;
004 import java.util.List;
005
006 import org.junit.AssumptionViolatedException;
007 import org.junit.Rule;
008 import org.junit.runner.Description;
009 import org.junit.runners.model.MultipleFailureException;
010 import org.junit.runners.model.Statement;
011
012 /**
013 * TestWatcher is a base class for Rules that take note of the testing
014 * action, without modifying it. For example, this class will keep a log of each
015 * passing and failing test:
016 *
017 * <pre>
018 * public static class WatchmanTest {
019 * private static String watchedLog;
020 *
021 * @Rule(order = Integer.MIN_VALUE)
022 * public TestWatcher watchman= new TestWatcher() {
023 * @Override
024 * protected void failed(Throwable e, Description description) {
025 * watchedLog+= description + "\n";
026 * }
027 *
028 * @Override
029 * protected void succeeded(Description description) {
030 * watchedLog+= description + " " + "success!\n";
031 * }
032 * };
033 *
034 * @Test
035 * public void fails() {
036 * fail();
037 * }
038 *
039 * @Test
040 * public void succeeds() {
041 * }
042 * }
043 * </pre>
044 * <p>It is recommended to always set the {@link Rule#order() order} of the
045 * {@code TestWatcher} to {@code Integer.MIN_VALUE} so that it encloses all
046 * other rules. Otherwise it may see failed tests as successful and vice versa
047 * if some rule changes the result of a test (e.g. {@link ErrorCollector} or
048 * {@link ExpectedException}).
049 *
050 * @since 4.9
051 */
052 public abstract class TestWatcher implements TestRule {
053 public Statement apply(final Statement base, final Description description) {
054 return new Statement() {
055 @Override
056 public void evaluate() throws Throwable {
057 List<Throwable> errors = new ArrayList<Throwable>();
058
059 startingQuietly(description, errors);
060 try {
061 base.evaluate();
062 succeededQuietly(description, errors);
063 } catch (org.junit.internal.AssumptionViolatedException e) {
064 errors.add(e);
065 skippedQuietly(e, description, errors);
066 } catch (Throwable e) {
067 errors.add(e);
068 failedQuietly(e, description, errors);
069 } finally {
070 finishedQuietly(description, errors);
071 }
072
073 MultipleFailureException.assertEmpty(errors);
074 }
075 };
076 }
077
078 private void succeededQuietly(Description description,
079 List<Throwable> errors) {
080 try {
081 succeeded(description);
082 } catch (Throwable e) {
083 errors.add(e);
084 }
085 }
086
087 private void failedQuietly(Throwable e, Description description,
088 List<Throwable> errors) {
089 try {
090 failed(e, description);
091 } catch (Throwable e1) {
092 errors.add(e1);
093 }
094 }
095
096 private void skippedQuietly(
097 org.junit.internal.AssumptionViolatedException e, Description description,
098 List<Throwable> errors) {
099 try {
100 if (e instanceof AssumptionViolatedException) {
101 skipped((AssumptionViolatedException) e, description);
102 } else {
103 skipped(e, description);
104 }
105 } catch (Throwable e1) {
106 errors.add(e1);
107 }
108 }
109
110 private void startingQuietly(Description description,
111 List<Throwable> errors) {
112 try {
113 starting(description);
114 } catch (Throwable e) {
115 errors.add(e);
116 }
117 }
118
119 private void finishedQuietly(Description description,
120 List<Throwable> errors) {
121 try {
122 finished(description);
123 } catch (Throwable e) {
124 errors.add(e);
125 }
126 }
127
128 /**
129 * Invoked when a test succeeds
130 */
131 protected void succeeded(Description description) {
132 }
133
134 /**
135 * Invoked when a test fails
136 */
137 protected void failed(Throwable e, Description description) {
138 }
139
140 /**
141 * Invoked when a test is skipped due to a failed assumption.
142 */
143 protected void skipped(AssumptionViolatedException e, Description description) {
144 // For backwards compatibility with JUnit 4.11 and earlier, call the legacy version
145 org.junit.internal.AssumptionViolatedException asInternalException = e;
146 skipped(asInternalException, description);
147 }
148
149 /**
150 * Invoked when a test is skipped due to a failed assumption.
151 *
152 * @deprecated use {@link #skipped(AssumptionViolatedException, Description)}
153 */
154 @Deprecated
155 protected void skipped(
156 org.junit.internal.AssumptionViolatedException e, Description description) {
157 }
158
159 /**
160 * Invoked when a test is about to start
161 */
162 protected void starting(Description description) {
163 }
164
165 /**
166 * Invoked when a test method finishes (whether passing or failing)
167 */
168 protected void finished(Description description) {
169 }
170 }