package com.carrotsearch.randomizedtesting;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Assert;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.runner.JUnitCore;
import org.junit.runner.Request;
import org.junit.runner.Result;
import org.junit.runner.Runner;
import org.junit.runner.notification.RunListener;
import org.junit.runner.notification.RunNotifier;
import com.carrotsearch.randomizedtesting.annotations.Repeat;
/**
* Try to be compatible with JUnit's runners wrt method hooks throwing
* exceptions.
*/
public class TestHookMethodOrderWithExceptions extends RandomizedTest {
static final List<String> callOrder = new ArrayList<String>();
/*
* We don't want to run nested classes as separate tests, but eclipse still
* wants to run them. this is a hack, but I don't know how to do it cleaner.
*/
static boolean testExecution;
/**
* Test superclass.
*/
public static class Super {
static Random rnd;
@BeforeClass
public static void beforeClassSuper() {
callOrder.add("beforeClassSuper");
maybeThrowException();
}
@Before
public final void beforeTest() {
callOrder.add("beforeTestSuper");
maybeThrowException();
}
@After
public final void afterTest() {
callOrder.add("afterTestSuper");
maybeThrowException();
}
@AfterClass
public static void afterClassSuper() {
callOrder.add("afterClassSuper");
maybeThrowException();
}
public static void maybeThrowException() {
if (testExecution && rnd.nextInt(10) == 0) {
throw new RuntimeException();
}
}
}
/**
* Test subclass.
*/
public static class SubSub extends Super {
@BeforeClass
public static void beforeClass() {
callOrder.add("beforeClassSub");
maybeThrowException();
}
@Before
public void beforeTestSub() {
callOrder.add("beforeTestSub");
maybeThrowException();
}
@Test
public void testMethod() {
callOrder.add("testMethodSub");
maybeThrowException();
}
@After
public void afterTestSub() {
callOrder.add("afterTestSub");
maybeThrowException();
}
@AfterClass
public static void afterClass() {
callOrder.add("afterClassSub");
maybeThrowException();
}
}
@Before
public void setup() {
callOrder.clear();
testExecution = true;
}
@After
public void cleanup() {
callOrder.clear();
testExecution = false;
}
@Test @Repeat(iterations = 20)
public void checkOrderSameAsJUnit() throws Exception {
long seed = RandomizedContext.current().getRandomness().getSeed();
callOrder.clear();
Super.rnd = new Random(seed);
Result junit = JUnitCore.runClasses(SubSub.class);
List<String> junitOrder = new ArrayList<String>(callOrder);
callOrder.clear();
Super.rnd = new Random(seed);
Result rrunner = runRequest(Request.runner(new RandomizedRunner(SubSub.class)));
List<String> rrunnerOrder = new ArrayList<String>(callOrder);
Assert.assertEquals(junitOrder, rrunnerOrder);
Assert.assertEquals(junit.getRunCount(), rrunner.getRunCount());
}
private Result runRequest(Request request) {
Result result = new Result();
RunNotifier notifier = new RunNotifier();
RunListener listener = result.createListener();
notifier.addFirstListener(listener);
try {
Runner runner = request.getRunner();
notifier.fireTestRunStarted(runner.getDescription());
runner.run(notifier);
notifier.fireTestRunFinished(result);
} finally {
notifier.removeListener(listener);
}
return result;
}
}