package org.junit.rules;
import org.junit.internal.AssumptionViolatedException;
import org.junit.runner.Description;
import java.util.concurrent.TimeUnit;
/**
* The Stopwatch Rule notifies one of its own protected methods of the time spent by a test.
*
* <p>Override them to get the time in nanoseconds. For example, this class will keep logging the
* time spent by each passed, failed, skipped, and finished test:
*
* <pre>
* public static class StopwatchTest {
* private static final Logger logger= Logger.getLogger("");
*
* private static void logInfo(String testName, String status, long nanos) {
* logger.info(String.format("Test %s %s, spent %d microseconds",
* testName, status, Stopwatch.toMicros(nanos)));
* }
*
* @Rule
* public Stopwatch stopwatch= new Stopwatch() {
* @Override
* protected void succeeded(long nanos, Description description) {
* logInfo(description.getMethodName(), "succeeded", nanos);
* }
*
* @Override
* protected void failed(long nanos, Throwable e, Description description) {
* logInfo(description.getMethodName(), "failed", nanos);
* }
*
* @Override
* protected void skipped(long nanos, AssumptionViolatedException e, Description description) {
* logInfo(description.getMethodName(), "skipped", nanos);
* }
*
* @Override
* protected void finished(long nanos, Description description) {
* logInfo(description.getMethodName(), "finished", nanos);
* }
* };
*
* @Test
* public void succeeds() {
* }
*
* @Test
* public void fails() {
* fail();
* }
*
* @Test
* public void skips() {
* assumeTrue(false);
* }
* }
* </pre>
*
* An example to assert runtime:
* <pre>
* @Test
* public void performanceTest() throws InterruptedException {
* long delta= 30;
* Thread.sleep(300L);
* assertEquals(300d, stopwatch.runtime(MILLISECONDS), delta);
* Thread.sleep(500L);
* assertEquals(800d, stopwatch.runtime(MILLISECONDS), delta);
* }
* </pre>
*
* @author tibor17
* @since 4.12
*/
public class Stopwatch extends TestWatcher {
private long fStartNanos;
private long fEndNanos;
/**
* @param unit time unit for returned runtime
* @return runtime measured during the test
*/
public long runtime(TimeUnit unit) {
return unit.convert(currentNanoTime() - fStartNanos, TimeUnit.NANOSECONDS);
}
/**
* Invoked when a test succeeds
*/
protected void succeeded(long nanos, Description description) {
}
/**
* Invoked when a test fails
*/
protected void failed(long nanos, Throwable e, Description description) {
}
/**
* Invoked when a test is skipped due to a failed assumption.
*/
protected void skipped(long nanos, AssumptionViolatedException e, Description description) {
}
/**
* Invoked when a test method finishes (whether passing or failing)
*/
protected void finished(long nanos, Description description) {
}
/**
* @param nanos time in nanoseconds
* @return time converted to microseconds
*/
public static long toMicros(long nanos) {
return TimeUnit.NANOSECONDS.toMicros(nanos);
}
/**
* @param nanos time in nanoseconds
* @return time converted to milliseconds
*/
public static long toMillis(long nanos) {
return TimeUnit.NANOSECONDS.toMillis(nanos);
}
/**
* @param nanos time in nanoseconds
* @return time converted to seconds
*/
public static long toSeconds(long nanos) {
return TimeUnit.NANOSECONDS.toSeconds(nanos);
}
private long getNanos() {
return fEndNanos - fStartNanos;
}
private void starting() {
fStartNanos= currentNanoTime();
}
private void stopping() {
fEndNanos= currentNanoTime();
}
private long currentNanoTime() {
return System.nanoTime();
}
@Override final protected void succeeded(Description description) {
stopping();
succeeded(getNanos(), description);
}
@Override final protected void failed(Throwable e, Description description) {
stopping();
failed(getNanos(), e, description);
}
@Override final protected void skipped(AssumptionViolatedException e, Description description) {
stopping();
skipped(getNanos(), e, description);
}
@Override final protected void starting(Description description) {
starting();
}
@Override final protected void finished(Description description) {
finished(getNanos(), description);
}
}