Skip to content

Commit 2694095

Browse files
brasmussonmpkorstanje
authored andcommitted
[Core] Add TestRunStarted event, let Stats handle the exit code
Add the TestRunStarted event and present the duration between the TestRunStarted and TestRunFinished events in the summary print out. Move the handling of exit code and errors to the summary print out to the Stats class.
1 parent d39527d commit 2694095

File tree

6 files changed

+129
-161
lines changed

6 files changed

+129
-161
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
package cucumber.api.event;
2+
3+
public final class TestRunStarted extends TimeStampedEvent {
4+
5+
public TestRunStarted(Long timeStamp) {
6+
super(timeStamp);
7+
}
8+
}

core/src/main/java/cucumber/runtime/Runtime.java

+5-99
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,7 @@
11
package cucumber.runtime;
22

3-
import cucumber.api.Pending;
4-
import cucumber.api.Result;
53
import cucumber.api.StepDefinitionReporter;
64
import cucumber.api.SummaryPrinter;
7-
import cucumber.api.event.EventHandler;
8-
import cucumber.api.event.TestCaseFinished;
95
import cucumber.api.event.TestRunFinished;
106
import cucumber.api.event.TestStepFinished;
117
import cucumber.runner.EventBus;
@@ -21,7 +17,6 @@
2117
import java.io.IOException;
2218
import java.io.PrintStream;
2319
import java.util.ArrayList;
24-
import java.util.Arrays;
2520
import java.util.Collection;
2621
import java.util.List;
2722
import java.util.Map;
@@ -32,50 +27,17 @@
3227
*/
3328
public class Runtime {
3429

35-
private static final String[] ASSUMPTION_VIOLATED_EXCEPTIONS = {
36-
"org.junit.AssumptionViolatedException",
37-
"org.junit.internal.AssumptionViolatedException"
38-
};
39-
40-
static {
41-
Arrays.sort(ASSUMPTION_VIOLATED_EXCEPTIONS);
42-
}
43-
44-
private static final byte ERRORS = 0x1;
45-
46-
private final Stats stats;
47-
UndefinedStepsTracker undefinedStepsTracker = new UndefinedStepsTracker(); // package private to be avaiable for tests.
30+
final Stats stats; // package private to be avaiable for tests.
31+
private final UndefinedStepsTracker undefinedStepsTracker = new UndefinedStepsTracker();
4832

4933
private final RuntimeOptions runtimeOptions;
5034

51-
private final List<Throwable> errors = new ArrayList<Throwable>();
5235
private final ResourceLoader resourceLoader;
5336
private final ClassLoader classLoader;
5437
private final Runner runner;
5538
private final List<PicklePredicate> filters;
5639
private final EventBus bus;
5740
private final Compiler compiler = new Compiler();
58-
private final EventHandler<TestStepFinished> stepFinishedHandler = new EventHandler<TestStepFinished>() {
59-
@Override
60-
public void receive(TestStepFinished event) {
61-
Result result = event.result;
62-
if (result.getError() != null) {
63-
addError(result.getError());
64-
}
65-
if (event.testStep.isHook()) {
66-
addHookToCounterAndResult(result);
67-
} else {
68-
addStepToCounterAndResult(result);
69-
}
70-
}
71-
};
72-
private final EventHandler<TestCaseFinished> testCaseFinishedHandler = new EventHandler<TestCaseFinished>() {
73-
@Override
74-
public void receive(TestCaseFinished event) {
75-
stats.addScenario(event.result.getStatus(), event.testCase.getScenarioDesignation());
76-
}
77-
};
78-
7941
public Runtime(ResourceLoader resourceLoader, ClassFinder classFinder, ClassLoader classLoader, RuntimeOptions runtimeOptions) {
8042
this(resourceLoader, classLoader, loadBackends(resourceLoader, classFinder), runtimeOptions);
8143
}
@@ -115,8 +77,7 @@ public Runtime(ResourceLoader resourceLoader, ClassLoader classLoader, Collectio
11577
this.filters.add(new LinePredicate(lineFilters));
11678
}
11779

118-
bus.registerHandlerFor(TestStepFinished.class, stepFinishedHandler);
119-
bus.registerHandlerFor(TestCaseFinished.class, testCaseFinishedHandler);
80+
stats.setEventPublisher(bus);
12081
undefinedStepsTracker.setEventPublisher(bus);
12182
runtimeOptions.setEventBus(bus);
12283
}
@@ -126,10 +87,6 @@ private static Collection<? extends Backend> loadBackends(ResourceLoader resourc
12687
return reflections.instantiateSubclasses(Backend.class, "cucumber.runtime", new Class[]{ResourceLoader.class}, new Object[]{resourceLoader});
12788
}
12889

