diff --git a/CHANGELOG.md b/CHANGELOG.md index 691e43bed8..09e68546e0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] ### Added - [Core] Emit Suggestion message ([#3073](https://github.com/cucumber/cucumber-jvm/pull/3073) M.P. Korstanje) +- [JUnit Platform Engine] Warn when surefire naming strategy is used ([#3067](https://github.com/cucumber/cucumber-jvm/pull/3067) M.P. Korstanje) ### Fixed - [Core] Emit StepMatchArgumentsList for ambiguous steps ([#3066](https://github.com/cucumber/cucumber-jvm/pull/3066) M.P. Korstanje) diff --git a/cucumber-junit-platform-engine/README.md b/cucumber-junit-platform-engine/README.md index 3fb773ae01..c60c24efb3 100644 --- a/cucumber-junit-platform-engine/README.md +++ b/cucumber-junit-platform-engine/README.md @@ -64,11 +64,13 @@ To improve the readability of the reports use the `cucumber.junit-platform.naming-strategy` configuration parameter. This will include the feature name, scenario name, example number, etc. in the report. +For `3.5.2` and below use: + ```xml org.apache.maven.plugins maven-surefire-plugin - 3.2.5 + 3.5.2 @@ -77,6 +79,23 @@ include the feature name, scenario name, example number, etc. in the report. +``` + +For `3.5.4` and above use: + +```xml + + org.apache.maven.plugins + maven-surefire-plugin + 3.5.4 + + + + cucumber.junit-platform.naming-strategy=long + + + + ``` ```kotlin @@ -456,7 +475,9 @@ cucumber.junit-platform.discovery.as-root-engine # true or false cucumber.junit-platform.naming-strategy= # long, short or surefire. # default: short # long: include parent descriptor names in test descriptor. - # surefire: Workaround to make test names appear nicely with Surefire. + # surefire: Workaround to make test names appear nicely + # with Surefire < 3.5.3. For 3.5.4 and above use the long + # strategy. cucumber.junit-platform.naming-strategy.short.example-name= # number, number-and-pickle-if-parameterized or pickle. # default: number-and-pickle-if-parameterized @@ -736,7 +757,7 @@ Note: any files written by Cucumber will be overwritten during the rerun. org.apache.maven.plugins maven-surefire-plugin - 3.2.5 + 3.5.4 2 @@ -744,7 +765,7 @@ Note: any files written by Cucumber will be overwritten during the rerun. information to disambiguate between different examples and scenarios. --> - cucumber.junit-platform.naming-strategy=surefire + cucumber.junit-platform.naming-strategy=long diff --git a/cucumber-junit-platform-engine/src/main/java/io/cucumber/junit/platform/engine/Constants.java b/cucumber-junit-platform-engine/src/main/java/io/cucumber/junit/platform/engine/Constants.java index 2c28d50fec..543330d50c 100644 --- a/cucumber-junit-platform-engine/src/main/java/io/cucumber/junit/platform/engine/Constants.java +++ b/cucumber-junit-platform-engine/src/main/java/io/cucumber/junit/platform/engine/Constants.java @@ -135,11 +135,13 @@ public final class Constants { * {@code Feature Name - Rule Name - Scenario Name - Examples Name - Example #N }. * This is useful for tools that only report the test name such as Gradle. *

