Skip to content

Commit 2c9a79d

Browse files
authored
Merge pull request #1168 from cucumber/ambiguous-result
[Core, JUnit, Android] Add the ambiguous result type.
2 parents b249304 + fba93e7 commit 2c9a79d

File tree

18 files changed

+121
-40
lines changed

18 files changed

+121
-40
lines changed

android/src/main/java/cucumber/runtime/android/AndroidInstrumentationReporter.java

+5-1
Original file line numberDiff line numberDiff line change
@@ -194,6 +194,10 @@ void finishTestCase() {
194194
instrumentation.sendStatus(StatusCodes.ERROR, testResult);
195195
}
196196
break;
197+
case AMBIGUOUS:
198+
testResult.putString(StatusKeys.STACK, getStackTrace(severestResult.getError()));
199+
instrumentation.sendStatus(StatusCodes.ERROR, testResult);
200+
break;
197201
case PENDING:
198202
testResult.putString(StatusKeys.STACK, severestResult.getErrorMessage());
199203
instrumentation.sendStatus(StatusCodes.ERROR, testResult);
@@ -214,7 +218,7 @@ void finishTestCase() {
214218
/**
215219
* Creates a template bundle for reporting the start and end of a test.
216220
*
217-
* @param path of the feature file of the current execution
221+
* @param path of the feature file of the current execution
218222
* @param testCaseName of the test case of the current execution
219223
* @return the new {@link Bundle}
220224
*/

core/src/main/java/cucumber/api/Result.java

+1
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ public static enum Type {
1515
SKIPPED,
1616
PENDING,
1717
UNDEFINED,
18+
AMBIGUOUS,
1819
FAILED;
1920

2021
public static Type fromLowerCaseName(String lowerCaseName) {

core/src/main/java/cucumber/api/TestStep.java

+4
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import cucumber.api.event.TestStepFinished;
44
import cucumber.api.event.TestStepStarted;
55
import cucumber.runner.EventBus;
6+
import cucumber.runtime.AmbiguousStepDefinitionsException;
67
import cucumber.runtime.DefinitionMatch;
78
import cucumber.runtime.UndefinedStepDefinitionException;
89
import gherkin.pickles.Argument;
@@ -92,6 +93,9 @@ private Result.Type mapThrowableToStatus(Throwable t) {
9293
if (t.getClass() == UndefinedStepDefinitionException.class) {
9394
return Result.Type.UNDEFINED;
9495
}
96+
if (t.getClass() == AmbiguousStepDefinitionsException.class) {
97+
return Result.Type.AMBIGUOUS;
98+
}
9599
return Result.Type.FAILED;
96100
}
97101

core/src/main/java/cucumber/runner/Runner.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,7 @@ private void addTestStepsForPickleSteps(List<TestStep> testSteps, PickleEvent pi
121121
match = new UndefinedStepDefinitionMatch(step);
122122
}
123123
} catch (AmbiguousStepDefinitionsException e) {
124-
match = new AmbiguousStepDefinitionsMatch(step, e);
124+
match = new AmbiguousStepDefinitionsMatch(pickleEvent.uri, step, e);
125125
} catch (Throwable t) {
126126
match = new FailedStepInstantiationMatch(pickleEvent.uri, step, t);
127127
}

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

+4-2
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,13 @@
33
import cucumber.api.Scenario;
44
import gherkin.pickles.PickleStep;
55

6+
import java.util.Collections;
7+
68
public class AmbiguousStepDefinitionsMatch extends StepDefinitionMatch {
79
private AmbiguousStepDefinitionsException exception;
810

9-
public AmbiguousStepDefinitionsMatch(PickleStep step, AmbiguousStepDefinitionsException e) {
10-
super(null, new NoStepDefinition(), null, step, null);
11+
public AmbiguousStepDefinitionsMatch(String uri, PickleStep step, AmbiguousStepDefinitionsException e) {
12+
super(Collections.<Argument>emptyList(), new NoStepDefinition(), uri, step, null);
1113
this.exception = e;
1214
}
1315

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

+1-1
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
import static java.util.Arrays.asList;
2121

2222
public class ScenarioImpl implements Scenario {
23-
private static final List<Result.Type> SEVERITY = asList(Result.Type.PASSED, Result.Type.SKIPPED, Result.Type.PENDING, Result.Type.UNDEFINED, Result.Type.FAILED);
23+
private static final List<Result.Type> SEVERITY = asList(Result.Type.PASSED, Result.Type.SKIPPED, Result.Type.PENDING, Result.Type.UNDEFINED, Result.Type.AMBIGUOUS, Result.Type.FAILED);
2424
private final List<Result> stepResults = new ArrayList<Result>();
2525
private final List<PickleTag> tags;
2626
private final String uri;

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

+11-1
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ class Stats {
2222
private Formats formats;
2323
private Locale locale;
2424
private List<String> failedScenarios = new ArrayList<String>();
25+
private List<String> ambiguousScenarios = new ArrayList<String>();
2526
private List<String> pendingScenarios = new ArrayList<String>();
2627
private List<String> undefinedScenarios = new ArrayList<String>();
2728

@@ -67,6 +68,7 @@ private void printScenarioCounts(PrintStream out) {
6768
private void printSubCounts(PrintStream out, SubCounts subCounts) {
6869
boolean addComma = false;
6970
addComma = printSubCount(out, subCounts.failed, Result.Type.FAILED, addComma);
71+
addComma = printSubCount(out, subCounts.ambiguous, Result.Type.AMBIGUOUS, addComma);
7072
addComma = printSubCount(out, subCounts.skipped, Result.Type.SKIPPED, addComma);
7173
addComma = printSubCount(out, subCounts.pending, Result.Type.PENDING, addComma);
7274
addComma = printSubCount(out, subCounts.undefined, Result.Type.UNDEFINED, addComma);
@@ -93,6 +95,7 @@ private void printDuration(PrintStream out) {
9395

9496
private void printNonZeroResultScenarios(PrintStream out, boolean isStrict) {
9597
printScenarios(out, failedScenarios, Result.Type.FAILED);
98+
printScenarios(out, ambiguousScenarios, Result.Type.AMBIGUOUS);
9699
if (isStrict) {
97100
printScenarios(out, pendingScenarios, Result.Type.PENDING);
98101
printScenarios(out, undefinedScenarios, Result.Type.UNDEFINED);
@@ -138,6 +141,9 @@ private void addResultToSubCount(SubCounts subCounts, Result.Type resultStatus)
138141
case FAILED:
139142
subCounts.failed++;
140143
break;
144+
case AMBIGUOUS:
145+
subCounts.ambiguous++;
146+
break;
141147
case PENDING:
142148
subCounts.pending++;
143149
break;
@@ -158,6 +164,9 @@ public void addScenario(Result.Type resultStatus, String scenarioDesignation) {
158164
case FAILED:
159165
failedScenarios.add(scenarioDesignation);
160166
break;
167+
case AMBIGUOUS:
168+
ambiguousScenarios.add(scenarioDesignation);
169+
break;
161170
case PENDING:
162171
pendingScenarios.add(scenarioDesignation);
163172
break;
@@ -172,12 +181,13 @@ public void addScenario(Result.Type resultStatus, String scenarioDesignation) {
172181
class SubCounts {
173182
public int passed = 0;
174183
public int failed = 0;
184+
public int ambiguous = 0;
175185
public int skipped = 0;
176186
public int pending = 0;
177187
public int undefined = 0;
178188

179189
public int getTotal() {
180-
return passed + failed + skipped + pending + undefined;
190+
return passed + failed + ambiguous + skipped + pending + undefined;
181191
}
182192
}
183193
}

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

+2
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@ public class AnsiFormats implements Formats {
1515
put("executing_arg", new ColorFormat(AnsiEscapes.GREY, AnsiEscapes.INTENSITY_BOLD));
1616
put("failed", new ColorFormat(AnsiEscapes.RED));
1717
put("failed_arg", new ColorFormat(AnsiEscapes.RED, AnsiEscapes.INTENSITY_BOLD));
18+
put("ambiguous", new ColorFormat(AnsiEscapes.RED));
19+
put("ambiguous_arg", new ColorFormat(AnsiEscapes.RED, AnsiEscapes.INTENSITY_BOLD));
1820
put("passed", new ColorFormat(AnsiEscapes.GREEN));
1921
put("passed_arg", new ColorFormat(AnsiEscapes.GREEN, AnsiEscapes.INTENSITY_BOLD));
2022
put("outline", new ColorFormat(AnsiEscapes.CYAN));

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

+3
Original file line numberDiff line numberDiff line change
@@ -250,6 +250,9 @@ public void addTestCaseElement(Document doc, Element tc, Result result) {
250250
if (result.is(Result.Type.FAILED)) {
251251
addStackTrace(sb, result);
252252
child = createElementWithMessage(doc, sb, "failure", result.getErrorMessage());
253+
} else if (result.is(Result.Type.AMBIGUOUS)) {
254+
addStackTrace(sb, result);
255+
child = createElementWithMessage(doc, sb, "failure", result.getErrorMessage());
253256
} else if (result.is(Result.Type.PENDING) || result.is(Result.Type.UNDEFINED)) {
254257
if (treatConditionallySkippedAsFailure) {
255258
child = createElementWithMessage(doc, sb, "failure", "The scenario has pending or undefined step(s)");

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

+2
Original file line numberDiff line numberDiff line change
@@ -21,13 +21,15 @@ class ProgressFormatter implements Formatter, ColorAware {
2121
put(Result.Type.PENDING, 'P');
2222
put(Result.Type.SKIPPED, '-');
2323
put(Result.Type.FAILED, 'F');
24+
put(Result.Type.AMBIGUOUS, 'A');
2425
}};
2526
private static final Map<Result.Type, AnsiEscapes> ANSI_ESCAPES = new HashMap<Result.Type, AnsiEscapes>() {{
2627
put(Result.Type.PASSED, AnsiEscapes.GREEN);
2728
put(Result.Type.UNDEFINED, AnsiEscapes.YELLOW);
2829
put(Result.Type.PENDING, AnsiEscapes.YELLOW);
2930
put(Result.Type.SKIPPED, AnsiEscapes.CYAN);
3031
put(Result.Type.FAILED, AnsiEscapes.RED);
32+
put(Result.Type.AMBIGUOUS, AnsiEscapes.RED);
3133
}};
3234

3335
private final NiceAppendable out;

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

+1-1
Original file line numberDiff line numberDiff line change
@@ -226,7 +226,7 @@ public void finish(Document doc, Element element) {
226226
Result skipped = null;
227227
Result failed = null;
228228
for (Result result : results) {
229-
if (result.is(Result.Type.FAILED)) {
229+
if (result.is(Result.Type.FAILED) || result.is(Result.Type.AMBIGUOUS)) {
230230
failed = result;
231231
}
232232
if (result.is(Result.Type.UNDEFINED) || result.is(Result.Type.PENDING)) {

core/src/test/java/cucumber/runtime/AmbiguousStepDefinitionMatchsTest.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
public class AmbiguousStepDefinitionMatchsTest {
1212
public static final String ENGLISH = "en";
1313
public final AmbiguousStepDefinitionsException e = mock(AmbiguousStepDefinitionsException.class);
14-
public final AmbiguousStepDefinitionsMatch match = new AmbiguousStepDefinitionsMatch(mock(PickleStep.class), e);
14+
public final AmbiguousStepDefinitionsMatch match = new AmbiguousStepDefinitionsMatch("uri", mock(PickleStep.class), e);
1515

1616
@Test
1717
public void throws_ambiguous_step_definitions_exception_when_run() {

core/src/test/java/cucumber/runtime/RuntimeTest.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -302,8 +302,8 @@ public void should_add_ambiguous_match_as_failed_result_to_the_summary_counter()
302302
runtime.printStats(new PrintStream(baos));
303303

304304
assertThat(baos.toString(), containsString(String.format(""+
305-
"1 Scenarios (1 failed)%n" +
306-
"1 Steps (1 failed)%n")));
305+
"1 Scenarios (1 ambiguous)%n" +
306+
"1 Steps (1 ambiguous)%n")));
307307
}
308308

309309
@Test

core/src/test/java/cucumber/runtime/StatsTest.java

+24-11
Original file line numberDiff line numberDiff line change
@@ -48,43 +48,46 @@ public void should_only_print_sub_counts_if_not_zero() {
4848
}
4949

5050
@Test
51-
public void should_print_sub_counts_in_order_failed_skipped_pending_undefined_passed() {
51+
public void should_print_sub_counts_in_order_failed_ambiguous_skipped_pending_undefined_passed() {
5252
Stats counter = createMonochromeSummaryCounter();
5353
ByteArrayOutputStream baos = new ByteArrayOutputStream();
5454

5555
addOneStepScenario(counter, Result.Type.PASSED);
5656
addOneStepScenario(counter, Result.Type.FAILED);
57+
addOneStepScenario(counter, Result.Type.AMBIGUOUS);
5758
addOneStepScenario(counter, Result.Type.PENDING);
5859
addOneStepScenario(counter, Result.Type.UNDEFINED);
5960
addOneStepScenario(counter, Result.Type.SKIPPED);
6061
counter.printStats(new PrintStream(baos), isStrict(false));
6162

6263
assertThat(baos.toString(), containsString(String.format("" +
63-
"5 Scenarios (1 failed, 1 skipped, 1 pending, 1 undefined, 1 passed)%n" +
64-
"5 Steps (1 failed, 1 skipped, 1 pending, 1 undefined, 1 passed)%n")));
64+
"6 Scenarios (1 failed, 1 ambiguous, 1 skipped, 1 pending, 1 undefined, 1 passed)%n" +
65+
"6 Steps (1 failed, 1 ambiguous, 1 skipped, 1 pending, 1 undefined, 1 passed)%n")));
6566
}
6667

6768
@Test
68-
public void should_print_sub_counts_in_order_failed_skipped_undefined_passed_in_color() {
69+
public void should_print_sub_counts_in_order_failed_ambiguous_skipped_undefined_passed_in_color() {
6970
Stats counter = createColorSummaryCounter();
7071
ByteArrayOutputStream baos = new ByteArrayOutputStream();
7172

7273
addOneStepScenario(counter, Result.Type.PASSED);
7374
addOneStepScenario(counter, Result.Type.FAILED);
75+
addOneStepScenario(counter, Result.Type.AMBIGUOUS);
7476
addOneStepScenario(counter, Result.Type.PENDING);
7577
addOneStepScenario(counter, Result.Type.UNDEFINED);
7678
addOneStepScenario(counter, Result.Type.SKIPPED);
7779
counter.printStats(new PrintStream(baos), isStrict(false));
7880

79-
String colorSubCounts =
81+
String colorSubCounts = "" +
8082
AnsiEscapes.RED + "1 failed" + AnsiEscapes.RESET + ", " +
83+
AnsiEscapes.RED + "1 ambiguous" + AnsiEscapes.RESET + ", " +
8184
AnsiEscapes.CYAN + "1 skipped" + AnsiEscapes.RESET + ", " +
8285
AnsiEscapes.YELLOW + "1 pending" + AnsiEscapes.RESET + ", " +
8386
AnsiEscapes.YELLOW + "1 undefined" + AnsiEscapes.RESET + ", " +
8487
AnsiEscapes.GREEN + "1 passed" + AnsiEscapes.RESET;
8588
assertThat(baos.toString(), containsString(String.format("" +
86-
"5 Scenarios (" + colorSubCounts + ")%n" +
87-
"5 Steps (" + colorSubCounts + ")%n")));
89+
"6 Scenarios (" + colorSubCounts + ")%n" +
90+
"6 Steps (" + colorSubCounts + ")%n")));
8891
}
8992

9093
@Test
@@ -155,12 +158,14 @@ public void should_use_locale_for_decimal_separator() {
155158
}
156159

157160
@Test
158-
public void should_print_failed_scenarios() {
161+
public void should_print_failed_ambiguous_scenarios() {
159162
Stats counter = createMonochromeSummaryCounter();
160163
ByteArrayOutputStream baos = new ByteArrayOutputStream();
161164

162165
counter.addStep(createResultWithStatus(Result.Type.FAILED));
163166
counter.addScenario(Result.Type.FAILED, "path/file.feature:3 # Scenario: scenario_name");
167+
counter.addStep(createResultWithStatus(Result.Type.AMBIGUOUS));
168+
counter.addScenario(Result.Type.AMBIGUOUS, "path/file.feature:3 # Scenario: scenario_name");
164169
counter.addStep(createResultWithStatus(Result.Type.UNDEFINED));
165170
counter.addScenario(Result.Type.UNDEFINED, "path/file.feature:3 # Scenario: scenario_name");
166171
counter.addStep(createResultWithStatus(Result.Type.PENDING));
@@ -171,16 +176,21 @@ public void should_print_failed_scenarios() {
171176
"Failed scenarios:%n" +
172177
"path/file.feature:3 # Scenario: scenario_name%n" +
173178
"%n" +
174-
"3 Scenarios")));
179+
"Ambiguous scenarios:%n" +
180+
"path/file.feature:3 # Scenario: scenario_name%n" +
181+
"%n" +
182+
"4 Scenarios")));
175183
}
176184

177185
@Test
178-
public void should_print_failed_pending_undefined_scenarios_if_strict() {
186+
public void should_print_failed_ambiguous_pending_undefined_scenarios_if_strict() {
179187
Stats counter = createMonochromeSummaryCounter();
180188
ByteArrayOutputStream baos = new ByteArrayOutputStream();
181189

182190
counter.addStep(createResultWithStatus(Result.Type.FAILED));
183191
counter.addScenario(Result.Type.FAILED, "path/file.feature:3 # Scenario: scenario_name");
192+
counter.addStep(createResultWithStatus(Result.Type.AMBIGUOUS));
193+
counter.addScenario(Result.Type.AMBIGUOUS, "path/file.feature:3 # Scenario: scenario_name");
184194
counter.addStep(createResultWithStatus(Result.Type.UNDEFINED));
185195
counter.addScenario(Result.Type.UNDEFINED, "path/file.feature:3 # Scenario: scenario_name");
186196
counter.addStep(createResultWithStatus(Result.Type.PENDING));
@@ -191,13 +201,16 @@ public void should_print_failed_pending_undefined_scenarios_if_strict() {
191201
"Failed scenarios:%n" +
192202
"path/file.feature:3 # Scenario: scenario_name%n" +
193203
"%n" +
204+
"Ambiguous scenarios:%n" +
205+
"path/file.feature:3 # Scenario: scenario_name%n" +
206+
"%n" +
194207
"Pending scenarios:%n" +
195208
"path/file.feature:3 # Scenario: scenario_name%n" +
196209
"%n" +
197210
"Undefined scenarios:%n" +
198211
"path/file.feature:3 # Scenario: scenario_name%n" +
199212
"%n" +
200-
"3 Scenarios")));
213+
"4 Scenarios")));
201214
}
202215

203216
private void addOneStepScenario(Stats counter, Result.Type status) {

core/src/test/java/cucumber/runtime/TestHelper.java

+16
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,8 @@ public static Result result(Result.Type status) {
6969
switch (status) {
7070
case FAILED:
7171
return result(status, mockAssertionFailedError());
72+
case AMBIGUOUS:
73+
return result(status, mockAmbiguousStepDefinitionException());
7274
case PENDING:
7375
return result(status, new PendingException());
7476
default:
@@ -251,6 +253,20 @@ public Object answer(InvocationOnMock invocation) throws Throwable {
251253
return error;
252254
}
253255

256+
private static AmbiguousStepDefinitionsException mockAmbiguousStepDefinitionException() {
257+
AmbiguousStepDefinitionsException exception = mock(AmbiguousStepDefinitionsException.class);
258+
Answer<Object> printStackTraceHandler = new Answer<Object>() {
259+
@Override
260+
public Object answer(InvocationOnMock invocation) throws Throwable {
261+
PrintWriter writer = (PrintWriter) invocation.getArguments()[0];
262+
writer.print("the stack trace");
263+
return null;
264+
}
265+
};
266+
doAnswer(printStackTraceHandler).when(exception).printStackTrace((PrintWriter) any());
267+
return exception;
268+
}
269+
254270
public static SimpleEntry<String, Result> hookEntry(String type, Result result) {
255271
return new SimpleEntry<String, Result>(type, result);
256272
}

junit/src/main/java/cucumber/runtime/junit/JUnitReporter.java

+6
Original file line numberDiff line numberDiff line change
@@ -127,9 +127,13 @@ void handleStepResult(TestStep testStep, Result result) {
127127
stepErrors.add(new UndefinedThrowable(testStep.getStepText()));
128128
addFailureOrFailedAssumptionDependingOnStrictMode(stepNotifier, error);
129129
break;
130+
case AMBIGUOUS:
130131
case FAILED:
131132
stepErrors.add(error);
132133
stepNotifier.addFailure(error);
134+
break;
135+
default:
136+
throw new IllegalStateException("Unexpected result status: " + result.getStatus());
133137
}
134138
stepNotifier.fireTestFinished();
135139
}
@@ -159,10 +163,12 @@ void handleTestCaseResult(Result result) {
159163
addFailureOrFailedAssumptionDependingOnStrictMode(pickleRunnerNotifier, error);
160164
}
161165
break;
166+
case AMBIGUOUS:
162167
case FAILED:
163168
for (Throwable error : stepErrors) {
164169
pickleRunnerNotifier.addFailure(error);
165170
}
171+
break;
166172
}
167173
pickleRunnerNotifier.fireTestFinished();
168174
}

0 commit comments

Comments
 (0)