package org.junit.tests.running.classes; import static org.hamcrest.CoreMatchers.equalTo; import static org.hamcrest.CoreMatchers.is; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertThat; import java.util.List; import org.hamcrest.Matcher; import org.hamcrest.TypeSafeMatcher; import org.junit.Assert; import org.junit.BeforeClass; import org.junit.Ignore; import org.junit.Test; import org.junit.internal.AssumptionViolatedException; import org.junit.runner.Description; import org.junit.runner.JUnitCore; import org.junit.runner.Request; import org.junit.runner.Result; import org.junit.runner.manipulation.Filter; import org.junit.runner.notification.Failure; import org.junit.runner.notification.RunListener; import org.junit.runner.notification.RunNotifier; import org.junit.runners.BlockJUnit4ClassRunner; import org.junit.runners.ParentRunner; import org.junit.runners.model.InitializationError; import org.junit.runners.model.RunnerScheduler; import org.junit.tests.experimental.rules.RuleFieldValidatorTest.TestWithNonStaticClassRule; import org.junit.tests.experimental.rules.RuleFieldValidatorTest.TestWithProtectedClassRule; public class ParentRunnerTest { public static String log = ""; public static class FruitTest { @Test public void apple() { log += "apple "; } @Test public void /* must hash-sort after "apple" */Banana() { log += "banana "; } } @Test public void useChildHarvester() throws InitializationError { log = ""; ParentRunner<?> runner = new BlockJUnit4ClassRunner(FruitTest.class); runner.setScheduler(new RunnerScheduler() { public void schedule(Runnable childStatement) { log += "before "; childStatement.run(); log += "after "; } public void finished() { log += "afterAll "; } }); runner.run(new RunNotifier()); assertEquals("before apple after before banana after afterAll ", log); } @Test public void testMultipleFilters() throws Exception { JUnitCore junitCore = new JUnitCore(); Request request = Request.aClass(ExampleTest.class); Request requestFiltered = request.filterWith(new Exclude("test1")); Request requestFilteredFiltered = requestFiltered .filterWith(new Exclude("test2")); Result result = junitCore.run(requestFilteredFiltered); assertThat(result.getFailures(), isEmpty()); assertEquals(1, result.getRunCount()); } private Matcher<List<?>> isEmpty() { return new TypeSafeMatcher<List<?>>() { public void describeTo(org.hamcrest.Description description) { description.appendText("is empty"); } @Override public boolean matchesSafely(List<?> item) { return item.size() == 0; } }; } private static class Exclude extends Filter { private final String methodName; public Exclude(String methodName) { this.methodName = methodName; } @Override public boolean shouldRun(Description description) { return !description.getMethodName().equals(methodName); } @Override public String describe() { return "filter method name: " + methodName; } } public static class ExampleTest { @Test public void test1() throws Exception { } @Test public void test2() throws Exception { } @Test public void test3() throws Exception { } } @Test public void failWithHelpfulMessageForProtectedClassRule() { assertClassHasFailureMessage(TestWithProtectedClassRule.class, "The @ClassRule 'temporaryFolder' must be public."); } @Test public void failWithHelpfulMessageForNonStaticClassRule() { assertClassHasFailureMessage(TestWithNonStaticClassRule.class, "The @ClassRule 'temporaryFolder' must be static."); } static class NonPublicTestClass { public NonPublicTestClass() { } } @Test public void cannotBeCreatedWithNonPublicTestClass() { assertClassHasFailureMessage( NonPublicTestClass.class, "The class org.junit.tests.running.classes.ParentRunnerTest$NonPublicTestClass is not public."); } private void assertClassHasFailureMessage(Class<?> klass, String message) { JUnitCore junitCore = new JUnitCore(); Request request = Request.aClass(klass); Result result = junitCore.run(request); assertThat(result.getFailureCount(), is(2)); //the second failure is no runnable methods assertThat(result.getFailures().get(0).getMessage(), is(equalTo(message))); } public static class AssertionErrorAtParentLevelTest { @BeforeClass public static void beforeClass() throws Throwable { throw new AssertionError("Thrown from @BeforeClass"); } @Test public void test() {} } @Test public void assertionErrorAtParentLevelTest() throws InitializationError { CountingRunListener countingRunListener = runTestWithParentRunner(AssertionErrorAtParentLevelTest.class); Assert.assertEquals(0, countingRunListener.testStarted); Assert.assertEquals(0, countingRunListener.testFinished); Assert.assertEquals(1, countingRunListener.testFailure); Assert.assertEquals(0, countingRunListener.testAssumptionFailure); Assert.assertEquals(0, countingRunListener.testIgnored); } public static class AssumptionViolatedAtParentLevelTest { @BeforeClass public static void beforeClass() { throw new AssumptionViolatedException("Thrown from @BeforeClass"); } @Test public void test() {} } @Test public void assumptionViolatedAtParentLevel() throws InitializationError { CountingRunListener countingRunListener = runTestWithParentRunner(AssumptionViolatedAtParentLevelTest.class); Assert.assertEquals(0, countingRunListener.testStarted); Assert.assertEquals(0, countingRunListener.testFinished); Assert.assertEquals(0, countingRunListener.testFailure); Assert.assertEquals(1, countingRunListener.testAssumptionFailure); Assert.assertEquals(0, countingRunListener.testIgnored); } public static class TestTest { @Test public void pass() {} @Test public void fail() { throw new AssertionError("Thrown from @Test"); } @Ignore @Test public void ignore() {} @Test public void assumptionFail() { throw new AssumptionViolatedException("Thrown from @Test"); } } @Test public void parentRunnerTestMethods() throws InitializationError { CountingRunListener countingRunListener = runTestWithParentRunner(TestTest.class); Assert.assertEquals(3, countingRunListener.testStarted); Assert.assertEquals(3, countingRunListener.testFinished); Assert.assertEquals(1, countingRunListener.testFailure); Assert.assertEquals(1, countingRunListener.testAssumptionFailure); Assert.assertEquals(1, countingRunListener.testIgnored); } private CountingRunListener runTestWithParentRunner(Class<?> testClass) throws InitializationError { CountingRunListener listener = new CountingRunListener(); RunNotifier runNotifier = new RunNotifier(); runNotifier.addListener(listener); ParentRunner runner = new BlockJUnit4ClassRunner(testClass); runner.run(runNotifier); return listener; } private static class CountingRunListener extends RunListener { private int testStarted = 0; private int testFinished = 0; private int testFailure = 0; private int testAssumptionFailure = 0; private int testIgnored = 0; @Override public void testStarted(Description description) throws Exception { testStarted++; } @Override public void testFinished(Description description) throws Exception { testFinished++; } @Override public void testFailure(Failure failure) throws Exception { testFailure++; } @Override public void testAssumptionFailure(Failure failure) { testAssumptionFailure++; } @Override public void testIgnored(Description description) throws Exception { testIgnored++; } } }