129-
public void addError(Throwable error) {
130-
errors.add(error);
131-
}
132-
13390
/**
13491
* This is the main entry point. Used from CLI, but not from JUnit.
13592
*/
@@ -191,40 +148,11 @@ void printStats(PrintStream out) {
191148
}
192149

193150
public List<Throwable> getErrors() {
194-
return errors;
151+
return stats.getErrors();
195152
}
196153

197154
public byte exitStatus() {
198-
byte result = 0x0;
199-
if (hasErrors() || hasUndefinedOrPendingStepsAndIsStrict()) {
200-
result |= ERRORS;
201-
}
202-
return result;
203-
}
204-
205-
private boolean hasUndefinedOrPendingStepsAndIsStrict() {
206-
return runtimeOptions.isStrict() && hasUndefinedOrPendingSteps();
207-
}
208-
209-
private boolean hasUndefinedOrPendingSteps() {
210-
return hasUndefinedSteps() || hasPendingSteps();
211-
}
212-
213-
private boolean hasUndefinedSteps() {
214-
return undefinedStepsTracker.hasUndefinedSteps();
215-
}
216-
217-
private boolean hasPendingSteps() {
218-
return !errors.isEmpty() && !hasErrors();
219-
}
220-
221-
private boolean hasErrors() {
222-
for (Throwable error : errors) {
223-
if (!isPending(error) && !isAssumptionViolated(error)) {
224-
return true;
225-
}
226-
}
227-
return false;
155+
return stats.exitStatus(runtimeOptions.isStrict());
228156
}
229157

