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