1
1
package io .cucumber .core .plugin ;
2
2
3
3
import io .cucumber .core .feature .FeatureWithLines ;
4
+ import io .cucumber .messages .types .Envelope ;
5
+ import io .cucumber .messages .types .TestCaseFinished ;
6
+ import io .cucumber .messages .types .TestStepResult ;
7
+ import io .cucumber .messages .types .TestStepResultStatus ;
4
8
import io .cucumber .plugin .ConcurrentEventListener ;
5
9
import io .cucumber .plugin .event .EventPublisher ;
6
- import io .cucumber .plugin .event .TestCase ;
7
- import io .cucumber .plugin .event .TestCaseFinished ;
8
- import io .cucumber .plugin .event .TestRunFinished ;
10
+ import io .cucumber .query .Query ;
11
+ import io .cucumber .query .Repository ;
9
12
10
13
import java .io .File ;
11
14
import java .io .OutputStream ;
15
+ import java .io .OutputStreamWriter ;
16
+ import java .io .PrintWriter ;
12
17
import java .net .URI ;
13
18
import java .net .URISyntaxException ;
14
- import java .util . ArrayList ;
15
- import java .util .Collection ;
19
+ import java .nio . charset . StandardCharsets ;
20
+ import java .util .HashSet ;
16
21
import java .util .LinkedHashMap ;
17
22
import java .util .Map ;
23
+ import java .util .Set ;
18
24
19
25
import static io .cucumber .core .feature .FeatureWithLines .create ;
26
+ import static io .cucumber .query .Repository .RepositoryFeature .INCLUDE_GHERKIN_DOCUMENT ;
27
+ import static java .util .Objects .requireNonNull ;
20
28
21
29
/**
22
30
* Formatter for reporting all failed test cases and print their locations
23
31
* Failed means: results that make the exit code non-zero.
24
32
*/
25
33
public final class RerunFormatter implements ConcurrentEventListener {
26
34
27
- private final UTF8PrintWriter out ;
28
- private final Map <URI , Collection <Integer >> featureAndFailedLinesMapping = new LinkedHashMap <>();
35
+ private final PrintWriter writer ;
36
+ private final Map <String , Set <Integer >> featureAndFailedLinesMapping = new LinkedHashMap <>();
37
+ private final Repository repository = Repository .builder ()
38
+ .feature (INCLUDE_GHERKIN_DOCUMENT , true )
39
+ .build ();
40
+ private final Query query = new Query (repository );
29
41
30
42
public RerunFormatter (OutputStream out ) {
31
- this .out = new UTF8PrintWriter (out );
43
+ this .writer = createPrintWriter (out );
32
44
}
33
45
34
- @ Override
35
- public void setEventPublisher (EventPublisher publisher ) {
36
- publisher .registerHandlerFor (TestCaseFinished .class , this ::handleTestCaseFinished );
37
- publisher .registerHandlerFor (TestRunFinished .class , event -> finishReport ());
38
- }
39
-
40
- private void handleTestCaseFinished (TestCaseFinished event ) {
41
- if (!event .getResult ().getStatus ().isOk ()) {
42
- recordTestFailed (event .getTestCase ());
43
- }
44
- }
45
-
46
- private void finishReport () {
47
- for (Map .Entry <URI , Collection <Integer >> entry : featureAndFailedLinesMapping .entrySet ()) {
48
- FeatureWithLines featureWithLines = create (relativize (entry .getKey ()), entry .getValue ());
49
- out .println (featureWithLines .toString ());
50
- }
51
-
52
- out .close ();
53
- }
54
-
55
- private void recordTestFailed (TestCase testCase ) {
56
- URI uri = testCase .getUri ();
57
- Collection <Integer > failedTestCaseLines = getFailedTestCaseLines (uri );
58
- failedTestCaseLines .add (testCase .getLocation ().getLine ());
59
- }
60
-
61
- private Collection <Integer > getFailedTestCaseLines (URI uri ) {
62
- return featureAndFailedLinesMapping .computeIfAbsent (uri , k -> new ArrayList <>());
46
+ private static PrintWriter createPrintWriter (OutputStream out ) {
47
+ return new PrintWriter (
48
+ new OutputStreamWriter (
49
+ requireNonNull (out ),
50
+ StandardCharsets .UTF_8 ));
63
51
}
64
52
65
53
static URI relativize (URI uri ) {
@@ -79,4 +67,46 @@ static URI relativize(URI uri) {
79
67
throw new IllegalArgumentException (e .getMessage (), e );
80
68
}
81
69
}
70
+
71
+ @ Override
72
+ public void setEventPublisher (EventPublisher publisher ) {
73
+ publisher .registerHandlerFor (Envelope .class , event -> {
74
+ repository .update (event );
75
+ event .getTestCaseFinished ().ifPresent (this ::handleTestCaseFinished );
76
+ event .getTestRunFinished ().ifPresent (testRunFinished -> finishReport ());
77
+ });
78
+ }
79
+
80
+ private void handleTestCaseFinished (TestCaseFinished event ) {
81
+ TestStepResultStatus testStepResultStatus = query .findMostSevereTestStepResultBy (event )
82
+ .map (TestStepResult ::getStatus )
83
+ // By definition
84
+ .orElse (TestStepResultStatus .PASSED );
85
+
86
+ if (testStepResultStatus == TestStepResultStatus .PASSED
87
+ || testStepResultStatus == TestStepResultStatus .SKIPPED ) {
88
+ return ;
89
+ }
90
+
91
+ query .findPickleBy (event ).ifPresent (pickle -> {
92
+ Set <Integer > lines = featureAndFailedLinesMapping
93
+ .computeIfAbsent (pickle .getUri (), s -> new HashSet <>());
94
+ query .findLocationOf (pickle ).ifPresent (location -> {
95
+ // TODO: Messages are silly
96
+ lines .add ((int ) (long ) location .getLine ());
97
+ });
98
+ });
99
+ }
100
+
101
+ private void finishReport () {
102
+ for (Map .Entry <String , Set <Integer >> entry : featureAndFailedLinesMapping .entrySet ()) {
103
+ String key = entry .getKey ();
104
+ // TODO: Should these be relative?
105
+ FeatureWithLines featureWithLines = create (relativize (URI .create (key )), entry .getValue ());
106
+ writer .println (featureWithLines );
107
+ }
108
+
109
+ writer .close ();
110
+ }
111
+
82
112
}
0 commit comments