230158
public List<String> getSnippets() {
@@ -235,28 +163,6 @@ public Glue getGlue() {
235163
return runner.getGlue();
236164
}
237165

238-
public static boolean isPending(Throwable t) {
239-
if (t == null) {
240-
return false;
241-
}
242-
return t.getClass().isAnnotationPresent(Pending.class);
243-
}
244-
245-
public static boolean isAssumptionViolated(Throwable t) {
246-
if (t == null) {
247-
return false;
248-
}
249-
return Arrays.binarySearch(ASSUMPTION_VIOLATED_EXCEPTIONS, t.getClass().getName()) >= 0;
250-
}
251-
252-
private void addStepToCounterAndResult(Result result) {
253-
stats.addStep(result);
254-
}
255-
256-
private void addHookToCounterAndResult(Result result) {
257-
stats.addHookTime(result.getDuration());
258-
}
259-
260166
public EventBus getEventBus() {
261167
return bus;
262168
}

core/src/main/java/cucumber/runtime/RuntimeOptions.java

+2
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import cucumber.api.SnippetType;
44
import cucumber.api.StepDefinitionReporter;
55
import cucumber.api.SummaryPrinter;
6+
import cucumber.api.event.TestRunStarted;
67
import cucumber.api.formatter.ColorAware;
78
import cucumber.api.formatter.Formatter;
89
import cucumber.api.formatter.StrictAware;
@@ -308,6 +309,7 @@ private void addKeywordRow(List<List<String>> table, String key, List<String> ke
308309
public List<CucumberFeature> cucumberFeatures(ResourceLoader resourceLoader, EventBus bus) {
309310
List<CucumberFeature> features = load(resourceLoader, featurePaths, System.out);
310311
getPlugins(); // to create the formatter objects
312+
bus.send(new TestRunStarted(bus.getTime()));
311313
for (CucumberFeature feature : features) {
312314
feature.sendTestSourceRead(bus);
313315
}

core/src/main/java/cucumber/runtime/Stats.java

+74-14
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,13 @@
11
package cucumber.runtime;
22

33
import cucumber.api.Result;
4+
import cucumber.api.event.EventHandler;
5+
import cucumber.api.event.EventListener;
6+
import cucumber.api.event.EventPublisher;
7+
import cucumber.api.event.TestCaseFinished;
8+
import cucumber.api.event.TestRunFinished;
9+
import cucumber.api.event.TestRunStarted;
10+
import cucumber.api.event.TestStepFinished;
411
import cucumber.runtime.formatter.AnsiFormats;
512
import cucumber.runtime.formatter.Format;
613
import cucumber.runtime.formatter.Formats;
@@ -13,17 +20,50 @@
1320
import java.util.List;
1421
import java.util.Locale;
1522

16-
class Stats {
23+
class Stats implements EventListener {
1724
public static final long ONE_SECOND = 1000000000;
1825
public static final long ONE_MINUTE = 60 * ONE_SECOND;
26+
private static final byte ERRORS = 0x1;
1927
private SubCounts scenarioSubCounts = new SubCounts();
2028
private SubCounts stepSubCounts = new SubCounts();
29+
private long startTime = 0;
2130
private long totalDuration = 0;
2231
private Formats formats;
2332
private Locale locale;
24-
private List<String> failedScenarios = new ArrayList<String>();
25-
private List<String> pendingScenarios = new ArrayList<String>();
26-
private List<String> undefinedScenarios = new ArrayList<String>();
33+
private final List<String> failedScenarios = new ArrayList<String>();
34+
private final List<String> pendingScenarios = new ArrayList<String>();
35+
private final List<String> undefinedScenarios = new ArrayList<String>();
36+
private final List<Throwable> errors = new ArrayList<Throwable>();
37+
private final EventHandler<TestRunStarted> testRunStartedHandler = new EventHandler<TestRunStarted>() {
38+
@Override
39+
public void receive(TestRunStarted event) {
40+
setStartTime(event.getTimeStamp());
41+
}
42+
};
43+
private final EventHandler<TestStepFinished> stepFinishedHandler = new EventHandler<TestStepFinished>() {
44+
@Override
45+
public void receive(TestStepFinished event) {
46+
Result result = event.result;
47+
if (result.getError() != null) {
48+
addError(result.getError());
49+
}
50+
if (!event.testStep.isHook()) {
51+
addStep(result.getStatus());
52+
}
53+
}
54+
};
55+
private final EventHandler<TestCaseFinished> testCaseFinishedHandler = new EventHandler<TestCaseFinished>() {
56+
@Override
57+
public void receive(TestCaseFinished event) {
58+
addScenario(event.result.getStatus(), event.testCase.getScenarioDesignation());
59+
}
60+
};
61+
private final EventHandler<TestRunFinished> testRunFinishedHandler = new EventHandler<TestRunFinished>() {
62+
@Override
63+
public void receive(TestRunFinished event) {
64+
setFinishTime(event.getTimeStamp());
65+
}
66+
};
2767

2868
public Stats(boolean monochrome) {
2969
this(monochrome, Locale.getDefault());
@@ -38,6 +78,27 @@ public Stats(boolean monochrome, Locale locale) {
3878
}
3979
}
4080

81+
82+
@Override
83+
public void setEventPublisher(EventPublisher publisher) {
84+
publisher.registerHandlerFor(TestRunStarted.class, testRunStartedHandler);
85+
publisher.registerHandlerFor(TestStepFinished.class, stepFinishedHandler);
86+
publisher.registerHandlerFor(TestCaseFinished.class, testCaseFinishedHandler);
87+
publisher.registerHandlerFor(TestRunFinished.class, testRunFinishedHandler);
88+
}
89+
90+
public List<Throwable> getErrors() {
91+
return errors;
92+
}
93+
94+
public byte exitStatus(boolean isStrict) {
95+
byte result = 0x0;
96+
if (!failedScenarios.isEmpty() || (isStrict && (!pendingScenarios.isEmpty() || !undefinedScenarios.isEmpty()))) {
97+
result |= ERRORS;
98+
}
99+
return result;
100+
}
101+
41102
public void printStats(PrintStream out, boolean isStrict) {
42103
printNonZeroResultScenarios(out, isStrict);
43104
if (stepSubCounts.getTotal() == 0) {
@@ -116,21 +177,20 @@ private void printScenarios(PrintStream out, List<String> scenarios, Result.Type
116177
}
117178
}
118179

119-
public void addStep(Result result) {
120-
addResultToSubCount(stepSubCounts, result.getStatus());
121-
addTime(result.getDuration());
180+
void addStep(Result.Type resultStatus) {
181+
addResultToSubCount(stepSubCounts, resultStatus);
122182
}
123183

124-
public void addScenario(Result.Type resultStatus) {
125-
addResultToSubCount(scenarioSubCounts, resultStatus);
184+
private void addError(Throwable error) {
185+
errors.add(error);
126186
}
127187

128-
public void addHookTime(Long duration) {
129-
addTime(duration);
188+
void setStartTime(Long startTime) {
189+
this.startTime = startTime;
130190
}
131191

132-
private void addTime(Long duration) {
133-
totalDuration += duration != null ? duration : 0;
192+
void setFinishTime(Long finishTime) {
193+
this.totalDuration = finishTime - startTime;
134194
}
135195

136196
private void addResultToSubCount(SubCounts subCounts, Result.Type resultStatus) {
@@ -152,7 +212,7 @@ private void addResultToSubCount(SubCounts subCounts, Result.Type resultStatus)
152212
}
153213
}
154214

155-
public void addScenario(Result.Type resultStatus, String scenarioDesignation) {
215+
void addScenario(Result.Type resultStatus, String scenarioDesignation) {
156216
addResultToSubCount(scenarioSubCounts, resultStatus);
157217
switch (resultStatus) {
158218
case FAILED:

0 commit comments

Comments
 (0)