/* * Copyright 2015-2017 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v1.0 which * accompanies this distribution and is available at * * http://www.eclipse.org/legal/epl-v10.html */ package org.junit.jupiter.engine; import static java.util.Arrays.asList; import static org.junit.jupiter.api.Assertions.assertAll; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.fail; import static org.junit.jupiter.api.Assumptions.assumeTrue; import static org.junit.platform.engine.discovery.DiscoverySelectors.selectMethod; import static org.junit.platform.launcher.core.LauncherDiscoveryRequestBuilder.request; import java.util.ArrayList; import java.util.List; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.platform.engine.test.event.ExecutionEventRecorder; import org.junit.platform.launcher.LauncherDiscoveryRequest; /** * Integration tests for test class hierarchy support in the {@link JupiterTestEngine}. * * @since 5.0 */ class TestCaseWithInheritanceTests extends AbstractJupiterTestEngineTests { private static final List<String> callSequence = new ArrayList<>(); @BeforeEach void initStatics() { callSequence.clear(); LocalTestCase.countBeforeInvoked = 0; LocalTestCase.countAfterInvoked = 0; AbstractTestCase.countSuperBeforeInvoked = 0; AbstractTestCase.countSuperAfterInvoked = 0; } @Test void executeAllTestsInClass() { ExecutionEventRecorder eventRecorder = executeTestsForClass(LocalTestCase.class); assertEquals(6, eventRecorder.getTestStartedCount(), "# tests started"); assertEquals(3, eventRecorder.getTestSuccessfulCount(), "# tests succeeded"); assertEquals(0, eventRecorder.getTestSkippedCount(), "# tests skipped"); assertEquals(1, eventRecorder.getTestAbortedCount(), "# tests aborted"); assertEquals(2, eventRecorder.getTestFailedCount(), "# tests failed"); assertEquals(6, LocalTestCase.countBeforeInvoked, "# before calls"); assertEquals(6, LocalTestCase.countAfterInvoked, "# after calls"); assertEquals(6, AbstractTestCase.countSuperBeforeInvoked, "# super before calls"); assertEquals(6, AbstractTestCase.countSuperAfterInvoked, "# super after calls"); } @Test void executeSingleTest() { LauncherDiscoveryRequest request = request().selectors( selectMethod(LocalTestCase.class, "alwaysPasses")).build(); ExecutionEventRecorder eventRecorder = executeTests(request); assertEquals(1, eventRecorder.getTestStartedCount(), "# tests started"); assertEquals(1, eventRecorder.getTestSuccessfulCount(), "# tests succeeded"); assertEquals(0, eventRecorder.getTestSkippedCount(), "# tests skipped"); assertEquals(0, eventRecorder.getTestAbortedCount(), "# tests aborted"); assertEquals(0, eventRecorder.getTestFailedCount(), "# tests failed"); } @Test void executeTestDeclaredInSuperClass() { LauncherDiscoveryRequest request = request().selectors(selectMethod(LocalTestCase.class, "superTest")).build(); ExecutionEventRecorder eventRecorder = executeTests(request); assertEquals(1, eventRecorder.getTestStartedCount(), "# tests started"); assertEquals(1, eventRecorder.getTestSuccessfulCount(), "# tests succeeded"); assertEquals(0, eventRecorder.getTestSkippedCount(), "# tests skipped"); assertEquals(0, eventRecorder.getTestAbortedCount(), "# tests aborted"); assertEquals(0, eventRecorder.getTestFailedCount(), "# tests failed"); assertEquals(1, LocalTestCase.countBeforeInvoked, "# after calls"); assertEquals(1, LocalTestCase.countAfterInvoked, "# after calls"); assertEquals(1, AbstractTestCase.countSuperBeforeInvoked, "# super before calls"); assertEquals(1, AbstractTestCase.countSuperAfterInvoked, "# super after calls"); } @Test void executeTestWithExceptionThrownInAfterMethod() { LauncherDiscoveryRequest request = request().selectors( selectMethod(LocalTestCase.class, "throwExceptionInAfterMethod")).build(); ExecutionEventRecorder eventRecorder = executeTests(request); assertEquals(1, eventRecorder.getTestStartedCount(), "# tests started"); assertEquals(0, eventRecorder.getTestSuccessfulCount(), "# tests succeeded"); assertEquals(0, eventRecorder.getTestSkippedCount(), "# tests skipped"); assertEquals(0, eventRecorder.getTestAbortedCount(), "# tests aborted"); assertEquals(1, eventRecorder.getTestFailedCount(), "# tests failed"); } @Test void beforeAndAfterMethodsInTestClassHierarchy() { ExecutionEventRecorder eventRecorder = executeTestsForClass(TestCase3.class); // @formatter:off assertAll( () -> assertEquals(1, eventRecorder.getTestStartedCount(), "# tests started"), () -> assertEquals(1, eventRecorder.getTestSuccessfulCount(), "# tests succeeded"), () -> assertEquals(0, eventRecorder.getTestSkippedCount(), "# tests skipped"), () -> assertEquals(0, eventRecorder.getTestAbortedCount(), "# tests aborted"), () -> assertEquals(0, eventRecorder.getTestFailedCount(), "# tests failed") ); // @formatter:on // @formatter:off assertEquals(asList( "beforeAll1", "beforeAll2", "beforeAll3", "beforeEach1", "beforeEach2", "beforeEach3", "test3", "afterEach3", "afterEach2", "afterEach1", "afterAll3", "afterAll2", "afterAll1" ), callSequence, "wrong call sequence"); // @formatter:on } // ------------------------------------------------------------------- private static abstract class AbstractTestCase { static int countSuperBeforeInvoked = 0; static int countSuperAfterInvoked = 0; @BeforeEach void superBefore() { countSuperBeforeInvoked++; } @AfterEach void superAfter() { countSuperAfterInvoked++; } @Test void superTest() { /* no-op */ } } private static class LocalTestCase extends AbstractTestCase { boolean throwExceptionInAfterMethod = false; static int countBeforeInvoked = 0; static int countAfterInvoked = 0; @BeforeEach void before() { countBeforeInvoked++; // Reset state, since the test instance is retained across all test methods; // otherwise, after() always throws an exception. this.throwExceptionInAfterMethod = false; } @AfterEach void after() { countAfterInvoked++; if (this.throwExceptionInAfterMethod) { throw new RuntimeException("Exception thrown from @AfterEach method"); } } @Test void otherTest() { /* no-op */ } @Test void throwExceptionInAfterMethod() { this.throwExceptionInAfterMethod = true; } @Test void alwaysPasses() { /* no-op */ } @Test void aborted() { assumeTrue(false); } @Test void alwaysFails() { fail("#fail"); } } private static class TestCase1 { @BeforeAll static void beforeAll1() { callSequence.add("beforeAll1"); } @BeforeEach void beforeEach1() { callSequence.add("beforeEach1"); } @AfterEach void afterEach1() { callSequence.add("afterEach1"); } @AfterAll static void afterAll1() { callSequence.add("afterAll1"); } } private static class TestCase2 extends TestCase1 { @BeforeAll static void beforeAll2() { callSequence.add("beforeAll2"); } @BeforeEach void beforeEach2() { callSequence.add("beforeEach2"); } @AfterEach void afterEach2() { callSequence.add("afterEach2"); } @AfterAll static void afterAll2() { callSequence.add("afterAll2"); } } private static class TestCase3 extends TestCase2 { @BeforeAll static void beforeAll3() { callSequence.add("beforeAll3"); } @BeforeEach void beforeEach3() { callSequence.add("beforeEach3"); } @Test void test3() { callSequence.add("test3"); } @AfterEach void afterEach3() { callSequence.add("afterEach3"); } @AfterAll static void afterAll3() { callSequence.add("afterAll3"); } } }