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