Skip to content

Commit 09c71de

Browse files
committed
Merge cucumber:master into brasmusson:pretty-formatter-test
Now when cucumber-jvm has reveted to all-steps-first execution, the test case for the PrettyFormatter should pass.
2 parents 39e2432 + 6045294 commit 09c71de

File tree

9 files changed

+576
-88
lines changed

9 files changed

+576
-88
lines changed

History.md

+4-2
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
* [Android] New Cucumber-Android module ([#525](https://github.com/cucumber/cucumber-jvm/pull/525) Maximilian Fellner).
55
* [Build] Deploy maven SNAPSHOT versions from Travis ([#517](https://github.com/cucumber/cucumber-jvm/issues/517), [#528](https://github.com/cucumber/cucumber-jvm/pull/528) Tom Dunstan)
66
* [Core] JUnitFormatter to mark skipped tests as failures in strict mode ([#543](https://github.com/cucumber/cucumber-jvm/pull/543) brasmusson)
7-
* [Core] Always cancel tomeout at the end of a stepdef, even when it fails. ([#540](https://github.com/cucumber/cucumber-jvm/issues/540) irb1s)
7+
* [Core] Always cancel timeout at the end of a stepdef, even when it fails. ([#540](https://github.com/cucumber/cucumber-jvm/issues/540) irb1s)
88
* [Groovy] Updated examples to be more explanatory and groovier syntax ([#537](https://github.com/cucumber/cucumber-jvm/pull/522) Quantoid)
99
* [PicoContainer,Groovy,JRuby,Jython] Not shading maven artifacts any longer. Gem has a shaded jar though. ([#522](https://github.com/cucumber/cucumber-jvm/pull/522) [#518](https://github.com/cucumber/cucumber-jvm/issues/518) Dmytro Chyzhykov, Aslak Hellesøy)
1010
* [Core] The `json-pretty` formatter is gone, and the `json` formatter is pretty!
@@ -15,7 +15,9 @@
1515
* [Core] Bugfix: Generated regex for ? character is incorrect. ([#494](https://github.com/cucumber/cucumber-jvm/issues/494) Aslak Hellesøy)
1616
* [Core] Improve readability with unanchored regular expressions ([#485](https://github.com/cucumber/cucumber-jvm/pull/485), [#466](https://github.com/cucumber/cucumber-jvm/issues/466) Anton)
1717
* [Core] Throw exception when unsupported command line options are used. ([#482](https://github.com/cucumber/cucumber-jvm/pull/482), [#463](https://github.com/cucumber/cucumber-jvm/issues/463) Klaus Bayrhammer)
18-
* [Scala] Release cucumber-scala for the two most recent minro releases (currently 2.9.2 and 2.9.0) ([#432](https://github.com/cucumber/cucumber-jvm/issues/432), [#462](https://github.com/cucumber/cucumber-jvm/pull/462) Chris Turner)
18+
* [Scala] Release cucumber-scala for the two most recent minor releases (currently 2.10.2 and 2.9.3) ([#432](https://github.com/cucumber/cucumber-jvm/issues/432), [#462](https://github.com/cucumber/cucumber-jvm/pull/462) Chris Turner)
19+
* [Core] JUnitFormatter: Fix indentation, hook handling and support all-steps-first execution ([#556](https://github.com/cucumber/cucumber-jvm/pull/556) Björn Rasmusson)
20+
* [Core] Make the PrettyFormatter work by revering to all-steps-first execution ([#557](https://github.com/cucumber/cucumber-jvm/pull/557) Björn Rasmusson)
1921

2022
## [1.1.3](https://github.com/cucumber/cucumber-jvm/compare/v1.1.2...v1.1.3) (2013-03-10)
2123

core/src/main/java/cucumber/runtime/formatter/JUnitFormatter.java

+77-36
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ class JUnitFormatter implements Formatter, Reporter, StrictAware {
4646

4747
public JUnitFormatter(URL out) throws IOException {
4848
this.out = new UTF8OutputStreamWriter(new URLOutputStream(out));
49+
TestCase.treatSkippedAsFailure = false;
4950
try {
5051
doc = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument();
5152
rootElement = doc.createElement("testsuite");
@@ -62,13 +63,15 @@ public void feature(Feature feature) {
6263

6364
@Override
6465
public void background(Background background) {
65-
testCase = new TestCase();
66-
root = testCase.createElement(doc);
66+
if (!isCurrentTestCaseCreatedNameless()) {
67+
testCase = new TestCase();
68+
root = testCase.createElement(doc);
69+
}
6770
}
6871

6972
@Override
7073
public void scenario(Scenario scenario) {
71-
if (testCase != null && testCase.scenario == null) {
74+
if (isCurrentTestCaseCreatedNameless()) {
7275
testCase.scenario = scenario;
7376
} else {
7477
testCase = new TestCase(scenario);
@@ -80,6 +83,10 @@ public void scenario(Scenario scenario) {
8083
increaseAttributeValue(rootElement, "tests");
8184
}
8285

86+
private boolean isCurrentTestCaseCreatedNameless() {
87+
return testCase != null && testCase.scenario == null;
88+
}
89+
8390
@Override
8491
public void step(Step step) {
8592
if (testCase != null) testCase.steps.add(step);
@@ -110,6 +117,10 @@ public void result(Result result) {
110117

111118
@Override
112119
public void before(Match match, Result result) {
120+
if (!isCurrentTestCaseCreatedNameless()) {
121+
testCase = new TestCase();
122+
root = testCase.createElement(doc);
123+
}
113124
handleHook(result);
114125
}
115126

@@ -119,10 +130,8 @@ public void after(Match match, Result result) {
119130
}
120131

121132
private void handleHook(Result result) {
122-
if (result.getStatus().equals(Result.FAILED)) {
123-
testCase.results.add(result);
124-
}
125-
133+
testCase.hookResults.add(result);
134+
testCase.updateElement(doc, root);
126135
}
127136

128137
private void increaseAttributeValue(Element element, String attribute) {
@@ -135,6 +144,7 @@ private void increaseAttributeValue(Element element, String attribute) {
135144

136145
@Override
137146
public void scenarioOutline(ScenarioOutline scenarioOutline) {
147+
testCase = null;
138148
}
139149

140150
@Override
@@ -195,6 +205,7 @@ private TestCase() {
195205
static boolean treatSkippedAsFailure = false;
196206
final List<Step> steps = new ArrayList<Step>();
197207
final List<Result> results = new ArrayList<Result>();
208+
final List<Result> hookResults = new ArrayList<Result>();
198209

199210
private Element createElement(Document doc) {
200211
return doc.createElement("testcase");
@@ -206,49 +217,31 @@ private void writeElement(Document doc, Element tc) {
206217
}
207218

208219
public void updateElement(Document doc, Element tc) {
209-
long totalDurationNanos = 0;
210-
for (Result r : results) {
211-
totalDurationNanos += r.getDuration() == null ? 0 : r.getDuration();
212-
}
213-
214-
double totalDurationSeconds = ((double) totalDurationNanos) / 1000000000;
215-
String time = NUMBER_FORMAT.format(totalDurationSeconds);
216-
tc.setAttribute("time", time);
220+
tc.setAttribute("time", calculateTotalDurationString());
217221

218222
StringBuilder sb = new StringBuilder();
223+
addStepAndResultListing(sb);
219224
Result skipped = null, failed = null;
220-
for (int i = 0; i < steps.size(); i++) {
221-
int length = sb.length();
222-
Result result = results.get(i);
225+
for (Result result : results) {
223226
if ("failed".equals(result.getStatus())) failed = result;
224227
if ("undefined".equals(result.getStatus()) || "pending".equals(result.getStatus())) skipped = result;
225-
sb.append(steps.get(i).getKeyword());
226-
sb.append(steps.get(i).getName());
227-
for (int j = 0; sb.length() - length + j < 140; j++) sb.append(".");
228-
sb.append(result.getStatus());
229-
sb.append("\n");
228+
}
229+
for (Result result : hookResults) {
230+
if (failed == null && "failed".equals(result.getStatus())) failed = result;
230231
}
231232
Element child;
232233
if (failed != null) {
233-
sb.append("\nStackTrace:\n");
234-
StringWriter sw = new StringWriter();
235-
failed.getError().printStackTrace(new PrintWriter(sw));
236-
sb.append(sw.toString());
237-
child = doc.createElement("failure");
238-
child.setAttribute("message", failed.getErrorMessage());
239-
child.appendChild(doc.createCDATASection(sb.toString()));
234+
addStackTrace(sb, failed);
235+
child = createElementWithMessage(doc, sb, "failure", failed.getErrorMessage());
240236
} else if (skipped != null) {
241237
if (treatSkippedAsFailure) {
242-
child = doc.createElement("failure");
243-
child.setAttribute("message", "The scenario has pending or undefined step(s)");
238+
child = createElementWithMessage(doc, sb, "failure", "The scenario has pending or undefined step(s)");
244239
}
245240
else {
246-
child = doc.createElement("skipped");
241+
child = createElement(doc, sb, "skipped");
247242
}
248-
child.appendChild(doc.createCDATASection(sb.toString()));
249243
} else {
250-
child = doc.createElement("system-out");
251-
child.appendChild(doc.createCDATASection(sb.toString()));
244+
child = createElement(doc, sb, "system-out");
252245
}
253246

254247
Node existingChild = tc.getFirstChild();
@@ -259,6 +252,54 @@ public void updateElement(Document doc, Element tc) {
259252
}
260253
}
261254

255+
private String calculateTotalDurationString() {
256+
long totalDurationNanos = 0;
257+
for (Result r : results) {
258+
totalDurationNanos += r.getDuration() == null ? 0 : r.getDuration();
259+
}
260+
for (Result r : hookResults) {
261+
totalDurationNanos += r.getDuration() == null ? 0 : r.getDuration();
262+
}
263+
double totalDurationSeconds = ((double) totalDurationNanos) / 1000000000;
264+
return NUMBER_FORMAT.format(totalDurationSeconds);
265+
}
266+
267+
private void addStepAndResultListing(StringBuilder sb) {
268+
for (int i = 0; i < steps.size(); i++) {
269+
int length = sb.length();
270+
String resultStatus = "not executed";
271+
if (i < results.size()) {
272+
resultStatus = results.get(i).getStatus();
273+
}
274+
sb.append(steps.get(i).getKeyword());
275+
sb.append(steps.get(i).getName());
276+
do {
277+
sb.append(".");
278+
} while (sb.length() - length < 76);
279+
sb.append(resultStatus);
280+
sb.append("\n");
281+
}
282+
}
283+
284+
private void addStackTrace(StringBuilder sb, Result failed) {
285+
sb.append("\nStackTrace:\n");
286+
StringWriter sw = new StringWriter();
287+
failed.getError().printStackTrace(new PrintWriter(sw));
288+
sb.append(sw.toString());
289+
}
290+
291+
private Element createElementWithMessage(Document doc, StringBuilder sb, String elementType, String message) {
292+
Element child = createElement(doc, sb, elementType);
293+
child.setAttribute("message", message);
294+
return child;
295+
}
296+
297+
private Element createElement(Document doc, StringBuilder sb, String elementType) {
298+
Element child = doc.createElement(elementType);
299+
child.appendChild(doc.createCDATASection(sb.toString()));
300+
return child;
301+
}
302+
262303
}
263304

264305
}

core/src/main/java/cucumber/runtime/model/CucumberScenario.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ public void run(Formatter formatter, Reporter reporter, Runtime runtime) {
3737

3838
runBackground(formatter, reporter, runtime);
3939
format(formatter);
40-
runSteps(formatter, reporter, runtime);
40+
runSteps(reporter, runtime);
4141

4242
runtime.runAfterHooks(reporter, tags);
4343
runtime.disposeBackendWorlds();
@@ -46,7 +46,7 @@ public void run(Formatter formatter, Reporter reporter, Runtime runtime) {
4646
private void runBackground(Formatter formatter, Reporter reporter, Runtime runtime) {
4747
if (cucumberBackground != null) {
4848
cucumberBackground.format(formatter);
49-
cucumberBackground.runSteps(formatter, reporter, runtime);
49+
cucumberBackground.runSteps(reporter, runtime);
5050
}
5151
}
5252
}

core/src/main/java/cucumber/runtime/model/CucumberScenarioOutline.java

-1
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,6 @@ public List<CucumberExamples> getCucumberExamplesList() {
3838
@Override
3939
public void run(Formatter formatter, Reporter reporter, Runtime runtime) {
4040
format(formatter);
41-
formatSteps(formatter);
4241
for (CucumberExamples cucumberExamples : cucumberExamplesList) {
4342
cucumberExamples.format(formatter);
4443
List<CucumberScenario> exampleScenarios = cucumberExamples.createExampleScenarios();

core/src/main/java/cucumber/runtime/model/StepContainer.java

+3-7
Original file line numberDiff line numberDiff line change
@@ -29,22 +29,18 @@ public void step(Step step) {
2929

3030
void format(Formatter formatter) {
3131
statement.replay(formatter);
32-
}
33-
34-
void formatSteps(Formatter formatter) {
3532
for (Step step : getSteps()) {
3633
formatter.step(step);
3734
}
3835
}
3936

40-
void runSteps(Formatter formatter, Reporter reporter, Runtime runtime) {
37+
void runSteps(Reporter reporter, Runtime runtime) {
4138
for (Step step : getSteps()) {
42-
runStep(step, formatter, reporter, runtime);
39+
runStep(step, reporter, runtime);
4340
}
4441
}
4542

46-
void runStep(Step step, Formatter formatter, Reporter reporter, Runtime runtime) {
47-
formatter.step(step);
43+
void runStep(Step step, Reporter reporter, Runtime runtime) {
4844
runtime.runStep(cucumberFeature.getUri(), step, reporter, cucumberFeature.getI18n());
4945
}
5046
}

0 commit comments

Comments
 (0)