001package org.junit.rules;
002
003import java.util.ArrayList;
004import java.util.List;
005
006import org.junit.internal.AssumptionViolatedException;
007import org.junit.runner.Description;
008import org.junit.runners.model.MultipleFailureException;
009import 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 *  &#064;Rule
021 *  public TestWatcher watchman= new TestWatcher() {
022 *      &#064;Override
023 *      protected void failed(Throwable e, Description description) {
024 *          watchedLog+= description + &quot;\n&quot;;
025 *      }
026 *
027 *      &#064;Override
028 *      protected void succeeded(Description description) {
029 *          watchedLog+= description + &quot; &quot; + &quot;success!\n&quot;;
030 *         }
031 *     };
032 *
033 *  &#064;Test
034 *  public void fails() {
035 *      fail();
036 *  }
037 *
038 *  &#064;Test
039 *  public void succeeds() {
040 *     }
041 * }
042 * </pre>
043 *
044 * @since 4.9
045 */
046public 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 (AssumptionViolatedException e) {
058                    errors.add(e);
059                    skippedQuietly(e, description, errors);
060                } catch (Throwable t) {
061                    errors.add(t);
062                    failedQuietly(t, 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 t) {
077            errors.add(t);
078        }
079    }
080
081    private void failedQuietly(Throwable t, Description description,
082            List<Throwable> errors) {
083        try {
084            failed(t, description);
085        } catch (Throwable t1) {
086            errors.add(t1);
087        }
088    }
089
090    private void skippedQuietly(AssumptionViolatedException e, Description description,
091            List<Throwable> errors) {
092        try {
093            skipped(e, description);
094        } catch (Throwable t) {
095            errors.add(t);
096        }
097    }
098
099    private void startingQuietly(Description description,
100            List<Throwable> errors) {
101        try {
102            starting(description);
103        } catch (Throwable t) {
104            errors.add(t);
105        }
106    }
107
108    private void finishedQuietly(Description description,
109            List<Throwable> errors) {
110        try {
111            finished(description);
112        } catch (Throwable t) {
113            errors.add(t);
114        }
115    }
116
117    /**
118     * Invoked when a test succeeds
119     */
120    protected void succeeded(Description description) {
121    }
122
123    /**
124     * Invoked when a test fails
125     */
126    protected void failed(Throwable e, Description description) {
127    }
128
129    /**
130     * Invoked when a test is skipped due to a failed assumption.
131     */
132    protected void skipped(AssumptionViolatedException e, Description description) {
133    }
134
135    /**
136     * Invoked when a test is about to start
137     */
138    protected void starting(Description description) {
139    }
140
141    /**
142     * Invoked when a test method finishes (whether passing or failing)
143     */
144    protected void finished(Description description) {
145    }
146}