Skip to content

Commit 9d7b1e3

Browse files
authored
Use a message based TeamCityPlugin (#3007)
1 parent 712878d commit 9d7b1e3

File tree

7 files changed

+533
-304
lines changed

7 files changed

+533
-304
lines changed

cucumber-bom/pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
<html-formatter.version>21.10.1</html-formatter.version>
2020
<junit-xml-formatter.version>0.7.1</junit-xml-formatter.version>
2121
<messages.version>27.2.0</messages.version>
22-
<query.version>13.2.0</query.version>
22+
<query.version>13.3.0</query.version>
2323
<tag-expressions.version>6.1.2</tag-expressions.version>
2424
<testng-xml-formatter.version>0.3.1</testng-xml-formatter.version>
2525
</properties>

cucumber-core/src/main/java/io/cucumber/core/plugin/TeamCityPlugin.java

Lines changed: 445 additions & 280 deletions
Large diffs are not rendered by default.

cucumber-core/src/test/java/io/cucumber/core/backend/StubHookDefinition.java

Lines changed: 31 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package io.cucumber.core.backend;
22

3+
import java.util.Optional;
34
import java.util.function.Consumer;
45

56
public class StubHookDefinition implements HookDefinition {
@@ -8,31 +9,46 @@ public class StubHookDefinition implements HookDefinition {
89
private final String location;
910
private final RuntimeException exception;
1011
private final Consumer<TestCaseState> action;
12+
private final SourceReference sourceReference;
13+
private final HookType hookType;
1114

12-
public StubHookDefinition(String location, RuntimeException exception, Consumer<TestCaseState> action) {
15+
public StubHookDefinition(
16+
String location, RuntimeException exception, Consumer<TestCaseState> action,
17+
SourceReference sourceReference, HookType hookType
18+
) {
1319
this.location = location;
1420
this.exception = exception;
1521
this.action = action;
22+
this.sourceReference = sourceReference;
23+
this.hookType = hookType;
1624
}
1725

1826
public StubHookDefinition(String location, Consumer<TestCaseState> action) {
19-
this(location, null, action);
27+
this(location, null, action, null, null);
2028
}
2129

2230
public StubHookDefinition() {
23-
this(STUBBED_LOCATION_WITH_DETAILS, null, null);
31+
this(STUBBED_LOCATION_WITH_DETAILS, null, null, null, null);
2432
}
2533

2634
public StubHookDefinition(Consumer<TestCaseState> action) {
27-
this(STUBBED_LOCATION_WITH_DETAILS, null, action);
35+
this(STUBBED_LOCATION_WITH_DETAILS, null, action, null, null);
2836
}
2937

3038
public StubHookDefinition(RuntimeException exception) {
31-
this(STUBBED_LOCATION_WITH_DETAILS, exception, null);
39+
this(STUBBED_LOCATION_WITH_DETAILS, exception, null, null, null);
3240
}
3341

3442
public StubHookDefinition(String location) {
35-
this(location, null, null);
43+
this(location, null, null, null, null);
44+
}
45+
46+
public StubHookDefinition(SourceReference sourceReference, HookType hookType) {
47+
this(null, null, null, sourceReference, hookType);
48+
}
49+
50+
public StubHookDefinition(SourceReference sourceReference, HookType hookType, RuntimeException exception) {
51+
this(null, exception, null, sourceReference, hookType);
3652
}
3753

3854
@Override
@@ -65,4 +81,13 @@ public String getLocation() {
6581
return location;
6682
}
6783

84+
@Override
85+
public Optional<SourceReference> getSourceReference() {
86+
return Optional.ofNullable(sourceReference);
87+
}
88+
89+
@Override
90+
public Optional<HookType> getHookType() {
91+
return Optional.ofNullable(hookType);
92+
}
6893
}

cucumber-core/src/test/java/io/cucumber/core/eventbus/IncrementingUuidGeneratorTest.java

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
import java.lang.reflect.Method;
1111
import java.net.URISyntaxException;
1212
import java.nio.file.Files;
13-
import java.nio.file.Path;
13+
import java.nio.file.Paths;
1414
import java.util.ArrayList;
1515
import java.util.HashSet;
1616
import java.util.List;
@@ -24,6 +24,7 @@
2424
import static org.hamcrest.Matchers.containsString;
2525
import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
2626
import static org.junit.jupiter.api.Assertions.assertEquals;
27+
import static org.junit.jupiter.api.Assertions.assertFalse;
2728
import static org.junit.jupiter.api.Assertions.assertNotEquals;
2829
import static org.junit.jupiter.api.Assertions.assertThrows;
2930
import static org.junit.jupiter.api.Assertions.assertTrue;
@@ -152,7 +153,7 @@ void lazy_init() {
152153

153154
private static void checkUuidProperties(List<UUID> uuids) {
154155
// all UUIDs are non-null
155-
assertTrue(uuids.stream().filter(Objects::isNull).findFirst().isEmpty());
156+
assertFalse(uuids.stream().anyMatch(Objects::isNull));
156157

157158
// UUID version is always 8
158159
List<Integer> versions = uuids.stream().map(UUID::version).distinct().collect(Collectors.toList());
@@ -331,7 +332,7 @@ protected Class<?> findClass(String name) {
331332

332333
private byte[] loadClassBytesFromDisk(String className) {
333334
try {
334-
return Files.readAllBytes(Path.of(Objects.requireNonNull(NonCachingClassLoader.class
335+
return Files.readAllBytes(Paths.get(Objects.requireNonNull(NonCachingClassLoader.class
335336
.getResource(className.replaceFirst(".+\\.", "") + ".class")).toURI()));
336337
} catch (IOException e) {
337338
throw new RuntimeException("Unable to read file from disk");

cucumber-core/src/test/java/io/cucumber/core/plugin/StubException.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ private StubException(String className, String message, String stacktrace) {
1515
}
1616

1717
public StubException() {
18-
this("the stack trace");
18+
this("stub exception");
1919
}
2020

2121
public StubException(String message) {

cucumber-core/src/test/java/io/cucumber/core/plugin/TeamCityPluginTest.java

Lines changed: 21 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,11 @@
2020
import java.io.PrintStream;
2121
import java.util.UUID;
2222

23+
import static io.cucumber.core.backend.HookDefinition.HookType.BEFORE;
2324
import static io.cucumber.core.plugin.Bytes.bytes;
25+
import static io.cucumber.core.plugin.TeamCityPluginTestStepDefinition.getAnnotationSourceReference;
26+
import static io.cucumber.core.plugin.TeamCityPluginTestStepDefinition.getStackSourceReference;
27+
import static java.nio.charset.StandardCharsets.UTF_8;
2428
import static java.time.Clock.fixed;
2529
import static java.time.Instant.EPOCH;
2630
import static java.time.ZoneId.of;
@@ -72,7 +76,7 @@ void should_handle_scenario_outline() {
7276
"##teamcity[testSuiteStarted timestamp = '1970-01-01T12:00:00.000+0000' locationHint = '" + location
7377
+ "path/test.feature:5' name = 'examples name']\n" +
7478
"##teamcity[testSuiteStarted timestamp = '1970-01-01T12:00:00.000+0000' locationHint = '" + location
75-
+ "path/test.feature:7' name = 'Example #1.1']\n" +
79+
+ "path/test.feature:7' name = '#1.1: name 1']\n" +
7680
"##teamcity[customProgressStatus type = 'testStarted' timestamp = '1970-01-01T12:00:00.000+0000']\n" +
7781
"##teamcity[testStarted timestamp = '1970-01-01T12:00:00.000+0000' locationHint = '" + location
7882
+ "path/test.feature:3' captureStandardOutput = 'true' name = 'first step']\n" +
@@ -83,9 +87,10 @@ void should_handle_scenario_outline() {
8387
"##teamcity[testFinished timestamp = '1970-01-01T12:00:00.000+0000' duration = '0' name = 'second step']\n"
8488
+
8589
"##teamcity[customProgressStatus type = 'testFinished' timestamp = '1970-01-01T12:00:00.000+0000']\n" +
86-
"##teamcity[testSuiteFinished timestamp = '1970-01-01T12:00:00.000+0000' name = 'Example #1.1']\n" +
90+
"##teamcity[testSuiteFinished timestamp = '1970-01-01T12:00:00.000+0000' name = '#1.1: name 1']\n"
91+
+
8792
"##teamcity[testSuiteStarted timestamp = '1970-01-01T12:00:00.000+0000' locationHint = '" + location
88-
+ "path/test.feature:8' name = 'Example #1.2']\n" +
93+
+ "path/test.feature:8' name = '#1.2: name 2']\n" +
8994
"##teamcity[customProgressStatus type = 'testStarted' timestamp = '1970-01-01T12:00:00.000+0000']\n" +
9095
"##teamcity[testStarted timestamp = '1970-01-01T12:00:00.000+0000' locationHint = '" + location
9196
+ "path/test.feature:3' captureStandardOutput = 'true' name = 'first step']\n" +
@@ -96,7 +101,8 @@ void should_handle_scenario_outline() {
96101
"##teamcity[testFinished timestamp = '1970-01-01T12:00:00.000+0000' duration = '0' name = 'third step']\n"
97102
+
98103
"##teamcity[customProgressStatus type = 'testFinished' timestamp = '1970-01-01T12:00:00.000+0000']\n" +
99-
"##teamcity[testSuiteFinished timestamp = '1970-01-01T12:00:00.000+0000' name = 'Example #1.2']\n" +
104+
"##teamcity[testSuiteFinished timestamp = '1970-01-01T12:00:00.000+0000' name = '#1.2: name 2']\n"
105+
+
100106
"##teamcity[customProgressStatus testsCategory = '' count = '0' timestamp = '1970-01-01T12:00:00.000+0000']\n"
101107
+
102108
"##teamcity[testSuiteFinished timestamp = '1970-01-01T12:00:00.000+0000' name = 'examples name']\n" +
@@ -121,7 +127,7 @@ void should_handle_nameless_attach_events() {
121127
.withEventBus(new TimeServiceEventBus(fixed(EPOCH, of("UTC")), UUID::randomUUID))
122128
.withBackendSupplier(new StubBackendSupplier(
123129
singletonList(new StubHookDefinition(
124-
(TestCaseState state) -> state.attach("A message", "text/plain", null))),
130+
(TestCaseState state) -> state.attach("A message".getBytes(UTF_8), "text/plain", null))),
125131
singletonList(new StubStepDefinition("first step")),
126132
emptyList()))
127133
.build()
@@ -168,7 +174,8 @@ void should_handle_attach_events() {
168174
.withEventBus(new TimeServiceEventBus(fixed(EPOCH, of("UTC")), UUID::randomUUID))
169175
.withBackendSupplier(new StubBackendSupplier(
170176
singletonList(new StubHookDefinition(
171-
(TestCaseState state) -> state.attach("A message", "text/plain", "message.txt"))),
177+
(TestCaseState state) -> state.attach("A message".getBytes(UTF_8), "text/plain",
178+
"message.txt"))),
172179
singletonList(new StubStepDefinition("first step")),
173180
emptyList()))
174181
.build()
@@ -258,17 +265,17 @@ void should_print_error_message_for_before_hooks() {
258265
.withEventBus(new TimeServiceEventBus(fixed(EPOCH, of("UTC")), UUID::randomUUID))
259266
.withBackendSupplier(new StubBackendSupplier(
260267
singletonList(
261-
new StubHookDefinition(new StubException("Step failed")
268+
new StubHookDefinition(getAnnotationSourceReference(), BEFORE, new StubException()
262269
.withStacktrace("the stack trace"))),
263270
singletonList(new StubStepDefinition("first step")),
264271
emptyList()))
265272
.build()
266273
.run();
267274

268275
assertThat(out, bytes(containsString("" +
269-
"##teamcity[testStarted timestamp = '1970-01-01T12:00:00.000+0000' locationHint = '{stubbed location with details}' captureStandardOutput = 'true' name = 'Before']\n"
276+
"##teamcity[testStarted timestamp = '1970-01-01T12:00:00.000+0000' locationHint = 'java:test://io.cucumber.core.plugin.TeamCityPluginTestStepDefinition/beforeHook' captureStandardOutput = 'true' name = 'Before(beforeHook)']\n"
270277
+
271-
"##teamcity[testFailed timestamp = '1970-01-01T12:00:00.000+0000' duration = '0' message = 'Step failed' details = 'Step failed|n\tthe stack trace|n' name = 'Before']")));
278+
"##teamcity[testFailed timestamp = '1970-01-01T12:00:00.000+0000' duration = '0' message = 'Step failed' details = 'stub exception|n\tthe stack trace|n' name = 'Before(beforeHook)']")));
272279
}
273280

274281
@Test
@@ -284,14 +291,14 @@ void should_print_location_hint_for_java_hooks() {
284291
.withAdditionalPlugins(new TeamCityPlugin(new PrintStream(out)))
285292
.withEventBus(new TimeServiceEventBus(fixed(EPOCH, of("UTC")), UUID::randomUUID))
286293
.withBackendSupplier(new StubBackendSupplier(
287-
singletonList(new StubHookDefinition("com.example.HookDefinition.beforeHook()")),
294+
singletonList(new StubHookDefinition(getAnnotationSourceReference(), BEFORE)),
288295
singletonList(new StubStepDefinition("first step")),
289296
emptyList()))
290297
.build()
291298
.run();
292299

293300
assertThat(out, bytes(containsString("" +
294-
"##teamcity[testStarted timestamp = '1970-01-01T12:00:00.000+0000' locationHint = 'java:test://com.example.HookDefinition/beforeHook' captureStandardOutput = 'true' name = 'Before(beforeHook)']\n")));
301+
"##teamcity[testStarted timestamp = '1970-01-01T12:00:00.000+0000' locationHint = 'java:test://io.cucumber.core.plugin.TeamCityPluginTestStepDefinition/beforeHook' captureStandardOutput = 'true' name = 'Before(beforeHook)']\n")));
295302
}
296303

297304
@Test
@@ -307,14 +314,14 @@ void should_print_location_hint_for_lambda_hooks() {
307314
.withAdditionalPlugins(new TeamCityPlugin(new PrintStream(out)))
308315
.withEventBus(new TimeServiceEventBus(fixed(EPOCH, of("UTC")), UUID::randomUUID))
309316
.withBackendSupplier(new StubBackendSupplier(
310-
singletonList(new StubHookDefinition("com.example.HookDefinition.<init>(HookDefinition.java:12)")),
317+
singletonList(new StubHookDefinition(getStackSourceReference(), BEFORE)),
311318
singletonList(new StubStepDefinition("first step")),
312319
emptyList()))
313320
.build()
314321
.run();
315322

316323
assertThat(out, bytes(containsString("" +
317-
"##teamcity[testStarted timestamp = '1970-01-01T12:00:00.000+0000' locationHint = 'java:test://com.example.HookDefinition/HookDefinition' captureStandardOutput = 'true' name = 'Before(HookDefinition)']\n")));
324+
"##teamcity[testStarted timestamp = '1970-01-01T12:00:00.000+0000' locationHint = 'java:test://io.cucumber.core.plugin.TeamCityPluginTestStepDefinition/TeamCityPluginTestStepDefinition' captureStandardOutput = 'true' name = 'Before(TeamCityPluginTestStepDefinition)']\n")));
318325
}
319326

320327
@Test
@@ -397,4 +404,5 @@ void should_print_comparison_failure_for_failed_assert_equal_with_prefix() {
397404
assertThat(out,
398405
bytes(containsString("expected = 'one value' actual = 'another value' name = 'first step']")));
399406
}
407+
400408
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
package io.cucumber.core.plugin;
2+
3+
import io.cucumber.core.backend.SourceReference;
4+
5+
import java.lang.reflect.Method;
6+
7+
class TeamCityPluginTestStepDefinition {
8+
SourceReference source;
9+
10+
TeamCityPluginTestStepDefinition() {
11+
source = SourceReference.fromStackTraceElement(new Exception().getStackTrace()[0]);
12+
}
13+
14+
public void beforeHook() {
15+
16+
}
17+
18+
static SourceReference getAnnotationSourceReference() {
19+
try {
20+
Method method = TeamCityPluginTestStepDefinition.class.getMethod("beforeHook");
21+
return SourceReference.fromMethod(method);
22+
} catch (NoSuchMethodException e) {
23+
throw new IllegalStateException(e);
24+
}
25+
}
26+
27+
static SourceReference getStackSourceReference() {
28+
return new TeamCityPluginTestStepDefinition().source;
29+
}
30+
}

0 commit comments

Comments
 (0)