1 package org.junit.rules;
2
3 import java.util.concurrent.TimeUnit;
4
5 import org.junit.AssumptionViolatedException;
6 import org.junit.Before;
7 import org.junit.Rule;
8 import org.junit.Test;
9 import org.junit.rules.Stopwatch;
10 import org.junit.runner.Description;
11 import org.junit.runner.JUnitCore;
12 import org.junit.runner.Request;
13 import org.junit.runner.Result;
14 import static java.util.concurrent.TimeUnit.MILLISECONDS;
15 import static org.hamcrest.core.Is.is;
16 import static org.junit.Assert.assertEquals;
17 import static org.junit.Assert.assertThat;
18 import static org.junit.Assume.assumeTrue;
19 import static org.junit.Assert.assertTrue;
20 import static org.junit.Assert.fail;
21 import static org.junit.Assert.assertNotEquals;
22
23
24
25
26
27 public class StopwatchTest {
28 private static enum TestStatus { SUCCEEDED, FAILED, SKIPPED }
29 private static Record record;
30 private static Record finishedRecord;
31 private static long fakeTimeNanos = 1234;
32
33 private static class Record {
34 final long duration;
35 final String name;
36 final TestStatus status;
37
38 Record() {
39 this(0, null, null);
40 }
41
42 Record(long duration, Description description) {
43 this(duration, null, description);
44 }
45
46 Record(long duration, TestStatus status, Description description) {
47 this.duration = duration;
48 this.status = status;
49 this.name = description == null ? null : description.getMethodName();
50 }
51 }
52
53 public static abstract class AbstractStopwatchTest {
54
55
56
57
58
59 private final Stopwatch.Clock fakeClock = new Stopwatch.Clock() {
60 @Override
61 public long nanoTime() {
62 return fakeTimeNanos++;
63 }
64 };
65
66 protected final Stopwatch stopwatch = new Stopwatch(fakeClock) {
67 @Override
68 protected void succeeded(long nanos, Description description) {
69 StopwatchTest.record = new Record(nanos, TestStatus.SUCCEEDED, description);
70 simulateTimePassing(1);
71 }
72
73 @Override
74 protected void failed(long nanos, Throwable e, Description description) {
75 StopwatchTest.record = new Record(nanos, TestStatus.FAILED, description);
76 simulateTimePassing(1);
77 }
78
79 @Override
80 protected void skipped(long nanos, AssumptionViolatedException e, Description description) {
81 StopwatchTest.record = new Record(nanos, TestStatus.SKIPPED, description);
82 simulateTimePassing(1);
83 }
84
85 @Override
86 protected void finished(long nanos, Description description) {
87 StopwatchTest.finishedRecord = new Record(nanos, description);
88 }
89 };
90
91 private final TestWatcher watcher = new TestWatcher() {
92 @Override
93 protected void finished(Description description) {
94 afterStopwatchRule();
95 }
96 };
97
98 @Rule
99 public final RuleChain chain = RuleChain
100 .outerRule(watcher)
101 .around(stopwatch);
102
103 protected void afterStopwatchRule() {
104 }
105 }
106
107 public static class SuccessfulTest extends AbstractStopwatchTest {
108 @Test
109 public void successfulTest() {
110 }
111 }
112
113 public static class FailedTest extends AbstractStopwatchTest {
114 @Test
115 public void failedTest() {
116 fail();
117 }
118 }
119
120 public static class SkippedTest extends AbstractStopwatchTest {
121 @Test
122 public void skippedTest() {
123 assumeTrue(false);
124 }
125 }
126
127 public static class DurationDuringTestTest extends AbstractStopwatchTest {
128 @Test
129 public void duration() {
130 simulateTimePassing(300L);
131 assertEquals(300L, stopwatch.runtime(MILLISECONDS));
132 simulateTimePassing(500L);
133 assertEquals(800L, stopwatch.runtime(MILLISECONDS));
134 }
135 }
136
137 public static class DurationAfterTestTest extends AbstractStopwatchTest {
138 @Test
139 public void duration() {
140 simulateTimePassing(300L);
141 assertEquals(300L, stopwatch.runtime(MILLISECONDS));
142 }
143
144 @Override
145 protected void afterStopwatchRule() {
146 assertEquals(300L, stopwatch.runtime(MILLISECONDS));
147 simulateTimePassing(500L);
148 assertEquals(300L, stopwatch.runtime(MILLISECONDS));
149 }
150 }
151
152 @Before
153 public void init() {
154 record = new Record();
155 finishedRecord = new Record();
156 simulateTimePassing(1L);
157 }
158
159 private static Result runTest(Class<?> test) {
160 simulateTimePassing(1L);
161 JUnitCore junitCore = new JUnitCore();
162 return junitCore.run(Request.aClass(test).getRunner());
163 }
164
165 private static void simulateTimePassing(long millis) {
166 fakeTimeNanos += TimeUnit.MILLISECONDS.toNanos(millis);
167 }
168
169 @Test
170 public void succeeded() {
171 Result result = runTest(SuccessfulTest.class);
172 assertEquals(0, result.getFailureCount());
173 assertThat(record.name, is("successfulTest"));
174 assertThat(record.name, is(finishedRecord.name));
175 assertThat(record.status, is(TestStatus.SUCCEEDED));
176 assertTrue("timeSpent > 0", record.duration > 0);
177 assertThat(record.duration, is(finishedRecord.duration));
178 }
179
180 @Test
181 public void failed() {
182 Result result = runTest(FailedTest.class);
183 assertEquals(1, result.getFailureCount());
184 assertThat(record.name, is("failedTest"));
185 assertThat(record.name, is(finishedRecord.name));
186 assertThat(record.status, is(TestStatus.FAILED));
187 assertTrue("timeSpent > 0", record.duration > 0);
188 assertThat(record.duration, is(finishedRecord.duration));
189 }
190
191 @Test
192 public void skipped() {
193 Result result = runTest(SkippedTest.class);
194 assertEquals(0, result.getFailureCount());
195 assertThat(record.name, is("skippedTest"));
196 assertThat(record.name, is(finishedRecord.name));
197 assertThat(record.status, is(TestStatus.SKIPPED));
198 assertTrue("timeSpent > 0", record.duration > 0);
199 assertThat(record.duration, is(finishedRecord.duration));
200 }
201
202 @Test
203 public void runtimeDuringTestShouldReturnTimeSinceStart() {
204 Result result = runTest(DurationDuringTestTest.class);
205 assertTrue(result.wasSuccessful());
206 }
207
208 @Test
209 public void runtimeAfterTestShouldReturnRunDuration() {
210 Result result = runTest(DurationAfterTestTest.class);
211 assertTrue(result.wasSuccessful());
212 }
213 }