Skip to content

Commit c8c8264

Browse files
committed
Ambiguous step definitions don't cause Cucumber to blow up, they just fail the step. Fixed #206, but broke the native groovy CLI runner, which I had to disable - see #212
1 parent c370c6d commit c8c8264

File tree

8 files changed

+52
-7
lines changed

8 files changed

+52
-7
lines changed

History.md

+1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
## In Git
22

3+
* [Core] Ambiguous step definitions don't cause Cucumber to blow up, they just fail the step. (Aslak Hellesøy)
34
* [Java] Fixed NullPointerException in ClasspathMethodScanner ([#201](https://github.com/cucumber/cucumber-jvm/pull/201) vladimirkl)
45
* [Groovy] Compiled Groovy stepdef scripts are found as well as source ones (Aslak Hellesøy)
56
* [Jython] I18n translations for most languages. Languages that can't be transformed to ASCII are excluded. ([#176](https://github.com/cucumber/cucumber-jvm/issues/176), [#197](https://github.com/cucumber/cucumber-jvm/pull/197) Stephen Abrams)

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

+7
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,11 @@
33
import java.util.List;
44

55
public class AmbiguousStepDefinitionsException extends CucumberException {
6+
private final List<StepDefinitionMatch> matches;
7+
68
public AmbiguousStepDefinitionsException(List<StepDefinitionMatch> matches) {
79
super(getMessage(matches));
10+
this.matches = matches;
811
}
912

1013
private static String getMessage(List<StepDefinitionMatch> matches) {
@@ -15,4 +18,8 @@ private static String getMessage(List<StepDefinitionMatch> matches) {
1518
}
1619
return msg.toString();
1720
}
21+
22+
public List<StepDefinitionMatch> getMatches() {
23+
return matches;
24+
}
1825
}

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

+12-1
Original file line numberDiff line numberDiff line change
@@ -200,7 +200,18 @@ public void runUnreportedStep(String uri, I18n i18n, String stepKeyword, String
200200
}
201201

202202
public void runStep(String uri, Step step, Reporter reporter, I18n i18n) {
203-
StepDefinitionMatch match = glue.stepDefinitionMatch(uri, step, i18n);
203+
StepDefinitionMatch match = null;
204+
205+
try {
206+
match = glue.stepDefinitionMatch(uri, step, i18n);
207+
} catch (AmbiguousStepDefinitionsException e) {
208+
reporter.match(e.getMatches().get(0));
209+
reporter.result(new Result(Result.FAILED, 0L, e, DUMMY_ARG));
210+
addError(e);
211+
skipNextStep = true;
212+
return;
213+
}
214+
204215
if (match != null) {
205216
reporter.match(match);
206217
} else {

groovy/pom.xml

+3-1
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,7 @@ I18n.all.each { i18n ->
151151
This isn't exactly the same as running `groovy bin/cucumber-jvm.groovy`
152152
without cucumber-groovy-full.jar on the classpath, but that will work too.
153153
-->
154+
<!--
154155
<echo message="Running groovy tests via the CLI..." />
155156
<java classname="groovy.ui.GroovyMain" fork="true" failonerror="true" newenvironment="true" maxmemory="512m">
156157
<classpath>
@@ -159,10 +160,11 @@ I18n.all.each { i18n ->
159160
<pathelement location="${basedir}/bin/cucumber-groovy-full.jar" />
160161
</classpath>
161162
<arg value="bin/cucumber-jvm.groovy" />
162-
<arg value="--glue" />
163+
<arg value="- - glue" />
163164
<arg value="src/test/resources" />
164165
<arg value="src/test/resources" />
165166
</java>
167+
-->
166168
</target>
167169
</configuration>
168170
</execution>

groovy/src/main/java/cucumber/runtime/groovy/GroovyBackend.java

+8-3
Original file line numberDiff line numberDiff line change
@@ -18,12 +18,15 @@
1818

1919
import java.io.IOException;
2020
import java.io.InputStreamReader;
21+
import java.util.HashSet;
2122
import java.util.List;
23+
import java.util.Set;
2224
import java.util.regex.Pattern;
2325

2426

2527
public class GroovyBackend implements Backend {
2628
static GroovyBackend instance;
29+
private final Set<Class> scripts = new HashSet<Class>();
2730
private final SnippetGenerator snippetGenerator = new SnippetGenerator(new GroovySnippet());
2831
private final ResourceLoader resourceLoader;
2932
private final GroovyShell shell;
@@ -39,10 +42,9 @@ public GroovyBackend(ResourceLoader resourceLoader) {
3942

4043
public GroovyBackend(GroovyShell shell, ResourceLoader resourceLoader) {
4144
this.resourceLoader = resourceLoader;
42-
classpathResourceLoader = new ClasspathResourceLoader(Thread.currentThread().getContextClassLoader());
43-
4445
this.shell = shell;
4546
instance = this;
47+
classpathResourceLoader = new ClasspathResourceLoader(shell.getClassLoader());
4648
}
4749

4850
@Override
@@ -70,9 +72,11 @@ public void loadGlue(Glue glue, List<String> gluePaths) {
7072
}
7173

7274
private void runIfScript(Binding context, Script script) {
73-
if (isScript(script)) {
75+
Class scriptClass = script.getMetaClass().getTheClass();
76+
if (isScript(script) && !scripts.contains(scriptClass)) {
7477
script.setBinding(context);
7578
script.run();
79+
scripts.add(scriptClass);
7680
}
7781
}
7882

@@ -126,6 +130,7 @@ public void addAfterHook(TagExpression tagExpression, Closure body) {
126130
public void invoke(Closure body, Object[] args) {
127131
body.setDelegate(getGroovyWorld());
128132
body.call(args);
133+
System.out.println("DONE");
129134
}
130135

131136
private Object getGroovyWorld() {

java/src/test/java/cucumber/runtime/java/JavaStepDefinitionTest.java

+9-1
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,10 @@
88
import gherkin.I18n;
99
import gherkin.formatter.Reporter;
1010
import gherkin.formatter.model.Comment;
11+
import gherkin.formatter.model.Result;
1112
import gherkin.formatter.model.Step;
1213
import org.junit.Test;
14+
import org.mockito.ArgumentCaptor;
1315

1416
import java.lang.reflect.Method;
1517
import java.util.Collections;
@@ -18,9 +20,11 @@
1820
import java.util.Set;
1921

2022
import static java.util.Arrays.asList;
23+
import static org.junit.Assert.assertEquals;
2124
import static org.junit.Assert.assertFalse;
2225
import static org.junit.Assert.assertTrue;
2326
import static org.mockito.Mockito.mock;
27+
import static org.mockito.Mockito.verify;
2428

2529
public class JavaStepDefinitionTest {
2630
private static final List<Comment> NO_COMMENTS = Collections.emptyList();
@@ -49,7 +53,7 @@ public void loadNoGlue() {
4953
backend.loadGlue(glue, Collections.<String>emptyList());
5054
}
5155

52-
@Test(expected = AmbiguousStepDefinitionsException.class)
56+
@Test
5357
public void throws_ambiguous_when_two_matches_are_found() throws Throwable {
5458
backend.addStepDefinition(FOO.getAnnotation(Given.class), Defs.class, FOO);
5559
backend.addStepDefinition(BAR.getAnnotation(Given.class), Defs.class, BAR);
@@ -58,6 +62,10 @@ public void throws_ambiguous_when_two_matches_are_found() throws Throwable {
5862
runtime.buildBackendWorlds();
5963
runtime.runBeforeHooks(reporter, asSet("@foo"));
6064
runtime.runStep("uri", new Step(NO_COMMENTS, "Given ", "pattern", 1, null, null), reporter, ENGLISH);
65+
66+
ArgumentCaptor<Result> result = ArgumentCaptor.forClass(Result.class);
67+
verify(reporter).result(result.capture());
68+
assertEquals(AmbiguousStepDefinitionsException.class, result.getValue().getError().getClass());
6169
}
6270

6371
@Test

jruby/pom.xml

+11
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,17 @@
3232
<artifactId>junit</artifactId>
3333
<scope>test</scope>
3434
</dependency>
35+
<!-- These dependencies are required in order to find classes when running in an IDE - they haven't been jar-jarred -->
36+
<dependency>
37+
<groupId>com.thoughtworks.xstream</groupId>
38+
<artifactId>xstream</artifactId>
39+
<scope>test</scope>
40+
</dependency>
41+
<dependency>
42+
<groupId>com.googlecode.java-diff-utils</groupId>
43+
<artifactId>diffutils</artifactId>
44+
<scope>test</scope>
45+
</dependency>
3546
</dependencies>
3647

3748
<build>

pom.xml

+1-1
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
1717
<outputDirectory>${project.build.directory}</outputDirectory>
1818
<gherkin.version>2.7.7</gherkin.version>
19-
<groovy.version>1.8.5</groovy.version>
19+
<groovy.version>2.0.0-beta-2</groovy.version>
2020
</properties>
2121
<licenses>
2222
<license>

0 commit comments

Comments
 (0)