Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix reporting of @Ignored JUnit 3 test classes #3427

Merged
merged 7 commits into from
Sep 5, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ JUnit repository on GitHub.

==== Bug Fixes

*
* Fix reporting of JUnit 3 test classes with `@Ignored` annotation

==== Deprecations and Breaking Changes

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,12 +43,14 @@ public class RunnerTestDescriptor extends VintageTestDescriptor {

private final Set<Description> rejectedExclusions = new HashSet<>();
private Runner runner;
private final boolean ignored;
private boolean wasFiltered;
private List<Filter> filters = new ArrayList<>();

public RunnerTestDescriptor(UniqueId uniqueId, Class<?> testClass, Runner runner) {
public RunnerTestDescriptor(UniqueId uniqueId, Class<?> testClass, Runner runner, boolean ignored) {
super(uniqueId, runner.getDescription(), testClass.getSimpleName(), ClassSource.from(testClass));
this.runner = runner;
this.ignored = ignored;
}

@Override
Expand Down Expand Up @@ -155,6 +157,10 @@ private Runner getRunnerToReport() {
return (runner instanceof RunnerDecorator) ? ((RunnerDecorator) runner).getDecoratedRunner() : runner;
}

public boolean isIgnored() {
return ignored;
}

private static class ExcludeDescriptionFilter extends Filter {

private final Description description;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,15 +26,14 @@
import org.junit.platform.engine.discovery.UniqueIdSelector;
import org.junit.platform.engine.support.discovery.SelectorResolver;
import org.junit.runner.Runner;
import org.junit.runners.model.RunnerBuilder;
import org.junit.vintage.engine.descriptor.RunnerTestDescriptor;

/**
* @since 4.12
*/
class ClassSelectorResolver implements SelectorResolver {

private static final RunnerBuilder RUNNER_BUILDER = new DefensiveAllDefaultPossibilitiesBuilder();
private static final DefensiveAllDefaultPossibilitiesBuilder RUNNER_BUILDER = new DefensiveAllDefaultPossibilitiesBuilder();

private final ClassFilter classFilter;

Expand Down Expand Up @@ -76,7 +75,7 @@ private Resolution resolveTestClass(Class<?> testClass, Context context) {

private RunnerTestDescriptor createRunnerTestDescriptor(TestDescriptor parent, Class<?> testClass, Runner runner) {
UniqueId uniqueId = parent.getUniqueId().append(SEGMENT_TYPE_RUNNER, testClass.getName());
return new RunnerTestDescriptor(uniqueId, testClass, runner);
return new RunnerTestDescriptor(uniqueId, testClass, runner, RUNNER_BUILDER.isIgnored(runner));
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,10 @@ public Runner runnerForClass(Class<?> testClass) throws Throwable {
return runner;
}

boolean isIgnored(Runner runner) {
return runner instanceof IgnoredClassRunner || runner instanceof IgnoringRunnerDecorator;
}

/**
* Instead of checking for the {@link Ignore} annotation and returning an
* {@link IgnoredClassRunner} from {@link IgnoredBuilder}, we've let the
Expand All @@ -72,7 +76,7 @@ public Runner runnerForClass(Class<?> testClass) throws Throwable {
* override its runtime behavior (i.e. skip execution) but return its
* regular {@link org.junit.runner.Description}.
*/
private Runner decorateIgnoredTestClass(Runner runner) {
private IgnoringRunnerDecorator decorateIgnoredTestClass(Runner runner) {
if (runner instanceof Filterable) {
return new FilterableIgnoringRunnerDecorator(runner);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
import org.junit.platform.engine.TestDescriptor;
import org.junit.platform.engine.TestExecutionResult;
import org.junit.platform.engine.UniqueId;
import org.junit.platform.engine.support.descriptor.ClassSource;
import org.junit.runner.Description;
import org.junit.runner.Result;
import org.junit.runner.notification.Failure;
Expand Down Expand Up @@ -49,7 +50,7 @@ class RunListenerAdapter extends RunListener {

@Override
public void testRunStarted(Description description) {
if (description.isSuite() && description.getAnnotation(Ignore.class) == null) {
if (description.isSuite() && !testRun.getRunnerTestDescriptor().isIgnored()) {
fireExecutionStarted(testRun.getRunnerTestDescriptor(), EventType.REPORTED);
}
}
Expand All @@ -65,7 +66,9 @@ public void testSuiteStarted(Description description) {

@Override
public void testIgnored(Description description) {
testIgnored(lookupOrRegisterNextTestDescriptor(description), determineReasonForIgnoredTest(description));
TestDescriptor testDescriptor = lookupOrRegisterNextTestDescriptor(description);
String reason = determineReasonForIgnoredTest(testDescriptor, description).orElse("<unknown>");
testIgnored(testDescriptor, reason);
}

@Override
Expand Down Expand Up @@ -176,9 +179,21 @@ private void testIgnored(TestDescriptor testDescriptor, String reason) {
fireExecutionSkipped(testDescriptor, reason);
}

private String determineReasonForIgnoredTest(Description description) {
Ignore ignoreAnnotation = description.getAnnotation(Ignore.class);
return Optional.ofNullable(ignoreAnnotation).map(Ignore::value).orElse("<unknown>");
private Optional<String> determineReasonForIgnoredTest(TestDescriptor testDescriptor, Description description) {
Optional<String> reason = getReason(description.getAnnotation(Ignore.class));
if (reason.isPresent()) {
return reason;
}
// Workaround for some runners (e.g. JUnit38ClassRunner) don't include the @Ignore annotation
// in the description, so we read it from the test class directly
return testDescriptor.getSource() //
.filter(ClassSource.class::isInstance) //
.map(source -> ((ClassSource) source).getJavaClass()) //
.flatMap(testClass -> getReason(testClass.getAnnotation(Ignore.class)));
}

private static Optional<String> getReason(Ignore annotation) {
return Optional.ofNullable(annotation).map(Ignore::value);
}

private void dynamicTestRegistered(TestDescriptor testDescriptor) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@

package org.junit.vintage.engine;

import static java.util.function.Predicate.isEqual;
import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.jupiter.api.Assumptions.assumeTrue;
import static org.junit.platform.engine.discovery.DiscoverySelectors.selectClass;
Expand Down Expand Up @@ -56,8 +57,10 @@
import org.junit.runner.notification.RunNotifier;
import org.junit.runners.Suite;
import org.junit.runners.Suite.SuiteClasses;
import org.junit.vintage.engine.samples.junit3.IgnoredJUnit3TestCase;
import org.junit.vintage.engine.samples.junit3.JUnit3ParallelSuiteWithSubsuites;
import org.junit.vintage.engine.samples.junit3.JUnit3SuiteWithSubsuites;
import org.junit.vintage.engine.samples.junit3.JUnit4SuiteWithIgnoredJUnit3TestCase;
import org.junit.vintage.engine.samples.junit3.PlainJUnit3TestCaseWithSingleTestWhichFails;
import org.junit.vintage.engine.samples.junit4.CompletelyDynamicTestCase;
import org.junit.vintage.engine.samples.junit4.EmptyIgnoredTestCase;
Expand Down Expand Up @@ -896,6 +899,27 @@ void executesRegularSpockFeatureMethod() {
event(engine(), finishedSuccessfully()));
}

@Test
void executesIgnoredJUnit3TestCase() {
var suiteClass = IgnoredJUnit3TestCase.class;
execute(suiteClass).allEvents().assertEventsMatchExactly( //
event(engine(), started()), //
event(container(suiteClass), skippedWithReason(isEqual("testing"))), //
event(engine(), finishedSuccessfully()));
}

@Test
void executesJUnit4SuiteWithIgnoredJUnit3TestCase() {
var suiteClass = JUnit4SuiteWithIgnoredJUnit3TestCase.class;
var testClass = IgnoredJUnit3TestCase.class;
execute(suiteClass).allEvents().assertEventsMatchExactly( //
event(engine(), started()), //
event(container(suiteClass), started()), //
event(container(testClass), skippedWithReason(isEqual("testing"))), //
event(container(suiteClass), finishedSuccessfully()), //
event(engine(), finishedSuccessfully()));
}

private static EngineExecutionResults execute(Class<?> testClass) {
return execute(request(testClass));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,8 @@ class TestRunTests {
void returnsEmptyOptionalForUnknownDescriptions() throws Exception {
Class<?> testClass = PlainJUnit4TestCaseWithSingleTestWhichFails.class;
var runnerId = engineId().append(SEGMENT_TYPE_RUNNER, testClass.getName());
var runnerTestDescriptor = new RunnerTestDescriptor(runnerId, testClass, new BlockJUnit4ClassRunner(testClass));
var runnerTestDescriptor = new RunnerTestDescriptor(runnerId, testClass, new BlockJUnit4ClassRunner(testClass),
false);
var unknownDescription = createTestDescription(testClass, "dynamicTest");

var testRun = new TestRun(runnerTestDescriptor);
Expand All @@ -45,7 +46,8 @@ void returnsEmptyOptionalForUnknownDescriptions() throws Exception {
void registersDynamicTestDescriptors() throws Exception {
Class<?> testClass = PlainJUnit4TestCaseWithSingleTestWhichFails.class;
var runnerId = engineId().append(SEGMENT_TYPE_RUNNER, testClass.getName());
var runnerTestDescriptor = new RunnerTestDescriptor(runnerId, testClass, new BlockJUnit4ClassRunner(testClass));
var runnerTestDescriptor = new RunnerTestDescriptor(runnerId, testClass, new BlockJUnit4ClassRunner(testClass),
false);
var dynamicTestId = runnerId.append(SEGMENT_TYPE_DYNAMIC, "dynamicTest");
var dynamicDescription = createTestDescription(testClass, "dynamicTest");
var dynamicTestDescriptor = new VintageTestDescriptor(dynamicTestId, dynamicDescription, null);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
/*
* Copyright 2015-2023 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.samples.junit3;

import junit.framework.TestCase;

import org.junit.Assert;
import org.junit.Ignore;

/**
* @since 4.12
*/
@Ignore("testing")
public class IgnoredJUnit3TestCase extends TestCase {

public void test() {
Assert.fail("this test should be ignored");
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
/*
* Copyright 2015-2023 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.samples.junit3;

import org.junit.runner.RunWith;
import org.junit.runners.Suite;
import org.junit.runners.Suite.SuiteClasses;

@RunWith(Suite.class)
@SuiteClasses({ IgnoredJUnit3TestCase.class })
public class JUnit4SuiteWithIgnoredJUnit3TestCase {
}