From 5d0355518d4dbed3029a208f0e9e4cc5403f2710 Mon Sep 17 00:00:00 2001 From: maestro-game <55531064+maestro-game@users.noreply.github.com> Date: Thu, 16 May 2024 22:03:26 +0300 Subject: [PATCH] [Core] Add hook method name to TeamCityPlugin (#2881) The TeamCityPlugin for IntelliJ IDEA now uses the hook's method name for the name of the hook itself. For example, if we have a hook with the method name `com.example.HookDefinition.beforeHook()``, the generated name will be `Before(beforeHook)`. If we have a hook with the method name `com.example.HookDefinition.(HookDefinition.java:12)`, the generated name will be `Before(HookDefinition)`. If the hook's method can't be identified then fallback to simple hook name. Closes #2798 --- CHANGELOG.md | 2 + .../cucumber/core/plugin/TeamCityPlugin.java | 78 ++++++++++++------- .../core/plugin/TeamCityPluginTest.java | 4 +- 3 files changed, 56 insertions(+), 28 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a297b95da0..b194f290f7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). ## [Unreleased] +### Changed +- [Core] The TeamCityPlugin for IntelliJ IDEA now uses the hook's method name for the name of the hook itself. ([#2798](https://github.com/cucumber/cucumber-jvm/issues/2798) V.V. Belov) ## [7.17.0] - 2024-04-18 ### Added diff --git a/cucumber-core/src/main/java/io/cucumber/core/plugin/TeamCityPlugin.java b/cucumber-core/src/main/java/io/cucumber/core/plugin/TeamCityPlugin.java index fd89f2bc1d..fff10cfce7 100644 --- a/cucumber-core/src/main/java/io/cucumber/core/plugin/TeamCityPlugin.java +++ b/cucumber-core/src/main/java/io/cucumber/core/plugin/TeamCityPlugin.java @@ -37,6 +37,8 @@ import java.util.Locale; import java.util.Map; import java.util.Optional; +import java.util.function.BiFunction; +import java.util.function.Function; import java.util.function.Predicate; import java.util.function.Supplier; import java.util.regex.Matcher; @@ -251,18 +253,31 @@ private String extractLocation(TestStepStarted event) { PickleStepTestStep pickleStepTestStep = (PickleStepTestStep) testStep; return pickleStepTestStep.getUri() + ":" + pickleStepTestStep.getStep().getLine(); } - return extractSourceLocation(testStep); + if (testStep instanceof HookTestStep) { + return formatHookStepLocation( + (HookTestStep) testStep, + javaTestLocationUri(), + TestStep::getCodeLocation); + } + return testStep.getCodeLocation(); } - private String extractSourceLocation(TestStep testStep) { + private static BiFunction javaTestLocationUri() { + return (fqDeclaringClassName, classOrMethodName) -> String.format("java:test://%s/%s", fqDeclaringClassName, + classOrMethodName); + } - Matcher javaMatcher = ANNOTATION_GLUE_CODE_LOCATION_PATTERN.matcher(testStep.getCodeLocation()); + private String formatHookStepLocation( + HookTestStep hookTestStep, BiFunction hookStepCase, + Function defaultHookName + ) { + Matcher javaMatcher = ANNOTATION_GLUE_CODE_LOCATION_PATTERN.matcher(hookTestStep.getCodeLocation()); if (javaMatcher.matches()) { String fqDeclaringClassName = javaMatcher.group(1); String methodName = javaMatcher.group(2); - return String.format("java:test://%s/%s", fqDeclaringClassName, methodName); + return hookStepCase.apply(fqDeclaringClassName, methodName); } - Matcher java8Matcher = LAMBDA_GLUE_CODE_LOCATION_PATTERN.matcher(testStep.getCodeLocation()); + Matcher java8Matcher = LAMBDA_GLUE_CODE_LOCATION_PATTERN.matcher(hookTestStep.getCodeLocation()); if (java8Matcher.matches()) { String fqDeclaringClassName = java8Matcher.group(1); String declaringClassName; @@ -272,10 +287,9 @@ private String extractSourceLocation(TestStep testStep) { } else { declaringClassName = fqDeclaringClassName; } - return String.format("java:test://%s/%s", fqDeclaringClassName, declaringClassName); + return hookStepCase.apply(fqDeclaringClassName, declaringClassName); } - - return testStep.getCodeLocation(); + return defaultHookName.apply(hookTestStep); } private void printTestStepFinished(TestStepFinished event) { @@ -324,30 +338,42 @@ private void printTestStepFinished(TestStepFinished event) { print(TEMPLATE_TEST_FINISHED, timeStamp, duration, name); } - private String extractName(TestStep step) { - if (step instanceof PickleStepTestStep) { - PickleStepTestStep pickleStepTestStep = (PickleStepTestStep) step; + private String getHookName(HookTestStep hook) { + HookType hookType = hook.getHookType(); + switch (hookType) { + case BEFORE: + return "Before"; + case AFTER: + return "After"; + case BEFORE_STEP: + return "BeforeStep"; + case AFTER_STEP: + return "AfterStep"; + default: + return hookType.name().toLowerCase(Locale.US); + } + } + + private String extractName(TestStep testStep) { + if (testStep instanceof PickleStepTestStep) { + PickleStepTestStep pickleStepTestStep = (PickleStepTestStep) testStep; return pickleStepTestStep.getStep().getText(); } - if (step instanceof HookTestStep) { - HookTestStep hook = (HookTestStep) step; - HookType hookType = hook.getHookType(); - switch (hookType) { - case BEFORE: - return "Before"; - case AFTER: - return "After"; - case BEFORE_STEP: - return "BeforeStep"; - case AFTER_STEP: - return "AfterStep"; - default: - return hookType.name().toLowerCase(Locale.US); - } + if (testStep instanceof HookTestStep) { + HookTestStep hookTestStep = (HookTestStep) testStep; + return formatHookStepLocation( + hookTestStep, + hookNameFormat(hookTestStep), + this::getHookName); } return "Unknown step"; } + private BiFunction hookNameFormat(HookTestStep hookTestStep) { + return (fqDeclaringClassName, classOrMethodName) -> String.format("%s(%s)", getHookName(hookTestStep), + classOrMethodName); + } + private String getSnippets(TestCase testCase) { URI uri = testCase.getUri(); Location location = testCase.getLocation(); diff --git a/cucumber-core/src/test/java/io/cucumber/core/plugin/TeamCityPluginTest.java b/cucumber-core/src/test/java/io/cucumber/core/plugin/TeamCityPluginTest.java index 024efb5830..e965d469ed 100755 --- a/cucumber-core/src/test/java/io/cucumber/core/plugin/TeamCityPluginTest.java +++ b/cucumber-core/src/test/java/io/cucumber/core/plugin/TeamCityPluginTest.java @@ -287,7 +287,7 @@ void should_print_location_hint_for_java_hooks() { .run(); assertThat(out, bytes(containsString("" + - "##teamcity[testStarted timestamp = '1970-01-01T12:00:00.000+0000' locationHint = 'java:test://com.example.HookDefinition/beforeHook' captureStandardOutput = 'true' name = 'Before']\n"))); + "##teamcity[testStarted timestamp = '1970-01-01T12:00:00.000+0000' locationHint = 'java:test://com.example.HookDefinition/beforeHook' captureStandardOutput = 'true' name = 'Before(beforeHook)']\n"))); } @Test @@ -310,7 +310,7 @@ void should_print_location_hint_for_lambda_hooks() { .run(); assertThat(out, bytes(containsString("" + - "##teamcity[testStarted timestamp = '1970-01-01T12:00:00.000+0000' locationHint = 'java:test://com.example.HookDefinition/HookDefinition' captureStandardOutput = 'true' name = 'Before']\n"))); + "##teamcity[testStarted timestamp = '1970-01-01T12:00:00.000+0000' locationHint = 'java:test://com.example.HookDefinition/HookDefinition' captureStandardOutput = 'true' name = 'Before(HookDefinition)']\n"))); } @Test