    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    }