1 package org.junit.rules; 2 3 import java.util.ArrayList; 4 import java.util.List; 5 6 import org.junit.AssumptionViolatedException; 7 import org.junit.Rule; 8 import org.junit.runner.Description; 9 import org.junit.runners.model.MultipleFailureException; 10 import org.junit.runners.model.Statement; 11 12 /** 13 * TestWatcher is a base class for Rules that take note of the testing 14 * action, without modifying it. For example, this class will keep a log of each 15 * passing and failing test: 16 * 17 * <pre> 18 * public static class WatchmanTest { 19 * private static String watchedLog; 20 * 21 * @Rule(order = Integer.MIN_VALUE) 22 * public TestWatcher watchman= new TestWatcher() { 23 * @Override 24 * protected void failed(Throwable e, Description description) { 25 * watchedLog+= description + "\n"; 26 * } 27 * 28 * @Override 29 * protected void succeeded(Description description) { 30 * watchedLog+= description + " " + "success!\n"; 31 * } 32 * }; 33 * 34 * @Test 35 * public void fails() { 36 * fail(); 37 * } 38 * 39 * @Test 40 * public void succeeds() { 41 * } 42 * } 43 * </pre> 44 * <p>It is recommended to always set the {@link Rule#order() order} of the 45 * {@code TestWatcher} to {@code Integer.MIN_VALUE} so that it encloses all 46 * other rules. Otherwise it may see failed tests as successful and vice versa 47 * if some rule changes the result of a test (e.g. {@link ErrorCollector} or 48 * {@link ExpectedException}). 49 * 50 * @since 4.9 51 */ 52 public abstract class TestWatcher implements TestRule { apply(final Statement base, final Description description)53 public Statement apply(final Statement base, final Description description) { 54 return new Statement() { 55 @Override 56 public void evaluate() throws Throwable { 57 List<Throwable> errors = new ArrayList<Throwable>(); 58 59 startingQuietly(description, errors); 60 try { 61 base.evaluate(); 62 succeededQuietly(description, errors); 63 } catch (org.junit.internal.AssumptionViolatedException e) { 64 errors.add(e); 65 skippedQuietly(e, description, errors); 66 } catch (Throwable e) { 67 errors.add(e); 68 failedQuietly(e, description, errors); 69 } finally { 70 finishedQuietly(description, errors); 71 } 72 73 MultipleFailureException.assertEmpty(errors); 74 } 75 }; 76 } 77 78 private void succeededQuietly(Description description, 79 List<Throwable> errors) { 80 try { 81 succeeded(description); 82 } catch (Throwable e) { 83 errors.add(e); 84 } 85 } 86 87 private void failedQuietly(Throwable e, Description description, 88 List<Throwable> errors) { 89 try { 90 failed(e, description); 91 } catch (Throwable e1) { 92 errors.add(e1); 93 } 94 } 95 96 private void skippedQuietly( 97 org.junit.internal.AssumptionViolatedException e, Description description, 98 List<Throwable> errors) { 99 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 } 171