001package org.junit.rules;
002
003import java.util.ArrayList;
004import java.util.List;
005
006import org.junit.AssumptionViolatedException;
007import org.junit.Rule;
008import org.junit.runner.Description;
009import org.junit.runners.model.MultipleFailureException;
010import 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 */
052public 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}