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