From 66bb647407c8f06e0c03f3f746f8fdad7ff396da Mon Sep 17 00:00:00 2001 From: KOSEUNGBIN Date: Fri, 8 Aug 2025 22:52:54 +0900 Subject: [PATCH 1/5] Add inspection for blank @SuiteDisplayName values Report WARNING when @SuiteDisplayName contains blank or whitespace-only values. --- .../suite/engine/SuiteTestDescriptor.java | 11 ++++++ .../suite/engine/SuiteEngineTests.java | 34 +++++++++++++++++++ .../BlankSuiteDisplayNameSuite.java | 27 +++++++++++++++ .../WhitespaceSuiteDisplayNameSuite.java | 27 +++++++++++++++ 4 files changed, 99 insertions(+) create mode 100644 platform-tests/src/test/java/org/junit/platform/suite/engine/testsuites/BlankSuiteDisplayNameSuite.java create mode 100644 platform-tests/src/test/java/org/junit/platform/suite/engine/testsuites/WhitespaceSuiteDisplayNameSuite.java diff --git a/junit-platform-suite-engine/src/main/java/org/junit/platform/suite/engine/SuiteTestDescriptor.java b/junit-platform-suite-engine/src/main/java/org/junit/platform/suite/engine/SuiteTestDescriptor.java index 0edf9c1eefbe..0a9c5d989b08 100644 --- a/junit-platform-suite-engine/src/main/java/org/junit/platform/suite/engine/SuiteTestDescriptor.java +++ b/junit-platform-suite-engine/src/main/java/org/junit/platform/suite/engine/SuiteTestDescriptor.java @@ -87,6 +87,7 @@ final class SuiteTestDescriptor extends AbstractTestDescriptor { this.suiteClass = suiteClass; this.lifecycleMethods = new LifecycleMethods(suiteClass, issueReporter); this.discoveryRequestBuilder.listener(DiscoveryIssueForwardingListener.create(id, discoveryListener)); + inspectSuiteDisplayName(suiteClass, issueReporter); } private static Boolean getFailIfNoTests(Class suiteClass) { @@ -149,6 +150,16 @@ private static String getSuiteDisplayName(Class testClass) { // @formatter:on } + private static void inspectSuiteDisplayName(Class suiteClass, DiscoveryIssueReporter issueReporter) { + findAnnotation(suiteClass, SuiteDisplayName.class).map(SuiteDisplayName::value).filter( + StringUtils::isBlank).ifPresent(__ -> { + String message = "@SuiteDisplayName on %s must be declared with a non-blank value.".formatted( + suiteClass.getName()); + issueReporter.reportIssue(DiscoveryIssue.builder(DiscoveryIssue.Severity.WARNING, message).source( + ClassSource.from(suiteClass)).build()); + }); + } + void execute(EngineExecutionListener executionListener, NamespacedHierarchicalStore requestLevelStore, CancellationToken cancellationToken) { diff --git a/platform-tests/src/test/java/org/junit/platform/suite/engine/SuiteEngineTests.java b/platform-tests/src/test/java/org/junit/platform/suite/engine/SuiteEngineTests.java index 12cb46e6d928..722ec9ceefd1 100644 --- a/platform-tests/src/test/java/org/junit/platform/suite/engine/SuiteEngineTests.java +++ b/platform-tests/src/test/java/org/junit/platform/suite/engine/SuiteEngineTests.java @@ -68,6 +68,7 @@ import org.junit.platform.suite.engine.testcases.SingleTestTestCase; import org.junit.platform.suite.engine.testcases.TaggedTestTestCase; import org.junit.platform.suite.engine.testsuites.AbstractSuite; +import org.junit.platform.suite.engine.testsuites.BlankSuiteDisplayNameSuite; import org.junit.platform.suite.engine.testsuites.ConfigurationSuite; import org.junit.platform.suite.engine.testsuites.CyclicSuite; import org.junit.platform.suite.engine.testsuites.DynamicSuite; @@ -88,6 +89,7 @@ import org.junit.platform.suite.engine.testsuites.SuiteSuite; import org.junit.platform.suite.engine.testsuites.SuiteWithErroneousTestSuite; import org.junit.platform.suite.engine.testsuites.ThreePartCyclicSuite; +import org.junit.platform.suite.engine.testsuites.WhitespaceSuiteDisplayNameSuite; import org.junit.platform.testkit.engine.EngineTestKit; /** @@ -705,6 +707,38 @@ void reportsChildrenOfEnginesInSuiteAsSkippedWhenCancelledDuringExecution() { } } + @Test + void blankSuiteDisplayNameGeneratesWarning() { + var expectedMessage = "@SuiteDisplayName on %s must be declared with a non-blank value.".formatted( + BlankSuiteDisplayNameSuite.class.getName()); + var expectedIssue = DiscoveryIssue.builder(Severity.WARNING, expectedMessage).source( + ClassSource.from(BlankSuiteDisplayNameSuite.class)).build(); + + var testKit = EngineTestKit.engine(ENGINE_ID).selectors(selectClass(BlankSuiteDisplayNameSuite.class)); + + assertThat(testKit.discover().getDiscoveryIssues()).contains(expectedIssue); + } + + @Test + void whitespaceSuiteDisplayNameGeneratesWarning() { + var expectedMessage = "@SuiteDisplayName on %s must be declared with a non-blank value.".formatted( + WhitespaceSuiteDisplayNameSuite.class.getName()); + var expectedIssue = DiscoveryIssue.builder(Severity.WARNING, expectedMessage).source( + ClassSource.from(WhitespaceSuiteDisplayNameSuite.class)).build(); + + var testKit = EngineTestKit.engine(ENGINE_ID).selectors(selectClass(WhitespaceSuiteDisplayNameSuite.class)); + + assertThat(testKit.discover().getDiscoveryIssues()).contains(expectedIssue); + } + + @Test + void validSuiteDisplayNameGeneratesNoWarning() { + var testKit = EngineTestKit.engine(ENGINE_ID).selectors(selectClass(SuiteDisplayNameSuite.class)); + + assertThat(testKit.discover().getDiscoveryIssues()).noneMatch( + issue -> issue.message().contains("@SuiteDisplayName")); + } + // ----------------------------------------------------------------------------------------------------------------- static class CancellingSuite extends SelectClassesSuite { diff --git a/platform-tests/src/test/java/org/junit/platform/suite/engine/testsuites/BlankSuiteDisplayNameSuite.java b/platform-tests/src/test/java/org/junit/platform/suite/engine/testsuites/BlankSuiteDisplayNameSuite.java new file mode 100644 index 000000000000..ebeb60db6c6c --- /dev/null +++ b/platform-tests/src/test/java/org/junit/platform/suite/engine/testsuites/BlankSuiteDisplayNameSuite.java @@ -0,0 +1,27 @@ +/* + * Copyright 2015-2025 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.platform.suite.engine.testsuites; + +import org.junit.platform.suite.api.SelectClasses; +import org.junit.platform.suite.api.Suite; +import org.junit.platform.suite.api.SuiteDisplayName; +import org.junit.platform.suite.engine.testcases.SingleTestTestCase; + +/** + * Test suite with blank @SuiteDisplayName to verify validation. + * + * @since 6.0.0-RC1 + */ +@Suite +@SelectClasses(SingleTestTestCase.class) +@SuiteDisplayName("") +public class BlankSuiteDisplayNameSuite { +} diff --git a/platform-tests/src/test/java/org/junit/platform/suite/engine/testsuites/WhitespaceSuiteDisplayNameSuite.java b/platform-tests/src/test/java/org/junit/platform/suite/engine/testsuites/WhitespaceSuiteDisplayNameSuite.java new file mode 100644 index 000000000000..e2afd52b4989 --- /dev/null +++ b/platform-tests/src/test/java/org/junit/platform/suite/engine/testsuites/WhitespaceSuiteDisplayNameSuite.java @@ -0,0 +1,27 @@ +/* + * Copyright 2015-2025 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.platform.suite.engine.testsuites; + +import org.junit.platform.suite.api.SelectClasses; +import org.junit.platform.suite.api.Suite; +import org.junit.platform.suite.api.SuiteDisplayName; +import org.junit.platform.suite.engine.testcases.SingleTestTestCase; + +/** + * Test suite with whitespace-only @SuiteDisplayName to verify validation. + * + * @since 6.0.0-RC1 + */ +@Suite +@SelectClasses(SingleTestTestCase.class) +@SuiteDisplayName(" ") +public class WhitespaceSuiteDisplayNameSuite { +} From 9f9ef0e5399a7a76459b550c14c413d4771426db Mon Sep 17 00:00:00 2001 From: KOSEUNGBIN Date: Sat, 9 Aug 2025 00:10:07 +0900 Subject: [PATCH 2/5] Update @since version for blank and whitespace-only @SuiteDisplayName test suites --- .../suite/engine/testsuites/BlankSuiteDisplayNameSuite.java | 2 +- .../engine/testsuites/WhitespaceSuiteDisplayNameSuite.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/platform-tests/src/test/java/org/junit/platform/suite/engine/testsuites/BlankSuiteDisplayNameSuite.java b/platform-tests/src/test/java/org/junit/platform/suite/engine/testsuites/BlankSuiteDisplayNameSuite.java index ebeb60db6c6c..65a6ae3c67de 100644 --- a/platform-tests/src/test/java/org/junit/platform/suite/engine/testsuites/BlankSuiteDisplayNameSuite.java +++ b/platform-tests/src/test/java/org/junit/platform/suite/engine/testsuites/BlankSuiteDisplayNameSuite.java @@ -18,7 +18,7 @@ /** * Test suite with blank @SuiteDisplayName to verify validation. * - * @since 6.0.0-RC1 + * @since 6.0 */ @Suite @SelectClasses(SingleTestTestCase.class) diff --git a/platform-tests/src/test/java/org/junit/platform/suite/engine/testsuites/WhitespaceSuiteDisplayNameSuite.java b/platform-tests/src/test/java/org/junit/platform/suite/engine/testsuites/WhitespaceSuiteDisplayNameSuite.java index e2afd52b4989..4bfc36a1eac1 100644 --- a/platform-tests/src/test/java/org/junit/platform/suite/engine/testsuites/WhitespaceSuiteDisplayNameSuite.java +++ b/platform-tests/src/test/java/org/junit/platform/suite/engine/testsuites/WhitespaceSuiteDisplayNameSuite.java @@ -18,7 +18,7 @@ /** * Test suite with whitespace-only @SuiteDisplayName to verify validation. * - * @since 6.0.0-RC1 + * @since 6.0 */ @Suite @SelectClasses(SingleTestTestCase.class) From d05b18d97f8a3de56d8fe04439e2315fb0486303 Mon Sep 17 00:00:00 2001 From: KOSEUNGBIN Date: Mon, 11 Aug 2025 23:11:49 +0900 Subject: [PATCH 3/5] Refactor suite display name retrieval to include issue reporting for blank values --- .../suite/engine/SuiteTestDescriptor.java | 29 +++++++++---------- 1 file changed, 13 insertions(+), 16 deletions(-) diff --git a/junit-platform-suite-engine/src/main/java/org/junit/platform/suite/engine/SuiteTestDescriptor.java b/junit-platform-suite-engine/src/main/java/org/junit/platform/suite/engine/SuiteTestDescriptor.java index 0a9c5d989b08..a5a6d8399d5c 100644 --- a/junit-platform-suite-engine/src/main/java/org/junit/platform/suite/engine/SuiteTestDescriptor.java +++ b/junit-platform-suite-engine/src/main/java/org/junit/platform/suite/engine/SuiteTestDescriptor.java @@ -80,14 +80,13 @@ final class SuiteTestDescriptor extends AbstractTestDescriptor { SuiteTestDescriptor(UniqueId id, Class suiteClass, ConfigurationParameters configurationParameters, OutputDirectoryProvider outputDirectoryProvider, EngineDiscoveryListener discoveryListener, DiscoveryIssueReporter issueReporter) { - super(id, getSuiteDisplayName(suiteClass), ClassSource.from(suiteClass)); + super(id, getSuiteDisplayName(suiteClass, issueReporter), ClassSource.from(suiteClass)); this.configurationParameters = configurationParameters; this.outputDirectoryProvider = outputDirectoryProvider; this.failIfNoTests = getFailIfNoTests(suiteClass); this.suiteClass = suiteClass; this.lifecycleMethods = new LifecycleMethods(suiteClass, issueReporter); this.discoveryRequestBuilder.listener(DiscoveryIssueForwardingListener.create(id, discoveryListener)); - inspectSuiteDisplayName(suiteClass, issueReporter); } private static Boolean getFailIfNoTests(Class suiteClass) { @@ -141,25 +140,23 @@ public Type getType() { return Type.CONTAINER; } - private static String getSuiteDisplayName(Class testClass) { + private static String getSuiteDisplayName(Class suitClass, DiscoveryIssueReporter issueReporter) { // @formatter:off - return findAnnotation(testClass, SuiteDisplayName.class) + var nonBlank = issueReporter.createReportingCondition(StringUtils::isNotBlank, __ -> { + String message = "@SuiteDisplayName on %s must be declared with a non-blank value.".formatted( + suitClass.getName()); + return DiscoveryIssue.builder(DiscoveryIssue.Severity.WARNING, message) + .source(ClassSource.from(suitClass)) + .build(); + }).toPredicate(); + + return findAnnotation(suitClass, SuiteDisplayName.class) .map(SuiteDisplayName::value) - .filter(StringUtils::isNotBlank) - .orElse(testClass.getSimpleName()); + .filter(nonBlank) + .orElse(suitClass.getSimpleName()); // @formatter:on } - private static void inspectSuiteDisplayName(Class suiteClass, DiscoveryIssueReporter issueReporter) { - findAnnotation(suiteClass, SuiteDisplayName.class).map(SuiteDisplayName::value).filter( - StringUtils::isBlank).ifPresent(__ -> { - String message = "@SuiteDisplayName on %s must be declared with a non-blank value.".formatted( - suiteClass.getName()); - issueReporter.reportIssue(DiscoveryIssue.builder(DiscoveryIssue.Severity.WARNING, message).source( - ClassSource.from(suiteClass)).build()); - }); - } - void execute(EngineExecutionListener executionListener, NamespacedHierarchicalStore requestLevelStore, CancellationToken cancellationToken) { From fe1117677630a5fbca5e17a5493a63bc19478d9b Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Tue, 12 Aug 2025 12:44:50 +0000 Subject: [PATCH 4/5] Fix typo --- .../platform/suite/engine/SuiteTestDescriptor.java | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/junit-platform-suite-engine/src/main/java/org/junit/platform/suite/engine/SuiteTestDescriptor.java b/junit-platform-suite-engine/src/main/java/org/junit/platform/suite/engine/SuiteTestDescriptor.java index a5a6d8399d5c..1b00b886b823 100644 --- a/junit-platform-suite-engine/src/main/java/org/junit/platform/suite/engine/SuiteTestDescriptor.java +++ b/junit-platform-suite-engine/src/main/java/org/junit/platform/suite/engine/SuiteTestDescriptor.java @@ -140,20 +140,20 @@ public Type getType() { return Type.CONTAINER; } - private static String getSuiteDisplayName(Class suitClass, DiscoveryIssueReporter issueReporter) { + private static String getSuiteDisplayName(Class suiteClass, DiscoveryIssueReporter issueReporter) { // @formatter:off var nonBlank = issueReporter.createReportingCondition(StringUtils::isNotBlank, __ -> { String message = "@SuiteDisplayName on %s must be declared with a non-blank value.".formatted( - suitClass.getName()); + suiteClass.getName()); return DiscoveryIssue.builder(DiscoveryIssue.Severity.WARNING, message) - .source(ClassSource.from(suitClass)) + .source(ClassSource.from(suiteClass)) .build(); }).toPredicate(); - return findAnnotation(suitClass, SuiteDisplayName.class) + return findAnnotation(suiteClass, SuiteDisplayName.class) .map(SuiteDisplayName::value) .filter(nonBlank) - .orElse(suitClass.getSimpleName()); + .orElse(suiteClass.getSimpleName()); // @formatter:on } From 59c5f2555e34f91375bfe74dbb1688a935cda5f3 Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Tue, 12 Aug 2025 12:45:06 +0000 Subject: [PATCH 5/5] Polish assertion --- .../org/junit/platform/suite/engine/SuiteEngineTests.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/platform-tests/src/test/java/org/junit/platform/suite/engine/SuiteEngineTests.java b/platform-tests/src/test/java/org/junit/platform/suite/engine/SuiteEngineTests.java index 722ec9ceefd1..a3bcf91afd94 100644 --- a/platform-tests/src/test/java/org/junit/platform/suite/engine/SuiteEngineTests.java +++ b/platform-tests/src/test/java/org/junit/platform/suite/engine/SuiteEngineTests.java @@ -735,8 +735,8 @@ void whitespaceSuiteDisplayNameGeneratesWarning() { void validSuiteDisplayNameGeneratesNoWarning() { var testKit = EngineTestKit.engine(ENGINE_ID).selectors(selectClass(SuiteDisplayNameSuite.class)); - assertThat(testKit.discover().getDiscoveryIssues()).noneMatch( - issue -> issue.message().contains("@SuiteDisplayName")); + assertThat(testKit.discover().getDiscoveryIssues()) // + .noneMatch(issue -> issue.message().contains("@SuiteDisplayName")); } // -----------------------------------------------------------------------------------------------------------------