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     *  &#064;Rule(order = Integer.MIN_VALUE)
022     *  public TestWatcher watchman= new TestWatcher() {
023     *      &#064;Override
024     *      protected void failed(Throwable e, Description description) {
025     *          watchedLog+= description + &quot;\n&quot;;
026     *      }
027     *
028     *      &#064;Override
029     *      protected void succeeded(Description description) {
030     *          watchedLog+= description + &quot; &quot; + &quot;success!\n&quot;;
031     *         }
032     *     };
033     *
034     *  &#064;Test
035     *  public void fails() {
036     *      fail();
037     *  }
038     *
039     *  &#064;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    }