Skip to content

Commit 60be1f8

Browse files
committed
Log discovery issue when using Jupiters @disabled
1 parent a787876 commit 60be1f8

4 files changed

Lines changed: 116 additions & 23 deletions

File tree

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
/*
2+
* Copyright 2026 the original author or authors.
3+
*
4+
* All rights reserved. This program and the accompanying materials are
5+
* made available under the terms of the Eclipse Public License v2.0 which
6+
* accompanies this distribution and is available at
7+
*
8+
* https://www.eclipse.org/legal/epl-v20.html
9+
*/
10+
11+
package org.junit.platform.suite.engine;
12+
13+
import static org.junit.platform.commons.support.AnnotationSupport.findAnnotation;
14+
import static org.junit.platform.engine.DiscoveryIssue.Severity.INFO;
15+
16+
import java.lang.annotation.Annotation;
17+
import java.util.Optional;
18+
19+
import org.jspecify.annotations.Nullable;
20+
import org.junit.platform.commons.function.Try;
21+
import org.junit.platform.engine.DiscoveryIssue;
22+
import org.junit.platform.engine.support.discovery.DiscoveryIssueReporter;
23+
import org.junit.platform.suite.api.Disabled;
24+
25+
final class JupiterDisabledUtils {
26+
private static final String ORG_JUNIT_JUPITER_API_DISABLED = "org.junit.jupiter.api.Disabled";
27+
28+
static void reportUseOfJupiterDisabled(Class<?> suiteClass, DiscoveryIssueReporter issueReporter) {
29+
getJupiterDisabledAnnotation() //
30+
.flatMap(annotationClass -> findAnnotation(suiteClass, annotationClass)) //
31+
.map(annotation -> DiscoveryIssue.create(INFO,
32+
"The suite [%s] was annotated with [%s] which does not disabled the suite. Did you mean to use [%s]?" //
33+
.formatted(suiteClass, annotation.annotationType().getName(), Disabled.class.getName()))) //
34+
.ifPresent(issueReporter::reportIssue);
35+
}
36+
37+
private static @Nullable Try<Class<? extends Annotation>> jupiterDisabled;
38+
39+
@SuppressWarnings("unchecked")
40+
private static Optional<Class<? extends Annotation>> getJupiterDisabledAnnotation() {
41+
if (jupiterDisabled == null) {
42+
jupiterDisabled = Try.call(
43+
() -> (Class<? extends Annotation>) Class.forName(ORG_JUNIT_JUPITER_API_DISABLED));
44+
}
45+
return jupiterDisabled.toOptional();
46+
47+
}
48+
}

junit-platform-suite-engine/src/main/java/org/junit/platform/suite/engine/SuiteTestDescriptor.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@
1515
import static java.util.stream.Collectors.joining;
1616
import static org.junit.platform.commons.support.AnnotationSupport.findAnnotation;
1717
import static org.junit.platform.commons.util.FunctionUtils.where;
18+
import static org.junit.platform.engine.DiscoveryIssue.Severity.*;
19+
import static org.junit.platform.suite.engine.JupiterDisabledUtils.reportUseOfJupiterDisabled;
1820
import static org.junit.platform.suite.engine.SuiteLauncherDiscoveryRequestBuilder.request;
1921

2022
import java.lang.reflect.Method;
@@ -94,6 +96,7 @@ final class SuiteTestDescriptor extends AbstractTestDescriptor {
9496
this.suiteClass = suiteClass;
9597
this.lifecycleMethods = new LifecycleMethods(suiteClass, issueReporter);
9698
this.discoveryRequestBuilder.listener(DiscoveryIssueForwardingListener.create(id, discoveryListener));
99+
reportUseOfJupiterDisabled(suiteClass, issueReporter);
97100
}
98101

