blob: 0d80fc60c2991b0828135e1d820f91d82ff39973 [file]
/*
* Copyright 2015-2022 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 v2.0 which
* accompanies this distribution and is available at
*
* https://www.eclipse.org/legal/epl-v20.html
*/
package org.junit.jupiter.engine;
import static java.util.Collections.emptyMap;
import static java.util.Collections.singletonMap;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.TestInstance.Lifecycle.PER_CLASS;
import static org.junit.jupiter.api.TestInstance.Lifecycle.PER_METHOD;
import static org.junit.platform.engine.discovery.DiscoverySelectors.selectClass;
import static org.junit.platform.launcher.core.LauncherDiscoveryRequestBuilder.request;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
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.jupiter.api.TestInfo;
import org.junit.jupiter.api.TestInstance;
import org.junit.platform.engine.ConfigurationParameters;
import org.junit.platform.launcher.Launcher;
import org.junit.platform.testkit.engine.EngineExecutionResults;
/**
* Integration tests for {@link TestInstance @TestInstance} lifecycle
* configuration support, not to be confused with {@link TestInstanceLifecycleTests}.
*
* <p>Specifically, this class tests custom lifecycle configuration specified
* via {@code @TestInstance} as well as via {@link ConfigurationParameters}
* supplied to the {@link Launcher} or via a JVM system property.
*
* @since 5.0
* @see TestInstanceLifecycleTests
*/
class TestInstanceLifecycleConfigurationTests extends AbstractJupiterTestEngineTests {
private static final String KEY = Constants.DEFAULT_TEST_INSTANCE_LIFECYCLE_PROPERTY_NAME;
private static final List<String> methodsInvoked = new ArrayList<>();
@BeforeEach
@AfterEach
void reset() {
methodsInvoked.clear();
System.clearProperty(KEY);
}
@Test
void instancePerMethodUsingStandardDefaultConfiguration() {
performAssertions(AssumedInstancePerTestMethodTestCase.class, 2, 0, 1, "beforeAll", "test", "afterAll");
}
@Test
void instancePerClassConfiguredViaExplicitAnnotationDeclaration() {
performAssertions(ExplicitInstancePerClassTestCase.class, 2, 0, 1, "beforeAll", "test", "afterAll");
}
@Test
void instancePerClassConfiguredViaSystemProperty() {
Class<?> testClass = AssumedInstancePerClassTestCase.class;
// Should fail by default...
performAssertions(testClass, 2, 1, 0);
// Should pass with the system property set
System.setProperty(KEY, PER_CLASS.name());
performAssertions(testClass, 2, 0, 1, "beforeAll", "test", "afterAll");
}
@Test
void instancePerClassConfiguredViaConfigParam() {
Class<?> testClass = AssumedInstancePerClassTestCase.class;
// Should fail by default...
performAssertions(testClass, 2, 1, 0);
// Should pass with the config param
performAssertions(testClass, singletonMap(KEY, PER_CLASS.name()), 2, 0, 1, "beforeAll", "test", "afterAll");
}
@Test
void instancePerClassConfiguredViaConfigParamThatOverridesSystemProperty() {
Class<?> testClass = AssumedInstancePerClassTestCase.class;
// Should fail with system property
System.setProperty(KEY, PER_METHOD.name());
performAssertions(testClass, 2, 1, 0);
// Should pass with the config param
performAssertions(testClass, singletonMap(KEY, PER_CLASS.name()), 2, 0, 1, "beforeAll", "test", "afterAll");
}
@Test
void instancePerMethodConfiguredViaExplicitAnnotationDeclarationThatOverridesSystemProperty() {
System.setProperty(KEY, PER_CLASS.name());
performAssertions(ExplicitInstancePerTestMethodTestCase.class, 2, 0, 1, "beforeAll", "test", "afterAll");
}
@Test
void instancePerMethodConfiguredViaExplicitAnnotationDeclarationThatOverridesConfigParam() {
Class<?> testClass = ExplicitInstancePerTestMethodTestCase.class;
performAssertions(testClass, singletonMap(KEY, PER_CLASS.name()), 2, 0, 1, "beforeAll", "test", "afterAll");
}
private void performAssertions(Class<?> testClass, int containers, int containersFailed, int tests,
String... methods) {
performAssertions(testClass, emptyMap(), containers, containersFailed, tests, methods);
}
private void performAssertions(Class<?> testClass, Map<String, String> configParams, int numContainers,
int numFailedContainers, int numTests, String... methods) {
// @formatter:off
EngineExecutionResults executionResults = executeTests(
request()
.selectors(selectClass(testClass))
.configurationParameters(configParams)
.build()
);
// @formatter:on
executionResults.containerEvents().assertStatistics(//
stats -> stats.started(numContainers).finished(numContainers).failed(numFailedContainers));
executionResults.testEvents().assertStatistics(//
stats -> stats.started(numTests).finished(numTests));
assertEquals(Arrays.asList(methods), methodsInvoked);
}
// -------------------------------------------------------------------------
@TestInstance(PER_METHOD)
static class ExplicitInstancePerTestMethodTestCase {
@BeforeAll
static void beforeAll() {
methodsInvoked.add("beforeAll");
}
@Test
void test() {
methodsInvoked.add("test");
}
@AfterAll
static void afterAllStatic() {
methodsInvoked.add("afterAll");
}
}
/**
* "per-method" lifecycle mode is assumed since the {@code @BeforeAll} and
* {@code @AfterAll} methods are static, even though there is no explicit
* {@code @TestInstance} declaration.
*/
static class AssumedInstancePerTestMethodTestCase {
@BeforeAll
static void beforeAll() {
methodsInvoked.add("beforeAll");
}
@Test
void test() {
methodsInvoked.add("test");
}
@AfterAll
static void afterAllStatic() {
methodsInvoked.add("afterAll");
}
}
@TestInstance(PER_CLASS)
static class ExplicitInstancePerClassTestCase {
@BeforeAll
void beforeAll(TestInfo testInfo) {
methodsInvoked.add("beforeAll");
}
@Test
void test() {
methodsInvoked.add("test");
}
@AfterAll
void afterAll(TestInfo testInfo) {
methodsInvoked.add("afterAll");
}
}
/**
* "per-class" lifecycle mode is assumed since the {@code @BeforeAll} and
* {@code @AfterAll} methods are non-static, even though there is no
* explicit {@code @TestInstance} declaration.
*/
static class AssumedInstancePerClassTestCase {
@BeforeAll
void beforeAll(TestInfo testInfo) {
methodsInvoked.add("beforeAll");
}
@Test
void test() {
methodsInvoked.add("test");
}
@AfterAll
void afterAll(TestInfo testInfo) {
methodsInvoked.add("afterAll");
}
}
}