- * When the {@code surefire} naming strategy is used nodes are named such - * that the Surefire output makes sense. The feature name will be rendered - * as the class name. The long name without the feature will be rendered as - * the test method name. For example: + * When the {@code surefire} naming strategy is used with Surefire <= 3.5.2, + * nodes are named such the output makes sense. The feature name will be + * rendered as the class name. The long name without the feature will be + * rendered as the test method name. For example: * {@code Feature Name.Rule Name - Scenario Name - Examples Name - Example #N}. + *

+ * For Surefire >= 3.5.4 use the {@code long} strategy instead. */ @API(status = Status.EXPERIMENTAL, since = "7.0.0") public static final String JUNIT_PLATFORM_NAMING_STRATEGY_PROPERTY_NAME = "cucumber.junit-platform.naming-strategy"; diff --git a/cucumber-junit-platform-engine/src/main/java/io/cucumber/junit/platform/engine/CucumberConfiguration.java b/cucumber-junit-platform-engine/src/main/java/io/cucumber/junit/platform/engine/CucumberConfiguration.java index 3c0a8909de..18907070d4 100644 --- a/cucumber-junit-platform-engine/src/main/java/io/cucumber/junit/platform/engine/CucumberConfiguration.java +++ b/cucumber-junit-platform-engine/src/main/java/io/cucumber/junit/platform/engine/CucumberConfiguration.java @@ -16,6 +16,7 @@ import io.cucumber.tagexpressions.TagExpressionParser; import org.junit.platform.engine.ConfigurationParameters; import org.junit.platform.engine.support.config.PrefixedConfigurationParameters; +import org.junit.platform.engine.support.discovery.DiscoveryIssueReporter; import org.junit.platform.engine.support.hierarchical.Node.ExecutionMode; import java.net.URI; @@ -47,7 +48,10 @@ import static io.cucumber.junit.platform.engine.Constants.PLUGIN_PUBLISH_TOKEN_PROPERTY_NAME; import static io.cucumber.junit.platform.engine.Constants.SNIPPET_TYPE_PROPERTY_NAME; import static io.cucumber.junit.platform.engine.Constants.UUID_GENERATOR_PROPERTY_NAME; +import static io.cucumber.junit.platform.engine.DefaultNamingStrategyProvider.SUREFIRE; import static java.util.Objects.requireNonNull; +import static org.junit.platform.engine.DiscoveryIssue.Severity.WARNING; +import static org.junit.platform.engine.DiscoveryIssue.create; class CucumberConfiguration implements io.cucumber.core.plugin.Options, @@ -56,9 +60,11 @@ class CucumberConfiguration implements io.cucumber.core.eventbus.Options { private final ConfigurationParameters configurationParameters; + private final DiscoveryIssueReporter issueReporter; - CucumberConfiguration(ConfigurationParameters configurationParameters) { + CucumberConfiguration(ConfigurationParameters configurationParameters, DiscoveryIssueReporter issueReporter) { this.configurationParameters = requireNonNull(configurationParameters); + this.issueReporter = requireNonNull(issueReporter); } @Override @@ -180,10 +186,22 @@ boolean isParallelExecutionEnabled() { NamingStrategy namingStrategy() { return configurationParameters .get(JUNIT_PLATFORM_NAMING_STRATEGY_PROPERTY_NAME, DefaultNamingStrategyProvider::getStrategyProvider) + .map(this::reportIssueIfSurefireStrategyIsUsed) .orElse(DefaultNamingStrategyProvider.SHORT) .create(configurationParameters); } + private DefaultNamingStrategyProvider reportIssueIfSurefireStrategyIsUsed(DefaultNamingStrategyProvider strategy) { + if (strategy == SUREFIRE) { + issueReporter.reportIssue(create( + WARNING, + String.format( + "The '%s=surefire' naming strategy does not work as expected on Surefire 3.5.4 and above. Upgrade Surefire to at least 3.5.4 and use the 'long' strategy instead.", + JUNIT_PLATFORM_NAMING_STRATEGY_PROPERTY_NAME))); + } + return strategy; + } + Set featuresWithLines() { return configurationParameters.get(FEATURES_PROPERTY_NAME, s -> Arrays.stream(s.split(",")) diff --git a/cucumber-junit-platform-engine/src/main/java/io/cucumber/junit/platform/engine/CucumberTestEngine.java b/cucumber-junit-platform-engine/src/main/java/io/cucumber/junit/platform/engine/CucumberTestEngine.java index e362c1eb1d..b4683f8307 100644 --- a/cucumber-junit-platform-engine/src/main/java/io/cucumber/junit/platform/engine/CucumberTestEngine.java +++ b/cucumber-junit-platform-engine/src/main/java/io/cucumber/junit/platform/engine/CucumberTestEngine.java @@ -47,13 +47,12 @@ public String getId() { public TestDescriptor discover(EngineDiscoveryRequest discoveryRequest, UniqueId uniqueId) { ConfigurationParameters configurationParameters = discoveryRequest.getConfigurationParameters(); TestSource testSource = createEngineTestSource(configurationParameters); - CucumberConfiguration configuration = new CucumberConfiguration(configurationParameters); - CucumberEngineDescriptor engineDescriptor = new CucumberEngineDescriptor(uniqueId, configuration, testSource); - DiscoveryIssueReporter issueReporter = deduplicating(forwarding( // discoveryRequest.getDiscoveryListener(), // - engineDescriptor.getUniqueId() // + uniqueId // )); + CucumberConfiguration configuration = new CucumberConfiguration(configurationParameters, issueReporter); + CucumberEngineDescriptor engineDescriptor = new CucumberEngineDescriptor(uniqueId, configuration, testSource); // Early out if Cucumber is the root engine and discovery has been // explicitly disabled. Workaround for: diff --git a/cucumber-junit-platform-engine/src/main/java/io/cucumber/junit/platform/engine/FeaturesPropertyResolver.java b/cucumber-junit-platform-engine/src/main/java/io/cucumber/junit/platform/engine/FeaturesPropertyResolver.java index 34c9d3e6b7..ebb3df556e 100644 --- a/cucumber-junit-platform-engine/src/main/java/io/cucumber/junit/platform/engine/FeaturesPropertyResolver.java +++ b/cucumber-junit-platform-engine/src/main/java/io/cucumber/junit/platform/engine/FeaturesPropertyResolver.java @@ -45,7 +45,7 @@ void resolveSelectors( DiscoveryIssueReporter issueReporter ) { ConfigurationParameters configuration = request.getConfigurationParameters(); - CucumberConfiguration options = new CucumberConfiguration(configuration); + CucumberConfiguration options = new CucumberConfiguration(configuration, issueReporter); Set selectors = options.featuresWithLines(); if (selectors.isEmpty()) { diff --git a/cucumber-junit-platform-engine/src/test/java/io/cucumber/junit/platform/engine/CucumberConfigurationTest.java b/cucumber-junit-platform-engine/src/test/java/io/cucumber/junit/platform/engine/CucumberConfigurationTest.java index 155e1dde3b..848debaeb6 100644 --- a/cucumber-junit-platform-engine/src/test/java/io/cucumber/junit/platform/engine/CucumberConfigurationTest.java +++ b/cucumber-junit-platform-engine/src/test/java/io/cucumber/junit/platform/engine/CucumberConfigurationTest.java @@ -6,8 +6,12 @@ import io.cucumber.core.snippets.SnippetType; import org.junit.jupiter.api.Test; import org.junit.platform.engine.ConfigurationParameters; +import org.junit.platform.engine.DiscoveryIssue; +import org.junit.platform.engine.support.discovery.DiscoveryIssueReporter; import java.net.URI; +import java.util.ArrayList; +import java.util.List; import java.util.Map; import static java.util.stream.Collectors.toList; @@ -22,20 +26,24 @@ class CucumberConfigurationTest { + private final List issues = new ArrayList<>(); + private final DiscoveryIssueReporter issueReporter = DiscoveryIssueReporter.collecting(issues); + @Test void getPluginNames() { ConfigurationParameters config = new MapConfigurationParameters( Constants.PLUGIN_PROPERTY_NAME, "html:path/to/report.html"); - assertThat(new CucumberConfiguration(config).plugins().stream() + assertThat(new CucumberConfiguration(config, issueReporter).plugins().stream() .map(Options.Plugin::pluginString) .collect(toList()), hasItem("html:path/to/report.html")); CucumberConfiguration htmlAndJson = new CucumberConfiguration( new MapConfigurationParameters(Constants.PLUGIN_PROPERTY_NAME, - "html:path/with spaces/to/report.html, message:path/with spaces/to/report.ndjson")); + "html:path/with spaces/to/report.html, message:path/with spaces/to/report.ndjson"), + issueReporter); assertThat(htmlAndJson.plugins().stream() .map(Options.Plugin::pluginString) @@ -48,7 +56,7 @@ void getPluginNamesWithPublishToken() { ConfigurationParameters config = new MapConfigurationParameters( Constants.PLUGIN_PUBLISH_TOKEN_PROPERTY_NAME, "some/token"); - assertThat(new CucumberConfiguration(config).plugins().stream() + assertThat(new CucumberConfiguration(config, issueReporter).plugins().stream() .map(Options.Plugin::pluginString) .collect(toList()), hasItem("io.cucumber.core.plugin.PublishFormatter:some/token")); @@ -58,7 +66,7 @@ void getPluginNamesWithPublishToken() { void getPluginNamesWithNothingEnabled() { ConfigurationParameters config = new EmptyConfigurationParameters(); - assertThat(new CucumberConfiguration(config).plugins().stream() + assertThat(new CucumberConfiguration(config, issueReporter).plugins().stream() .map(Options.Plugin::pluginString) .collect(toList()), empty()); @@ -69,7 +77,7 @@ void getPluginNamesWithPublishQuiteEnabled() { ConfigurationParameters config = new MapConfigurationParameters( Constants.PLUGIN_PUBLISH_QUIET_PROPERTY_NAME, "true"); - assertThat(new CucumberConfiguration(config).plugins().stream() + assertThat(new CucumberConfiguration(config, issueReporter).plugins().stream() .map(Options.Plugin::pluginString) .collect(toList()), empty()); @@ -80,7 +88,7 @@ void getPluginNamesWithPublishEnabled() { ConfigurationParameters config = new MapConfigurationParameters( Constants.PLUGIN_PUBLISH_ENABLED_PROPERTY_NAME, "true"); - assertThat(new CucumberConfiguration(config).plugins().stream() + assertThat(new CucumberConfiguration(config, issueReporter).plugins().stream() .map(Options.Plugin::pluginString) .collect(toList()), hasItem("io.cucumber.core.plugin.PublishFormatter")); @@ -92,7 +100,7 @@ void getPluginNamesWithPublishDisabledAndPublishToken() { Constants.PLUGIN_PUBLISH_ENABLED_PROPERTY_NAME, "false", Constants.PLUGIN_PUBLISH_TOKEN_PROPERTY_NAME, "some/token")); - assertThat(new CucumberConfiguration(config).plugins().stream() + assertThat(new CucumberConfiguration(config, issueReporter).plugins().stream() .map(Options.Plugin::pluginString) .collect(toList()), empty()); @@ -103,12 +111,12 @@ void isMonochrome() { MapConfigurationParameters ansiColors = new MapConfigurationParameters( Constants.ANSI_COLORS_DISABLED_PROPERTY_NAME, "true"); - assertTrue(new CucumberConfiguration(ansiColors).isMonochrome()); + assertTrue(new CucumberConfiguration(ansiColors, issueReporter).isMonochrome()); MapConfigurationParameters noAnsiColors = new MapConfigurationParameters( Constants.ANSI_COLORS_DISABLED_PROPERTY_NAME, "false"); - assertFalse(new CucumberConfiguration(noAnsiColors).isMonochrome()); + assertFalse(new CucumberConfiguration(noAnsiColors, issueReporter).isMonochrome()); } @Test @@ -117,7 +125,7 @@ void getGlue() { Constants.GLUE_PROPERTY_NAME, "com.example.app, com.example.glue"); - assertThat(new CucumberConfiguration(config).getGlue(), + assertThat(new CucumberConfiguration(config, issueReporter).getGlue(), contains( URI.create("classpath:/com/example/app"), URI.create("classpath:/com/example/glue"))); @@ -128,12 +136,12 @@ void isDryRun() { ConfigurationParameters dryRun = new MapConfigurationParameters( Constants.EXECUTION_DRY_RUN_PROPERTY_NAME, "true"); - assertTrue(new CucumberConfiguration(dryRun).isDryRun()); + assertTrue(new CucumberConfiguration(dryRun, issueReporter).isDryRun()); ConfigurationParameters noDryRun = new MapConfigurationParameters( Constants.EXECUTION_DRY_RUN_PROPERTY_NAME, "false"); - assertFalse(new CucumberConfiguration(noDryRun).isDryRun()); + assertFalse(new CucumberConfiguration(noDryRun, issueReporter).isDryRun()); } @Test @@ -142,12 +150,12 @@ void getSnippetType() { Constants.SNIPPET_TYPE_PROPERTY_NAME, "underscore"); - assertThat(new CucumberConfiguration(underscore).getSnippetType(), is(SnippetType.UNDERSCORE)); + assertThat(new CucumberConfiguration(underscore, issueReporter).getSnippetType(), is(SnippetType.UNDERSCORE)); ConfigurationParameters camelcase = new MapConfigurationParameters( Constants.SNIPPET_TYPE_PROPERTY_NAME, "camelcase"); - assertThat(new CucumberConfiguration(camelcase).getSnippetType(), is(SnippetType.CAMELCASE)); + assertThat(new CucumberConfiguration(camelcase, issueReporter).getSnippetType(), is(SnippetType.CAMELCASE)); } @Test @@ -155,15 +163,15 @@ void isParallelExecutionEnabled() { ConfigurationParameters enabled = new MapConfigurationParameters( Constants.PARALLEL_EXECUTION_ENABLED_PROPERTY_NAME, "true"); - assertTrue(new CucumberConfiguration(enabled).isParallelExecutionEnabled()); + assertTrue(new CucumberConfiguration(enabled, issueReporter).isParallelExecutionEnabled()); ConfigurationParameters disabled = new MapConfigurationParameters( Constants.PARALLEL_EXECUTION_ENABLED_PROPERTY_NAME, "false"); - assertFalse(new CucumberConfiguration(disabled).isParallelExecutionEnabled()); + assertFalse(new CucumberConfiguration(disabled, issueReporter).isParallelExecutionEnabled()); ConfigurationParameters absent = new MapConfigurationParameters( "some key", "some value"); - assertFalse(new CucumberConfiguration(absent).isParallelExecutionEnabled()); + assertFalse(new CucumberConfiguration(absent, issueReporter).isParallelExecutionEnabled()); } @Test @@ -172,7 +180,7 @@ void objectFactory() { Constants.OBJECT_FACTORY_PROPERTY_NAME, DefaultObjectFactory.class.getName()); - assertThat(new CucumberConfiguration(configurationParameters).getObjectFactoryClass(), + assertThat(new CucumberConfiguration(configurationParameters, issueReporter).getObjectFactoryClass(), is(DefaultObjectFactory.class)); } @@ -182,7 +190,7 @@ void uuidGenerator() { Constants.UUID_GENERATOR_PROPERTY_NAME, IncrementingUuidGenerator.class.getName()); - assertThat(new CucumberConfiguration(configurationParameters).getUuidGeneratorClass(), + assertThat(new CucumberConfiguration(configurationParameters, issueReporter).getUuidGeneratorClass(), is(IncrementingUuidGenerator.class)); } } diff --git a/examples/calculator-java-junit5/pom.xml b/examples/calculator-java-junit5/pom.xml index 2d06cab86e..276455daec 100644 --- a/examples/calculator-java-junit5/pom.xml +++ b/examples/calculator-java-junit5/pom.xml @@ -92,7 +92,7 @@ - cucumber.junit-platform.naming-strategy=surefire + cucumber.junit-platform.naming-strategy=long diff --git a/examples/calculator-kotlin-junit5/pom.xml b/examples/calculator-kotlin-junit5/pom.xml index a6ee7e2180..c93ec996af 100644 --- a/examples/calculator-kotlin-junit5/pom.xml +++ b/examples/calculator-kotlin-junit5/pom.xml @@ -114,7 +114,7 @@ - cucumber.junit-platform.naming-strategy=surefire + cucumber.junit-platform.naming-strategy=long diff --git a/examples/spring-java-junit5/pom.xml b/examples/spring-java-junit5/pom.xml index caf0a88ea7..5f6b66506a 100644 --- a/examples/spring-java-junit5/pom.xml +++ b/examples/spring-java-junit5/pom.xml @@ -111,7 +111,7 @@ - cucumber.junit-platform.naming-strategy=surefire + cucumber.junit-platform.naming-strategy=long