99102
private static Boolean getFailIfNoTests(Class<?> suiteClass) {
@@ -152,7 +155,7 @@ private static String getSuiteDisplayName(Class<?> suiteClass, DiscoveryIssueRep
152155
var nonBlank = issueReporter.createReportingCondition(StringUtils::isNotBlank, __ -> {
153156
String message = "@SuiteDisplayName on %s must be declared with a non-blank value.".formatted(
154157
suiteClass.getName());
155-
return DiscoveryIssue.builder(DiscoveryIssue.Severity.WARNING, message)
158+
return DiscoveryIssue.builder(WARNING, message)
156159
.source(ClassSource.from(suiteClass))
157160
.build();
158161
}).toPredicate();

platform-tests/src/test/java/org/junit/platform/suite/engine/SuiteEngineTests.java

Lines changed: 40 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
import static java.util.Objects.requireNonNull;
1414
import static org.assertj.core.api.Assertions.assertThat;
1515
import static org.junit.jupiter.api.TemporaryClasspathExecutor.withAdditionalClasspathRoot;
16+
import static org.junit.platform.engine.DiscoveryIssue.Severity.INFO;
1617
import static org.junit.platform.engine.discovery.DiscoverySelectors.selectClass;
1718
import static org.junit.platform.engine.discovery.DiscoverySelectors.selectUniqueId;
1819
import static org.junit.platform.launcher.TagFilter.excludeTags;
@@ -88,6 +89,7 @@
8889
import org.junit.platform.suite.engine.testsuites.ErroneousTestSuite;
8990
import org.junit.platform.suite.engine.testsuites.FailingSuite;
9091
import org.junit.platform.suite.engine.testsuites.InheritedSuite;
92+
import org.junit.platform.suite.engine.testsuites.JupiterDisabledSuite;
9193
import org.junit.platform.suite.engine.testsuites.MultiEngineSuite;
9294
import org.junit.platform.suite.engine.testsuites.MultipleSuite;
9395
import org.junit.platform.suite.engine.testsuites.NestedSuite;
@@ -591,7 +593,7 @@ void cyclicSuite() {
591593
.append(SuiteTestDescriptor.SEGMENT_TYPE, CyclicSuite.class.getName());
592594
var message = "The suite configuration of [%s] resulted in a cycle [%s] and will not be discovered a second time."
593595
.formatted(CyclicSuite.class.getName(), expectedUniqueId);
594-
var issue = DiscoveryIssue.builder(Severity.INFO, message)
596+
var issue = DiscoveryIssue.builder(INFO, message)
595597
.source(ClassSource.from(CyclicSuite.class))
596598
.build();
597599

@@ -835,36 +837,52 @@ void validSuiteDisplayNameGeneratesNoWarning() {
835837

836838
@Test
837839
void disabledSuite() {
838-
// @formatter:off
839-
EngineTestKit.Builder testKit = EngineTestKit.engine(ENGINE_ID)
840-
.selectors(selectClass(DisabledSuite.class));
840+
EngineTestKit.Builder testKit = EngineTestKit.engine(ENGINE_ID) //
841+
.selectors(selectClass(DisabledSuite.class)) //
842+
.outputDirectoryCreator(hierarchicalOutputDirectoryCreator(outputDir)); //
841843

842-
assertThat(testKit.discover().getDiscoveryIssues())
844+
assertThat(testKit.discover().getDiscoveryIssues())//
843845
.isEmpty();
844846

845-
testKit
846-
.execute()
847-
.allEvents()
848-
.assertThatEvents()
849-
.haveExactly(1, event(container(DisabledSuite.class.getName()), skippedWithReason(DisabledSuite.class + " is @Disabled")));
850-
// @formatter:on
847+
testKit.execute() //
848+
.allEvents() //
849+
.assertThatEvents() //
850+
.haveExactly(1, event(container(DisabledSuite.class.getName()),
851+
skippedWithReason(DisabledSuite.class + " is @Disabled")));
851852
}
852853

853854
@Test
854855
void disabledSuiteWithReason() {
855-
// @formatter:off
856-
EngineTestKit.Builder testKit = EngineTestKit.engine(ENGINE_ID)
857-
.selectors(selectClass(DisabledWithReasonSuite.class));
856+
EngineTestKit.Builder testKit = EngineTestKit.engine(ENGINE_ID).selectors(
857+
selectClass(DisabledWithReasonSuite.class)) //
858+
.outputDirectoryCreator(hierarchicalOutputDirectoryCreator(outputDir));
858859

859-
assertThat(testKit.discover().getDiscoveryIssues())
860-
.isEmpty();
860+
assertThat(testKit.discover().getDiscoveryIssues()).isEmpty();
861861

862-
testKit
863-
.execute()
864-
.allEvents()
865-
.assertThatEvents()
866-
.haveExactly(1, event(container(DisabledWithReasonSuite.class.getName()), skippedWithReason("for testing purposes")));
867-
// @formatter:on
862+
testKit.execute() //
863+
.allEvents() //
864+
.assertThatEvents() //
865+
.haveExactly(1, event(container(DisabledWithReasonSuite.class.getName()),
866+
skippedWithReason("for testing purposes")));
867+
}
868+
869+
@Test
870+
void usingJupiterDisabledLogsAnIssue() {
871+
var testKit = EngineTestKit.engine(ENGINE_ID).selectors(
872+
selectClass(JupiterDisabledSuite.class)).outputDirectoryCreator(
873+
hierarchicalOutputDirectoryCreator(outputDir));
874+
875+
var expectedIssue = DiscoveryIssue.create(INFO,
876+
("The suite [%s] was annotated with [org.junit.jupiter.api.Disabled] which does not disabled the suite. "
877+
+ "Did you mean to use [org.junit.platform.suite.api.Disabled]?") //
878+
.formatted(JupiterDisabledSuite.class));
879+
assertThat(testKit.discover().getDiscoveryIssues()).contains(expectedIssue);
880+
881+
testKit.execute() //
882+
.testEvents() //
883+
.assertThatEvents() //
884+
.haveExactly(1, event(test(JupiterDisabledSuite.class.getName()), finishedSuccessfully())) //
885+
.haveExactly(1, event(test(SingleTestTestCase.class.getName()), finishedSuccessfully()));
868886
}
869887

870888
// -----------------------------------------------------------------------------------------------------------------
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
/*
2+
* Copyright 2026 the original author or authors.
3+
*
4+
* All rights reserved. This program and the accompanying materials are
5+
* made available under the terms of the Eclipse Public License v2.0 which
6+
* accompanies this distribution and is available at
7+
*
8+
* https://www.eclipse.org/legal/epl-v20.html
9+
*/
10+
11+
package org.junit.platform.suite.engine.testsuites;
12+
13+
import org.junit.platform.suite.api.SelectClasses;
14+
import org.junit.platform.suite.api.Suite;
15+
import org.junit.platform.suite.engine.testcases.SingleTestTestCase;
16+
17+
/**
18+
* @since 6.2
19+
*/
20+
@Suite
21+
@SelectClasses(SingleTestTestCase.class)
22+
@org.junit.jupiter.api.Disabled
23+
public class JupiterDisabledSuite {
24+
}

0 commit comments

Comments
 (0)