Skip to content

[JUnit Platform Engine] Use number-and-pickle-if-parameterized strategy #3004

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

Merged
merged 1 commit into from
May 29, 2025
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
8 changes: 4 additions & 4 deletions cucumber-junit-platform-engine/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -420,13 +420,13 @@ cucumber.junit-platform.naming-strategy= # long or short.
# default: short
# include parent descriptor name in test descriptor.

cucumber.junit-platform.naming-strategy.short.example-name= # number or pickle.
# default: number
cucumber.junit-platform.naming-strategy.short.example-name= # number, number-and-pickle-if-parameterized or pickle.
# default: number-and-pickle-if-parameterized
# Use example number or pickle name for examples when
# short naming strategy is used

cucumber.junit-platform.naming-strategy.long.example-name= # number or pickle.
# default: number
cucumber.junit-platform.naming-strategy.long.example-name= # number, number-and-pickle-if-parameterized or pickle.
# default: number-and-pickle-if-parameterized
# Use example number or pickle name for examples when
# long naming strategy is used

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -143,17 +143,19 @@ public final class Constants {
* Property name used to configure the naming strategy of examples in case
* of short naming strategy: {@value}
* <p>
* Value must be one of {@code number} or {@code pickle}. By default,
* numbers are used.
* <p>
* When set to {@code pickle} the pickle name is used. So for scenario name
* {@code Adding <a> and <b>} and example with params {@code a = 10} and
* {@code b = 20} the following name would be produced:
* Value must be one of {@code number}, {@code pickle}, or
* {@code number-and-pickle-if-parameterized}. By default,
* {@code number-and-pickle-if-parameterized} is used.
* <ul>
* <li>When set to {@code number} examples are numbered. So the first
* example of the first examples section would be named {@code #1.1}
* <li>When set to {@code pickle} the pickle name is used. So for scenario
* name {@code Adding <a> and <b>} and example with params {@code a = 10}
* and {@code b = 20} the following name would be produced:
* {@code Adding 10 and 20}.
* <p>
* Using example numbers works well in all scenarios, but if parameterized
* scenario names are used consistently, the pickle name provides more
* clarity.
* <li>When set to {@code number-and-pickle-if-parameterized} the name would
* be rendered as {@code #1.1: Adding 10 and 20}.
* </ul>
*/
@API(status = Status.EXPERIMENTAL, since = "7.16.2")
public static final String JUNIT_PLATFORM_SHORT_NAMING_STRATEGY_EXAMPLE_NAME_PROPERTY_NAME = "cucumber.junit-platform.naming-strategy.short.example-name";
Expand All @@ -162,17 +164,19 @@ public final class Constants {
* Property name used to configure the naming strategy of examples in case
* of long naming strategy: {@value}
* <p>
* Value must be one of {@code number} or {@code pickle}. By default,
* numbers are used.
* <p>
* When set to {@code pickle} the pickle name is used. So for scenario name
* {@code Adding <a> and <b>} and example with params {@code a = 10} and
* {@code b = 20} the following name would be produced:
* {@code Feature Name - Rule Name - Adding <a> and <b> - Examples Name - Adding 10 and 20}.
* <p>
* Using example numbers works well in all scenarios, but if parameterized
* scenario names are used consistently, the pickle name provides more
* clarity.
* Value must be one of {@code number}, {@code pickle}, or
* {@code number-and-pickle-if-parameterized}. By default,
* {@code number-and-pickle-if-parameterized} is used.
* <ul>
* <li>When set to {@code number} examples are numbered. So the first
* example of the first examples section would be named {@code #1.1}
* <li>When set to {@code pickle} the pickle name is used. So for scenario
* name {@code Adding <a> and <b>} and example with params {@code a = 10}
* and {@code b = 20} the following name would be produced:
* {@code Adding 10 and 20}.
* <li>When set to {@code number-and-pickle-if-parameterized} the name would
* be rendered as {@code #1.1: Adding 10 and 20}.
* </ul>
*/
@API(status = Status.EXPERIMENTAL, since = "7.16.2")
public static final String JUNIT_PLATFORM_LONG_NAMING_STRATEGY_EXAMPLE_NAME_PROPERTY_NAME = "cucumber.junit-platform.naming-strategy.long.example-name";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ enum DefaultNamingStrategyProvider {
NamingStrategy create(ConfigurationParameters configuration) {
return configuration.get(JUNIT_PLATFORM_LONG_NAMING_STRATEGY_EXAMPLE_NAME_PROPERTY_NAME)
.map(DefaultNamingStrategyProvider::parseStrategy)
.orElse(DefaultNamingStrategyProvider::exampleNumberStrategy)
.orElse(DefaultNamingStrategyProvider::exampleNumberAndPickleIfParameterizedStrategy)
.apply(DefaultNamingStrategyProvider::longStrategy);
}
},
Expand All @@ -28,7 +28,7 @@ NamingStrategy create(ConfigurationParameters configuration) {
NamingStrategy create(ConfigurationParameters configuration) {
return configuration.get(JUNIT_PLATFORM_SHORT_NAMING_STRATEGY_EXAMPLE_NAME_PROPERTY_NAME)
.map(DefaultNamingStrategyProvider::parseStrategy)
.orElse(DefaultNamingStrategyProvider::exampleNumberStrategy)
.orElse(DefaultNamingStrategyProvider::exampleNumberAndPickleIfParameterizedStrategy)
.apply(DefaultNamingStrategyProvider::shortStrategy);
}
};
Expand All @@ -43,13 +43,38 @@ private static Function<BiFunction<Node, String, String>, NamingStrategy> parseS
switch (exampleStrategy) {
case "number":
return DefaultNamingStrategyProvider::exampleNumberStrategy;
case "number-and-pickle-if-parameterized":
return DefaultNamingStrategyProvider::exampleNumberAndPickleIfParameterizedStrategy;
case "pickle":
return DefaultNamingStrategyProvider::pickleNameStrategy;
default:
throw new IllegalArgumentException("Unrecognized example naming strategy " + exampleStrategy);
}
}

private static NamingStrategy exampleNumberAndPickleIfParameterizedStrategy(
BiFunction<Node, String, String> baseStrategy
) {
return createNamingStrategy(
(node) -> baseStrategy.apply(node, nameOrKeyword(node)),
(node, pickle) -> baseStrategy.apply(node, nameOrKeyword(node) + pickleNameIfParameterized(node, pickle)));
}

private static String pickleNameIfParameterized(Node node, Pickle pickle) {
if (node instanceof Node.Example) {
String pickleName = pickle.getName();
boolean parameterized = !node.getParent()
.flatMap(Node::getParent)
.flatMap(Node::getName)
.filter(pickleName::equals)
.isPresent();
if (parameterized) {
return ": " + pickleName;
}
}
return "";
}

private static NamingStrategy exampleNumberStrategy(BiFunction<Node, String, String> baseStrategy) {
return createNamingStrategy(
(node) -> baseStrategy.apply(node, nameOrKeyword(node)),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,14 @@ private TestDescriptor getOutline() {
return iterator.next();
}

private TestDescriptor getParameterizedOutline() {
Iterator<? extends TestDescriptor> iterator = getFeature().getChildren().iterator();
iterator.next();
iterator.next();
iterator.next();
return iterator.next();
}

@Test
void example() {
TestDescriptor example = getExample();
Expand All @@ -153,8 +161,9 @@ void example() {

@Test
void longNames() {
configurationParameters = new MapConfigurationParameters(
JUNIT_PLATFORM_NAMING_STRATEGY_PROPERTY_NAME, "long");
configurationParameters = new MapConfigurationParameters(Map.of(
JUNIT_PLATFORM_NAMING_STRATEGY_PROPERTY_NAME, "long",
JUNIT_PLATFORM_LONG_NAMING_STRATEGY_EXAMPLE_NAME_PROPERTY_NAME, "number"));

TestDescriptor example = getExample();
assertEquals("A feature with scenario outlines - A scenario outline - With some text - Example #1.1",
Expand All @@ -172,6 +181,17 @@ void longNamesWithPickleNames() {
example.getDisplayName());
}

@Test
void longNamesWithPickleNamesIfParameterized() {
configurationParameters = new MapConfigurationParameters(
JUNIT_PLATFORM_NAMING_STRATEGY_PROPERTY_NAME, "long");

TestDescriptor example = getParametrizedExample();
assertEquals(
"A feature with scenario outlines - A scenario with <example> - Examples - Example #1.1: A scenario with A",
example.getDisplayName());
}

@Test
void shortNamesWithExampleNumbers() {
configurationParameters = new MapConfigurationParameters(
Expand All @@ -191,10 +211,23 @@ void shortNamesWithPickleNames() {
assertEquals("A scenario outline", example.getDisplayName());
}

@Test
void shortNamesWithPickleNamesIfParameterized() {
configurationParameters = new MapConfigurationParameters(
JUNIT_PLATFORM_NAMING_STRATEGY_PROPERTY_NAME, "short");

TestDescriptor example = getParametrizedExample();
assertEquals("Example #1.1: A scenario with A", example.getDisplayName());
}

private TestDescriptor getExample() {
return getOutline().getChildren().iterator().next().getChildren().iterator().next();
}

private TestDescriptor getParametrizedExample() {
return getParameterizedOutline().getChildren().iterator().next().getChildren().iterator().next();
}

@Test
void parallelExecutionForFeaturesEnabled() {
configurationParameters = new MapConfigurationParameters(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,3 +36,15 @@ Feature: A feature with scenario outlines
| example |
| A |
| B |

@ScenarioOutlineTag
Scenario Outline: A scenario with <example>
Given a parameterized scenario outline
When it is executed
Then <example> is used

@Example1Tag
Examples:
| example |
| A |
| B |