blob: 9b204236f5be3c911146eeed76ca95f71b746bc9 [file] [log] [blame]
/*
* 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.vintage.engine;
import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.platform.commons.util.CollectionUtils.getOnlyElement;
import static org.junit.platform.engine.FilterResult.excluded;
import static org.junit.platform.engine.FilterResult.includedIf;
import static org.junit.platform.engine.discovery.DiscoverySelectors.selectClass;
import static org.junit.platform.launcher.EngineFilter.includeEngines;
import static org.junit.platform.launcher.TagFilter.excludeTags;
import static org.junit.platform.launcher.TagFilter.includeTags;
import static org.junit.platform.launcher.core.LauncherDiscoveryRequestBuilder.request;
import static org.junit.vintage.engine.descriptor.VintageTestDescriptor.ENGINE_ID;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.LogRecord;
import org.junit.internal.runners.SuiteMethod;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.fixtures.TrackLogRecords;
import org.junit.platform.commons.logging.LogRecordListener;
import org.junit.platform.engine.TestExecutionResult;
import org.junit.platform.launcher.LauncherDiscoveryRequest;
import org.junit.platform.launcher.PostDiscoveryFilter;
import org.junit.platform.launcher.TestExecutionListener;
import org.junit.platform.launcher.TestIdentifier;
import org.junit.platform.launcher.TestPlan;
import org.junit.platform.launcher.core.LauncherDiscoveryRequestBuilder;
import org.junit.platform.launcher.core.LauncherFactory;
import org.junit.runners.Suite;
import org.junit.vintage.engine.descriptor.RunnerTestDescriptor;
import org.junit.vintage.engine.samples.junit3.JUnit3SuiteWithSingleTestCaseWithSingleTestWhichFails;
import org.junit.vintage.engine.samples.junit3.PlainJUnit3TestCaseWithSingleTestWhichFails;
import org.junit.vintage.engine.samples.junit4.Categories;
import org.junit.vintage.engine.samples.junit4.EnclosedJUnit4TestCase;
import org.junit.vintage.engine.samples.junit4.JUnit4SuiteOfSuiteWithFilterableChildRunner;
import org.junit.vintage.engine.samples.junit4.JUnit4SuiteWithTwoTestCases;
import org.junit.vintage.engine.samples.junit4.JUnit4TestCaseWithNotFilterableRunner;
import org.junit.vintage.engine.samples.junit4.NotFilterableRunner;
import org.junit.vintage.engine.samples.junit4.ParameterizedTestCase;
import org.junit.vintage.engine.samples.junit4.PlainJUnit4TestCaseWithFiveTestMethods;
import org.junit.vintage.engine.samples.junit4.PlainJUnit4TestCaseWithTwoTestMethods;
/**
* @since 5.1
*/
class VintageLauncherIntegrationTests {
@Test
void executesOnlyTaggedMethodOfRegularTestClass() {
Class<?> testClass = PlainJUnit4TestCaseWithFiveTestMethods.class;
var request = request() //
.selectors(selectClass(testClass)) //
.filters(includeTags(Categories.Failing.class.getName()));
var testPlan = discover(request);
assertThat(testPlan.getDescendants(getOnlyElement(testPlan.getRoots()))).hasSize(2);
var results = execute(request);
assertThat(results.keySet().stream().map(TestIdentifier::getDisplayName)) //
.containsExactlyInAnyOrder("JUnit Vintage", testClass.getSimpleName(), "failingTest");
}
@Test
void executesIncludedTaggedMethodOfNestedTestClass() {
Class<?> testClass = EnclosedJUnit4TestCase.class;
Class<?> nestedTestClass = EnclosedJUnit4TestCase.NestedClass.class;
var request = request() //
.selectors(selectClass(testClass)) //
.filters(includeTags(Categories.Failing.class.getName()));
var testPlan = discover(request);
assertThat(testPlan.getDescendants(getOnlyElement(testPlan.getRoots()))).hasSize(3);
var results = execute(request);
assertThat(results.keySet().stream().map(TestIdentifier::getDisplayName)) //
.containsExactlyInAnyOrder("JUnit Vintage", testClass.getSimpleName(), nestedTestClass.getName(),
"failingTest");
}
@Test
void executesOnlyNotExcludedTaggedMethodOfNestedTestClass() {
Class<?> testClass = EnclosedJUnit4TestCase.class;
Class<?> nestedTestClass = EnclosedJUnit4TestCase.NestedClass.class;
var request = request() //
.selectors(selectClass(testClass)) //
.filters(excludeTags(Categories.Failing.class.getName()));
var testPlan = discover(request);
assertThat(testPlan.getDescendants(getOnlyElement(testPlan.getRoots()))).hasSize(3);
var results = execute(request);
assertThat(results.keySet().stream().map(TestIdentifier::getDisplayName)) //
.containsExactlyInAnyOrder("JUnit Vintage", testClass.getSimpleName(), nestedTestClass.getName(),
"successfulTest");
}
@Test
void removesWholeSubtree() {
Class<?> testClass = EnclosedJUnit4TestCase.class;
var request = request() //
.selectors(selectClass(testClass)) //
.filters(excludeTags(Categories.Plain.class.getName()));
var testPlan = discover(request);
assertThat(testPlan.getDescendants(getOnlyElement(testPlan.getRoots()))).isEmpty();
var results = execute(request);
assertThat(results.keySet().stream().map(TestIdentifier::getDisplayName)) //
.containsExactlyInAnyOrder("JUnit Vintage");
}
@Test
void removesCompleteClassIfNoMethodHasMatchingTags() {
Class<?> testClass = PlainJUnit4TestCaseWithFiveTestMethods.class;
var request = request() //
.selectors(selectClass(testClass)) //
.filters(includeTags("wrong-tag"));
var testPlan = discover(request);
assertThat(testPlan.getDescendants(getOnlyElement(testPlan.getRoots()))).isEmpty();
var results = execute(request);
assertThat(results.keySet().stream().map(TestIdentifier::getDisplayName)) //
.containsExactly("JUnit Vintage");
}
@Test
void removesCompleteClassIfItHasExcludedTag() {
Class<?> testClass = PlainJUnit4TestCaseWithFiveTestMethods.class;
var request = request() //
.selectors(selectClass(testClass)) //
.filters(excludeTags(Categories.Plain.class.getName()));
var testPlan = discover(request);
assertThat(testPlan.getDescendants(getOnlyElement(testPlan.getRoots()))).isEmpty();
var results = execute(request);
assertThat(results.keySet().stream().map(TestIdentifier::getDisplayName)) //
.containsExactly("JUnit Vintage");
}
@TrackLogRecords
@Test
void executesAllTestsForNotFilterableRunner(LogRecordListener logRecordListener) {
Class<?> testClass = JUnit4TestCaseWithNotFilterableRunner.class;
var request = request() //
.selectors(selectClass(testClass)) //
.filters((PostDiscoveryFilter) descriptor -> includedIf(descriptor.getDisplayName().contains("#1")));
var testPlan = discover(request);
logRecordListener.clear();
assertThat(testPlan.getDescendants(getOnlyElement(testPlan.getRoots()))).hasSize(3);
var results = execute(request);
assertThat(results.keySet().stream().map(TestIdentifier::getDisplayName)) //
.containsExactlyInAnyOrder("JUnit Vintage", testClass.getSimpleName(), "Test #0", "Test #1");
assertThat(logRecordListener.stream(RunnerTestDescriptor.class, Level.WARNING).map(LogRecord::getMessage)) //
.containsExactly(
"Runner " + NotFilterableRunner.class.getName() + " (used on class " + testClass.getName() + ")" //
+ " does not support filtering and will therefore be run completely.");
}
@TrackLogRecords
@Test
void executesAllTestsForNotFilterableChildRunnerOfSuite(LogRecordListener logRecordListener) {
Class<?> suiteClass = JUnit4SuiteOfSuiteWithFilterableChildRunner.class;
Class<?> testClass = JUnit4TestCaseWithNotFilterableRunner.class;
var request = request() //
.selectors(selectClass(suiteClass)) //
.filters((PostDiscoveryFilter) descriptor -> includedIf(descriptor.getDisplayName().contains("#1")));
var testPlan = discover(request);
logRecordListener.clear();
assertThat(testPlan.getDescendants(getOnlyElement(testPlan.getRoots()))).hasSize(4);
var results = execute(request);
assertThat(results.keySet().stream().map(TestIdentifier::getDisplayName)) //
.containsExactlyInAnyOrder("JUnit Vintage", suiteClass.getSimpleName(), testClass.getName(), "Test #0",
"Test #1");
assertThat(logRecordListener.stream(RunnerTestDescriptor.class, Level.WARNING).map(LogRecord::getMessage)) //
.containsExactly("Runner " + Suite.class.getName() + " (used on class " + suiteClass.getName() + ")" //
+ " was not able to satisfy all filter requests.");
}
@TrackLogRecords
@Test
void executesAllTestsWhenFilterDidNotExcludeTestForJUnit3Suite(LogRecordListener logRecordListener) {
Class<?> suiteClass = JUnit3SuiteWithSingleTestCaseWithSingleTestWhichFails.class;
Class<?> testClass = PlainJUnit3TestCaseWithSingleTestWhichFails.class;
var request = request() //
.selectors(selectClass(suiteClass)) //
.filters((PostDiscoveryFilter) descriptor -> excluded("not today"));
var testPlan = discover(request);
logRecordListener.clear();
assertThat(testPlan.getDescendants(getOnlyElement(testPlan.getRoots()))).hasSize(3);
var results = execute(request);
assertThat(results.keySet().stream().map(TestIdentifier::getDisplayName)) //
.containsExactlyInAnyOrder("JUnit Vintage", suiteClass.getSimpleName(), testClass.getName(), "test");
assertThat(logRecordListener.stream(RunnerTestDescriptor.class, Level.WARNING).map(LogRecord::getMessage)) //
.containsExactly(
"Runner " + SuiteMethod.class.getName() + " (used on class " + suiteClass.getName() + ")" //
+ " was not able to satisfy all filter requests.");
}
@Test
void executesOnlyTaggedMethodsForSuite() {
Class<?> suiteClass = JUnit4SuiteWithTwoTestCases.class;
Class<?> testClass = PlainJUnit4TestCaseWithTwoTestMethods.class;
var request = request() //
.selectors(selectClass(suiteClass)) //
.filters(includeTags(Categories.Successful.class.getName()));
var testPlan = discover(request);
assertThat(testPlan.getDescendants(getOnlyElement(testPlan.getRoots()))).hasSize(3);
var results = execute(request);
assertThat(results.keySet().stream().map(TestIdentifier::getDisplayName)) //
.containsExactlyInAnyOrder("JUnit Vintage", suiteClass.getSimpleName(), testClass.getName(),
"successfulTest");
}
@Test
void removesCompleteClassWithNotFilterableRunnerIfItHasExcludedTag() {
Class<?> testClass = JUnit4TestCaseWithNotFilterableRunner.class;
var request = request() //
.selectors(selectClass(testClass)) //
.filters(excludeTags(Categories.Successful.class.getName()));
var testPlan = discover(request);
assertThat(testPlan.getDescendants(getOnlyElement(testPlan.getRoots()))).isEmpty();
var results = execute(request);
assertThat(results.keySet().stream().map(TestIdentifier::getDisplayName)) //
.containsExactly("JUnit Vintage");
}
@Test
void filtersOutAllDescendantsOfParameterizedTestCase() {
Class<?> testClass = ParameterizedTestCase.class;
var request = request() //
.selectors(selectClass(testClass)) //
.filters((PostDiscoveryFilter) descriptor -> excluded("excluded"));
var testPlan = discover(request);
assertThat(testPlan.getDescendants(getOnlyElement(testPlan.getRoots()))).isEmpty();
var results = execute(request);
assertThat(results.keySet().stream().map(TestIdentifier::getDisplayName)) //
.containsExactly("JUnit Vintage");
}
private TestPlan discover(LauncherDiscoveryRequestBuilder requestBuilder) {
var launcher = LauncherFactory.create();
return launcher.discover(toRequest(requestBuilder));
}
private Map<TestIdentifier, TestExecutionResult> execute(LauncherDiscoveryRequestBuilder requestBuilder) {
Map<TestIdentifier, TestExecutionResult> results = new LinkedHashMap<>();
var request = toRequest(requestBuilder);
var launcher = LauncherFactory.create();
launcher.execute(request, new TestExecutionListener() {
@Override
public void executionFinished(TestIdentifier testIdentifier, TestExecutionResult testExecutionResult) {
results.put(testIdentifier, testExecutionResult);
}
});
return results;
}
private LauncherDiscoveryRequest toRequest(LauncherDiscoveryRequestBuilder requestBuilder) {
return requestBuilder.filters(includeEngines(ENGINE_ID)).build();
}
}