// Copyright © 2011-2013, Esko Luontola <www.orfjackal.net>
// This software is released under the Apache License 2.0.
// The license text is at http://www.apache.org/licenses/LICENSE-2.0
package fi.jumi.core.junit;
import fi.jumi.api.drivers.TestId;
import fi.jumi.core.api.*;
import fi.jumi.core.results.*;
import fi.jumi.core.testbench.TestBench;
import fi.jumi.core.util.SpyListener;
import org.junit.*;
import org.junit.experimental.runners.Enclosed;
import org.junit.runner.*;
import org.junit.runner.notification.*;
import java.util.Arrays;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.*;
import static org.mockito.Matchers.eq;
import static org.mockito.Matchers.notNull;
import static org.mockito.Mockito.*;
public class JUnitCompatibilityDriverTest {
private final TestBench testBench = new TestBench();
private final SpyListener<RunVisitor> spy = new SpyListener<>(RunVisitor.class);
private final RunVisitor expect = spy.getListener();
private TestFile testFile;
private SuiteEventDemuxer results;
@Before
public void setup() {
testBench.setDriverFinder(new JUnitCompatibilityDriverFinder());
// testBench.setActorsMessageListener(new PrintStreamMessageLogger(System.out));
}
private void runTestClass(Class<?> testClass) {
testFile = TestFile.fromClass(testClass);
results = testBench.run(testClass);
}
private void checkExpectations() {
spy.replay();
results.visitAllRuns(expect);
spy.verify();
}
@Test
public void single_passing_test() {
runTestClass(OnePassing.class);
assertThat(results.getTestName(testFile, TestId.ROOT), is("OnePassing"));
assertThat(results.getTestName(testFile, TestId.of(0)), is("testPassing"));
expect.onRunStarted(new RunId(1), testFile);
expect.onTestStarted(new RunId(1), testFile, TestId.ROOT);
expect.onTestStarted(new RunId(1), testFile, TestId.of(0));
expect.onTestFinished(new RunId(1), testFile, TestId.of(0));
expect.onTestFinished(new RunId(1), testFile, TestId.ROOT);
expect.onRunFinished(new RunId(1), testFile);
checkExpectations();
}
@Test
public void single_failing_test() {
runTestClass(OneFailing.class);
assertThat(results.getTestName(testFile, TestId.ROOT), is("OneFailing"));
assertThat(results.getTestName(testFile, TestId.of(0)), is("testFailing"));
expect.onRunStarted(new RunId(1), testFile);
expect.onTestStarted(new RunId(1), testFile, TestId.ROOT);
expect.onTestStarted(new RunId(1), testFile, TestId.of(0));
expect.onFailure(new RunId(1), testFile, TestId.of(0), StackTrace.from(new AssertionError("dummy failure")));
expect.onTestFinished(new RunId(1), testFile, TestId.of(0));
expect.onTestFinished(new RunId(1), testFile, TestId.ROOT);
expect.onRunFinished(new RunId(1), testFile);
checkExpectations();
}
@Test
public void multiple_passing_tests() {
runTestClass(TwoPassing.class);
assertThat(results.getTestName(testFile, TestId.ROOT), is("TwoPassing"));
String name0 = results.getTestName(testFile, TestId.of(0));
String name1 = results.getTestName(testFile, TestId.of(1));
assertThat(Arrays.asList(name0, name1), containsInAnyOrder("testOne", "testTwo")); // JUnit's order of test methods is undefined
expect.onRunStarted(new RunId(1), testFile);
expect.onTestStarted(new RunId(1), testFile, TestId.ROOT);
expect.onTestStarted(new RunId(1), testFile, TestId.of(0));
expect.onTestFinished(new RunId(1), testFile, TestId.of(0));
expect.onTestFinished(new RunId(1), testFile, TestId.ROOT);
expect.onRunFinished(new RunId(1), testFile);
expect.onRunStarted(new RunId(2), testFile);
expect.onTestStarted(new RunId(2), testFile, TestId.ROOT);
expect.onTestStarted(new RunId(2), testFile, TestId.of(1));
expect.onTestFinished(new RunId(2), testFile, TestId.of(1));
expect.onTestFinished(new RunId(2), testFile, TestId.ROOT);
expect.onRunFinished(new RunId(2), testFile);
checkExpectations();
}
@Test
public void deep_test_hierarchies() {
runTestClass(DeepHierarchy.class);
assertThat(results.getTestName(testFile, TestId.ROOT), is("DeepHierarchy"));
assertThat(results.getTestName(testFile, TestId.of(0)), is("NestedContext"));
assertThat(results.getTestName(testFile, TestId.of(0, 0)), is("theLeaf"));
expect.onRunStarted(new RunId(1), testFile);
expect.onTestStarted(new RunId(1), testFile, TestId.ROOT);
expect.onTestStarted(new RunId(1), testFile, TestId.of(0));
expect.onTestStarted(new RunId(1), testFile, TestId.of(0, 0));
expect.onTestFinished(new RunId(1), testFile, TestId.of(0, 0));
expect.onTestFinished(new RunId(1), testFile, TestId.of(0));
expect.onTestFinished(new RunId(1), testFile, TestId.ROOT);
expect.onRunFinished(new RunId(1), testFile);
checkExpectations();
}
@Test
public void reports_JUnit_test_mechanism_failures_as_internal_errors() {
SuiteListener listener = mock(SuiteListener.class);
testBench.run(listener, Buggy.class);
verify(listener).onInternalError(eq("Failure in JUnit test mechanism"), notNull(StackTrace.class));
}
// TODO: ignored tests
// TODO: assumptions
public static class OnePassing {
@Test
public void testPassing() {
}
}
public static class OneFailing {
@Test
public void testFailing() {
throw new AssertionError("dummy failure");
}
}
public static class TwoPassing {
@Test
public void testOne() {
}
@Test
public void testTwo() {
}
}
@RunWith(Enclosed.class)
public static class DeepHierarchy {
public static class NestedContext {
@Test
public void theLeaf() {
}
}
}
@RunWith(BuggyJUnitRunner.class)
private static class Buggy {
}
public static class BuggyJUnitRunner extends Runner {
private final Class<?> testClass;
public BuggyJUnitRunner(Class<?> testClass) {
this.testClass = testClass;
}
@Override
public Description getDescription() {
return Description.createSuiteDescription(testClass);
}
@Override
public void run(RunNotifier notifier) {
notifier.fireTestFailure(new Failure(Description.TEST_MECHANISM, new RuntimeException("dummy exception")));
}
}
}