Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

We’re showing branches in this repository, but you can also compare across forks.

base fork: cucumber/cucumber-jvm
...
head fork: cucumber/cucumber-jvm
  • 14 commits
  • 48 files changed
  • 6 commit comments
  • 2 contributors
Showing with 358 additions and 98 deletions.
  1. +11 −2 History.md
  2. +7 −6 README.md
  3. +1 −1  clojure/pom.xml
  4. +1 −1  core/pom.xml
  5. +6 −12 core/src/main/java/cucumber/runtime/RuntimeOptions.java
  6. +26 −7 core/src/main/java/cucumber/runtime/StepDefinitionMatch.java
  7. +3 −0  core/src/main/java/cucumber/table/TableConverter.java
  8. +83 −1 core/src/test/java/cucumber/runtime/StepDefinitionMatchTest.java
  9. +19 −0 core/src/test/java/cucumber/table/ToDataTableTest.java
  10. +1 −1  examples/groovy-calculator/pom.xml
  11. +1 −1  examples/java-calculator/pom.xml
  12. +2 −0  examples/java-helloworld/.gitignore
  13. +27 −3 examples/java-helloworld/build.xml
  14. +3 −3 examples/java-helloworld/pom.xml
  15. +1 −1  examples/java-webbit-websockets-selenium/pom.xml
  16. +17 −0 ...les/java-webbit-websockets-selenium/src/test/java/cucumber/examples/java/websockets/NavigationStepdefs.java
  17. +28 −6 examples/java-webbit-websockets-selenium/src/test/java/cucumber/examples/java/websockets/SharedDriver.java
  18. +0 −5 ...es/java-webbit-websockets-selenium/src/test/java/cucumber/examples/java/websockets/TemperatureStepdefs.java
  19. +7 −2 ...bit-websockets-selenium/src/test/resources/cucumber/examples/java/websockets/temperature_conversion.feature
  20. +1 −1  examples/scala-calculator/pom.xml
  21. +1 −1  groovy/pom.xml
  22. +2 −2 groovy/src/main/java/cucumber/runtime/groovy/GroovySnippet.java
  23. +10 −10 groovy/src/test/java/cucumber/runtime/groovy/GroovySnippetTest.java
  24. +1 −1  guice/pom.xml
  25. +1 −1  ioke/pom.xml
  26. +1 −1  java/pom.xml
  27. +9 −2 java/src/main/java/cucumber/runtime/java/ClasspathMethodScanner.java
  28. +3 −2 java/src/main/java/cucumber/runtime/java/JavaBackend.java
  29. +26 −2 java/src/test/java/cucumber/runtime/java/ClasspathMethodScannerTest.java
  30. +12 −3 java/src/test/java/cucumber/runtime/java/JavaBackendTest.java
  31. +0 −1  java/src/test/java/cucumber/runtime/java/JavaStepDefinitionTest.java
  32. +6 −0 java/src/test/java/cucumber/runtime/java/incorrectlysubclassedstepdefs/SubclassesStepdefs.java
  33. +1 −1  java/src/test/java/cucumber/runtime/java/{test → stepdefs}/Stepdefs.java
  34. +1 −1  jruby/pom.xml
  35. +1 −1  junit/pom.xml
  36. +4 −4 junit/src/main/java/cucumber/junit/Cucumber.java
  37. +1 −1  jython/pom.xml
  38. +1 −1  openejb/pom.xml
  39. +1 −1  picocontainer/pom.xml
  40. +1 −0  picocontainer/src/test/java/cucumber/runtime/java/picocontainer/RunCukesTest.java
  41. +18 −0 picocontainer/src/test/resources/.cucumber/stepdefs.json
  42. +4 −0 picocontainer/src/test/resources/cucumber/runtime/java/picocontainer/dates.feature
  43. +4 −4 pom.xml
  44. +1 −1  rhino/pom.xml
  45. +0 −1  rhino/src/main/java/cucumber/runtime/rhino/RhinoBackend.java
  46. +1 −1  scala/pom.xml
  47. +1 −1  spring/pom.xml
  48. +1 −1  weld/pom.xml
13 History.md
View
@@ -1,8 +1,17 @@
-## [Git master](https://github.com/cucumber/cucumber-jvm/compare/v1.0.1...master)
+## [1.0.4](https://github.com/cucumber/cucumber-jvm/compare/v1.0.3...1.0.4)
+
+* [Core] Ability to specify line numbers: `@Cucumber.Options(features = "my/nice.feature:2:10")` ([#234](https://github.com/cucumber/cucumber-jvm/issues/234) Aslak Hellesøy)
+* [WebDriver] Improved example that shows how to reuse a driver for the entire JVM. (Aslak Hellesøy)
+* [Core] Allow custom @XStreamConverter to be used on regular arguments - not just table arguments. (Aslak Hellesøy)
+* [Groovy] fixed & simplified groovy step snippets ([#303](https://github.com/cucumber/cucumber-jvm/pull/303) Martin Hauner)
+* [Java] Detect subclassing in glue code and report to the user that it's illegal. ([#301](https://github.com/cucumber/cucumber-jvm/issues/301) Aslak Hellesøy)
+* [Core] Friendlier error message when XStream fails to assign null to primitive fields ([#296](https://github.com/cucumber/cucumber-jvm/issues/296) Aslak Hellesøy)
+
+## [1.0.3](https://github.com/cucumber/cucumber-jvm/compare/v1.0.2...1.0.3)
* [Core] Friendlier error message when XStream fails conversion ([#296](https://github.com/cucumber/cucumber-jvm/issues/296) Aslak Hellesøy)
* [Core] Empty strings from matched steps and table cells are converted to `null`. This means boxed types must be used if you intend to have empty strings. (Aslak Hellesøy)
-* [Core] ([#196](https://github.com/cucumber/cucumber-jvm/issues/196), [#284](https://github.com/cucumber/cucumber-jvm/pull/284) Klaus Bayrhammer)
+* [Core] Implement --strict ([#196](https://github.com/cucumber/cucumber-jvm/issues/196), [#284](https://github.com/cucumber/cucumber-jvm/pull/284) Klaus Bayrhammer)
* [Clojure] Cucumber-clojure adding after hook to before ([#294](https://github.com/cucumber/cucumber-jvm/pull/294) Daniel E. Renfer)
* [Java] Show code source for Java step definitions in case of duplicates or ambiguous stepdefs. (Aslak Hellesøy).
* [Groovy] Arity mismatch can be avoided by explicitly declaring an empty list of closure parameters. ([#297](https://github.com/cucumber/cucumber-jvm/issues/297) Aslak Hellesøy)
13 README.md
View
@@ -46,13 +46,13 @@ in your [POM](http://maven.apache.org/pom.html):
<dependency>
<groupId>info.cukes</groupId>
<artifactId>cucumber-java</artifactId>
- <version>1.0.3</version>
+ <version>1.0.4</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>info.cukes</groupId>
<artifactId>cucumber-junit</artifactId>
- <version>1.0.3</version>
+ <version>1.0.4</version>
<scope>test</scope>
</dependency>
<dependency>
@@ -70,7 +70,7 @@ There are more jars available - add the ones you need. (TODO: A guide on how to
Add a [dependency](http://ant.apache.org/ivy/history/latest-milestone/ivyfile/dependency.html) in your [ivy.xml](http://ant.apache.org/ivy/history/latest-milestone/ivyfile.html):
```xml
- <dependency org="info.cukes" name="cucumber-core" rev="1.0.2"/>
+ <dependency org="info.cukes" name="cucumber-core" rev="1.0.4"/>
```
Since the artifacts are released to Maven Central, the default Ivy configuration should pull them down automatically.
@@ -90,7 +90,7 @@ There isn't any online documentation yet. Check out the examples, read the code
### API Docs
-* http://cukes.info/cucumber/jvm/api/1.0.2
+* http://cukes.info/cucumber/jvm/api/1.0.4
## Examples
@@ -194,7 +194,7 @@ Fork the repository on Github, clone it and send a pull request when you have fi
This is a reminder to the developers:
-First, replace versions in this file. Then make sure you have the proper keys set up - in your `~/.m2/settings.xml` - for example:
+First, make sure you have the proper keys set up - in your `~/.m2/settings.xml` - for example:
```
<settings>
@@ -224,8 +224,9 @@ Replace version numbers in:
* examples/java-helloworld/build.xml
* examples/java-helloworld/pom.xml
* README.md
+* History.md
-Then release everything:
+git commit -m "Release X.Y.Z", then release everything:
```
mvn release:clean
2  clojure/pom.xml
View
@@ -5,7 +5,7 @@
<groupId>info.cukes</groupId>
<artifactId>cucumber-jvm</artifactId>
<relativePath>../pom.xml</relativePath>
- <version>1.0.3</version>
+ <version>1.0.4</version>
</parent>
<artifactId>cucumber-clojure</artifactId>
2  core/pom.xml
View
@@ -5,7 +5,7 @@
<groupId>info.cukes</groupId>
<artifactId>cucumber-jvm</artifactId>
<relativePath>../pom.xml</relativePath>
- <version>1.0.3</version>
+ <version>1.0.4</version>
</parent>
<artifactId>cucumber-core</artifactId>
18 core/src/main/java/cucumber/runtime/RuntimeOptions.java
View
@@ -28,7 +28,7 @@
public File dotCucumber;
public boolean dryRun;
public boolean strict = false;
- public List<String> tags = new ArrayList<String>();
+ public List<Object> filters = new ArrayList<Object>();
public List<Formatter> formatters = new ArrayList<Formatter>();
public List<String> featurePaths = new ArrayList<String>();
private boolean monochrome = false;
@@ -63,7 +63,7 @@ private void parse(ArrayList<String> args) {
String gluePath = args.remove(0);
glue.add(gluePath);
} else if (arg.equals("--tags") || arg.equals("-t")) {
- tags.add(args.remove(0));
+ filters.add(args.remove(0));
} else if (arg.equals("--format") || arg.equals("-f")) {
formatters.add(formatterConverter.convert(args.remove(0)));
} else if (arg.equals("--dotcucumber")) {
@@ -75,14 +75,15 @@ private void parse(ArrayList<String> args) {
} else if (arg.equals("--monochrome") || arg.equals("-m")) {
monochrome = true;
} else {
- // TODO: Use PathWithLines and add line filter if any
- featurePaths.add(arg);
+ PathWithLines pathWithLines = new PathWithLines(arg);
+ featurePaths.add(pathWithLines.path);
+ filters.addAll(pathWithLines.lines);
}
}
}
public List<CucumberFeature> cucumberFeatures(ResourceLoader resourceLoader) {
- return load(resourceLoader, featurePaths, filters());
+ return load(resourceLoader, featurePaths, filters);
}
public Formatter formatter(ClassLoader classLoader) {
@@ -110,11 +111,4 @@ public Object invoke(Object target, Method method, Object[] args) throws Throwab
}
});
}
-
- private List<Object> filters() {
- List<Object> filters = new ArrayList<Object>();
- filters.addAll(tags);
- // TODO: Add lines and patterns (names)
- return filters;
- }
}
33 core/src/main/java/cucumber/runtime/StepDefinitionMatch.java
View
@@ -1,6 +1,8 @@
package cucumber.runtime;
import com.thoughtworks.xstream.XStream;
+import com.thoughtworks.xstream.annotations.XStreamConverter;
+import com.thoughtworks.xstream.converters.Converter;
import com.thoughtworks.xstream.converters.ConverterLookup;
import com.thoughtworks.xstream.converters.SingleValueConverter;
import cucumber.runtime.converters.EnumConverter;
@@ -77,22 +79,39 @@ public void runStep(I18n i18n) throws Throwable {
int n = 0;
for (Argument a : getArguments()) {
- SingleValueConverter converter;
+ SingleValueConverter singleValueConverter;
TimeConverter timeConverter = null;
ParameterType parameterType = parameterTypes.get(n);
+
+ xStream.processAnnotations(parameterType.getParameterClass());
+
if (parameterType.getDateFormat() != null) {
timeConverter = TimeConverter.getInstance(parameterType, locale);
timeConverter.setOnlyFormat(parameterType.getDateFormat(), locale);
- converter = timeConverter;
+ singleValueConverter = timeConverter;
} else if (parameterType.getParameterClass().isEnum()) {
- converter = new EnumConverter(locale, (Class<? extends Enum>) parameterType.getParameterClass());
+ singleValueConverter = new EnumConverter(locale, (Class<? extends Enum>) parameterType.getParameterClass());
} else {
- // TODO: We might get a lookup that doesn't implement SingleValueConverter
- // Need to throw a more friendly exception in that case.
- converter = (SingleValueConverter) converterLookup.lookupConverterForType(parameterType.getParameterClass());
+ Converter converter = converterLookup.lookupConverterForType(parameterType.getParameterClass());
+ if(converter instanceof SingleValueConverter) {
+ singleValueConverter = (SingleValueConverter) converter;
+ } else {
+ throw new CucumberException(String.format(
+ "Don't know how to convert %s into %s.\n" +
+ "Try writing your own converter:\n" +
+ "\n" +
+ "@%s(%sConverter.class)\n" +
+ "public class %s {}\n",
+ a.getVal(),
+ parameterType.getParameterClass().getName(),
+ XStreamConverter.class.getName(),
+ parameterType.getParameterClass().getSimpleName(),
+ parameterType.getParameterClass().getSimpleName()
+ ));
+ }
}
try {
- result[n] = converter.fromString(a.getVal());
+ result[n] = singleValueConverter.fromString(a.getVal());
} finally {
if (timeConverter != null) {
timeConverter.removeOnlyFormat();
3  core/src/main/java/cucumber/table/TableConverter.java
View
@@ -1,6 +1,7 @@
package cucumber.table;
import com.thoughtworks.xstream.XStream;
+import com.thoughtworks.xstream.converters.ConversionException;
import com.thoughtworks.xstream.converters.Converter;
import com.thoughtworks.xstream.converters.SingleValueConverter;
import com.thoughtworks.xstream.converters.reflection.AbstractReflectionConverter;
@@ -48,6 +49,8 @@ public TableConverter(XStream xStream) {
return (List) xStream.unmarshal(reader);
} catch (AbstractReflectionConverter.UnknownFieldException e) {
throw new CucumberException(e.getShortMessage());
+ } catch (ConversionException e){
+ throw new CucumberException(String.format("Can't assign null value to one of the primitive fields in %s. Please use boxed types.", e.get("class")));
}
}
84 core/src/test/java/cucumber/runtime/StepDefinitionMatchTest.java
View
@@ -1,5 +1,7 @@
package cucumber.runtime;
+import com.thoughtworks.xstream.annotations.XStreamConverter;
+import com.thoughtworks.xstream.converters.basic.AbstractSingleValueConverter;
import cucumber.runtime.converters.LocalizedXStreams;
import gherkin.I18n;
import gherkin.formatter.Argument;
@@ -38,6 +40,86 @@ public void converts_numbers() throws Throwable {
}
@Test
+ public void converts_with_explicit_converter() throws Throwable {
+ StepDefinition stepDefinition = mock(StepDefinition.class);
+ List<ParameterType> parameterTypes = asList(new ParameterType(Thing.class, null));
+ when(stepDefinition.getParameterTypes()).thenReturn(parameterTypes);
+
+ Step stepWithoutDocStringOrTable = mock(Step.class);
+ when(stepWithoutDocStringOrTable.getDocString()).thenReturn(null);
+ when(stepWithoutDocStringOrTable.getRows()).thenReturn(null);
+
+ StepDefinitionMatch stepDefinitionMatch = new StepDefinitionMatch(Arrays.asList(new Argument(0, "the thing")), stepDefinition, "some.feature", stepWithoutDocStringOrTable, new LocalizedXStreams(classLoader));
+ stepDefinitionMatch.runStep(ENGLISH);
+ verify(stepDefinition).execute(ENGLISH, new Object[]{new Thing("the thing")});
+ }
+
+ @XStreamConverter(ThingConverter.class)
+ public static class Thing {
+ public final String name;
+
+ public Thing(String name) {
+ this.name = name;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+ Thing thing = (Thing) o;
+ return name.equals(thing.name);
+ }
+
+ @Override
+ public int hashCode() {
+ return name.hashCode();
+ }
+ }
+
+ public static class ThingConverter extends AbstractSingleValueConverter {
+ @Override
+ public boolean canConvert(Class type) {
+ return Thing.class.equals(type);
+ }
+
+ @Override
+ public Object fromString(String str) {
+ return new Thing(str);
+ }
+ }
+
+ @Test
+ public void gives_nice_error_message_when_conversion_fails() throws Throwable {
+ StepDefinition stepDefinition = mock(StepDefinition.class);
+ List<ParameterType> parameterTypes = asList(new ParameterType(Thang.class, null));
+ when(stepDefinition.getParameterTypes()).thenReturn(parameterTypes);
+
+ Step stepWithoutDocStringOrTable = mock(Step.class);
+ when(stepWithoutDocStringOrTable.getDocString()).thenReturn(null);
+ when(stepWithoutDocStringOrTable.getRows()).thenReturn(null);
+
+ StepDefinitionMatch stepDefinitionMatch = new StepDefinitionMatch(Arrays.asList(new Argument(0, "blah")), stepDefinition, "some.feature", stepWithoutDocStringOrTable, new LocalizedXStreams(classLoader));
+ try {
+
+ stepDefinitionMatch.runStep(ENGLISH);
+ fail();
+ } catch (CucumberException expected) {
+ assertEquals(
+ "Don't know how to convert blah into cucumber.runtime.StepDefinitionMatchTest$Thang.\n" +
+ "Try writing your own converter:\n" +
+ "\n" +
+ "@com.thoughtworks.xstream.annotations.XStreamConverter(ThangConverter.class)\n" +
+ "public class Thang {}\n",
+ expected.getMessage()
+ );
+ }
+ }
+
+ public static class Thang {
+
+ }
+
+ @Test
public void can_have_doc_string_as_only_argument() throws Throwable {
StepDefinition stepDefinition = mock(StepDefinition.class);
List<ParameterType> parameterTypes = asList(new ParameterType(String.class, null));
@@ -78,7 +160,7 @@ public void throws_arity_mismatch_exception() throws Throwable {
try {
stepDefinitionMatch.runStep(new I18n("en"));
fail();
- } catch(CucumberException expected) {
+ } catch (CucumberException expected) {
assertEquals("Arity mismatch: Step Definition 'toString' with pattern /some pattern/ is declared with 0 parameters. However, the gherkin step matched 1 arguments [3]. \n" +
"Step: Given I have 4 cukes in my belly", expected.getMessage());
}
19 core/src/test/java/cucumber/table/ToDataTableTest.java
View
@@ -59,6 +59,21 @@ public void gives_a_nice_error_message_when_field_is_missing() {
}
@Test
+ public void gives_a_nice_error_message_when_primitive_field_is_null() {
+ try {
+ tc.toList(PojoWithInt.class, TableParser.parse("" +
+ "| credits |\n" +
+ "| 5 |\n" +
+ "| |\n" +
+ "")
+ );
+ fail();
+ } catch (CucumberException e) {
+ assertEquals("Can't assign null value to one of the primitive fields in cucumber.table.ToDataTableTest$PojoWithInt. Please use boxed types.", e.getMessage());
+ }
+ }
+
+ @Test
@Ignore
public void converts_list_of_beans_to_table_with_explicit_columns() {
List<UserPojo> users = tc.toList(UserPojo.class, personTable());
@@ -111,4 +126,8 @@ public void converts_list_of_single_value_to_table() {
public UserPojo(int foo) {
}
}
+
+ public static class PojoWithInt {
+ public int credits;
+ }
}
2  examples/groovy-calculator/pom.xml
View
@@ -5,7 +5,7 @@
<groupId>info.cukes</groupId>
<artifactId>cucumber-jvm</artifactId>
<relativePath>../../pom.xml</relativePath>
- <version>1.0.3</version>
+ <version>1.0.4</version>
</parent>
<artifactId>groovy-calculator</artifactId>
2  examples/java-calculator/pom.xml
View
@@ -5,7 +5,7 @@
<groupId>info.cukes</groupId>
<artifactId>cucumber-jvm</artifactId>
<relativePath>../../pom.xml</relativePath>
- <version>1.0.3</version>
+ <version>1.0.4</version>
</parent>
<artifactId>java-calculator</artifactId>
2  examples/java-helloworld/.gitignore
View
@@ -0,0 +1,2 @@
+lib/
+target/
30 examples/java-helloworld/build.xml
View
@@ -1,9 +1,9 @@
<project name="java-helloworld" basedir="." default="runcukes">
<property name="repo" value="https://oss.sonatype.org/content/repositories/releases"/>
- <property name="cucumber-jvm.version" value="1.0.3"/>
+ <property name="cucumber-jvm.version" value="1.0.4"/>
<property name="gherkin.version" value="2.9.3"/>
<property name="junit.version" value="4.10"/>
- <property name="jars" value="target/lib"/>
+ <property name="jars" value="lib"/>
<target name="download">
<mkdir dir="${jars}"/>
@@ -40,7 +40,8 @@
</target>
<target name="runcukes" depends="compile-test">
- <java classname="cucumber.cli.Main" fork="true">
+ <mkdir dir="target/junit-report"/>
+ <java classname="cucumber.cli.Main" fork="true" failonerror="false" resultproperty="cucumber.exitstatus">
<classpath>
<fileset dir="${jars}">
<include name="**/*.jar"/>
@@ -48,13 +49,36 @@
<pathelement location="target/classes"/>
<pathelement location="target/test-classes"/>
</classpath>
+ <arg value="--format"/>
+ <arg value="junit:target/junit-report.xml"/>
+ <arg value="--format"/>
+ <arg value="pretty"/>
<arg value="--glue"/>
<arg value="cucumber.examples.java.helloworld"/>
<arg value="src/test/resources"/>
</java>
+
+ <junitreport todir="target/junit-report">
+ <fileset dir="target">
+ <include name="junit-report.xml"/>
+ </fileset>
+ <report format="frames" todir="target/junit-report"/>
+ </junitreport>
+
+ <fail message="Cucumber failed">
+ <condition>
+ <not>
+ <equals arg1="${cucumber.exitstatus}" arg2="0"/>
+ </not>
+ </condition>
+ </fail>
</target>
<target name="clean">
<delete dir="target"/>
</target>
+
+ <target name="clobber" depends="clean">
+ <delete dir="${jars}"/>
+ </target>
</project>
6 examples/java-helloworld/pom.xml
View
@@ -4,7 +4,7 @@
<groupId>info.cukes</groupId>
<artifactId>java-helloworld</artifactId>
- <version>1.0.3</version>
+ <version>1.0.4-SNAPSHOT</version>
<packaging>jar</packaging>
<name>Examples: Java Hello World</name>
@@ -27,13 +27,13 @@
<dependency>
<groupId>info.cukes</groupId>
<artifactId>cucumber-java</artifactId>
- <version>1.0.2</version>
+ <version>1.0.4-SNAPSHOT</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>info.cukes</groupId>
<artifactId>cucumber-junit</artifactId>
- <version>1.0.2</version>
+ <version>1.0.4-SNAPSHOT</version>
<scope>test</scope>
</dependency>
<dependency>
2  examples/java-webbit-websockets-selenium/pom.xml
View
@@ -5,7 +5,7 @@
<groupId>info.cukes</groupId>
<artifactId>cucumber-jvm</artifactId>
<relativePath>../../pom.xml</relativePath>
- <version>1.0.3</version>
+ <version>1.0.4</version>
</parent>
<artifactId>java-webbit-websockets-selenium</artifactId>
17 .../java-webbit-websockets-selenium/src/test/java/cucumber/examples/java/websockets/NavigationStepdefs.java
View
@@ -0,0 +1,17 @@
+package cucumber.examples.java.websockets;
+
+import cucumber.annotation.en.Given;
+import org.openqa.selenium.WebDriver;
+
+public class NavigationStepdefs {
+ private final WebDriver webDriver;
+
+ public NavigationStepdefs(SharedDriver webDriver) {
+ this.webDriver = webDriver;
+ }
+
+ @Given("^I am on the front page$")
+ public void i_am_on_the_front_page() {
+ webDriver.get("http://localhost:" + ServerHooks.PORT);
+ }
+}
34 examples/java-webbit-websockets-selenium/src/test/java/cucumber/examples/java/websockets/SharedDriver.java
View
@@ -1,8 +1,10 @@
package cucumber.examples.java.websockets;
import cucumber.annotation.After;
+import cucumber.annotation.Before;
import cucumber.runtime.ScenarioResult;
import org.openqa.selenium.OutputType;
+import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebDriverException;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.support.events.EventFiringWebDriver;
@@ -10,23 +12,43 @@
import java.io.ByteArrayInputStream;
/**
- * Example of a WebDriver implementation that automatically closes at the
- * end of each scenario, and can be shared across step definitions via dependency injection.
+ * Example of a WebDriver implementation that has an underlying instance that is used for all scenarios and closed
+ * when the JVM exits. This saves time. To prevent browser state from leaking between scenarios, cookies are deleted before
+ * every scenario.
+ *
+ * As a bonus, screenshots are embedded into the report for each scenario. (This only works
+ * if you're also using the HTML formatter).
+ *
+ * This class can be shared across step definitions via dependency injection.
*/
public class SharedDriver extends EventFiringWebDriver {
+ private static final WebDriver REAL_DRIVER = new ChromeDriver();
+
+ static {
+ Runtime.getRuntime().addShutdownHook(new Thread() {
+ @Override
+ public void run() {
+ REAL_DRIVER.close();
+ }
+ });
+ }
+
public SharedDriver() {
- super(new ChromeDriver());
+ super(REAL_DRIVER);
+ }
+
+ @Before
+ public void deleteAllCookies() {
+ manage().deleteAllCookies();
}
@After
- public void close(ScenarioResult result) {
+ public void embedScreenshot(ScenarioResult result) {
try {
byte[] screenshot = this.getScreenshotAs(OutputType.BYTES);
result.embed(new ByteArrayInputStream(screenshot), "image/png");
} catch (WebDriverException somePlatformsDontSupportScreenshots) {
System.err.println(somePlatformsDontSupportScreenshots.getMessage());
- } finally {
- close();
}
}
}
5 ...java-webbit-websockets-selenium/src/test/java/cucumber/examples/java/websockets/TemperatureStepdefs.java
View
@@ -15,11 +15,6 @@ public TemperatureStepdefs(SharedDriver webDriver) {
this.webDriver = webDriver;
}
- @Given("^I am on the front page$")
- public void i_am_on_the_front_page() {
- webDriver.get("http://localhost:" + ServerHooks.PORT);
- }
-
@When("^I enter (.+) Celcius$")
public void i_enter_Celcius(double celcius) {
webDriver.findElement(By.id("celcius")).sendKeys(String.valueOf(celcius));
9 ...-websockets-selenium/src/test/resources/cucumber/examples/java/websockets/temperature_conversion.feature
View
@@ -1,6 +1,11 @@
Feature: Temperature conversion
- Scenario: Celcius to Fahrenheit
+ Scenario: 0 Celcius to Fahrenheit
Given I am on the front page
When I enter 0 Celcius
- Then I should see 32.0 Fahrenheit
+ Then I should see 32.0 Fahrenheit
+
+ Scenario: 100 Celcius to Fahrenheit
+ Given I am on the front page
+ When I enter 100 Celcius
+ Then I should see 212.0 Fahrenheit
2  examples/scala-calculator/pom.xml
View
@@ -5,7 +5,7 @@
<groupId>info.cukes</groupId>
<artifactId>cucumber-jvm</artifactId>
<relativePath>../../pom.xml</relativePath>
- <version>1.0.3</version>
+ <version>1.0.4</version>
</parent>
<artifactId>scala-calculator</artifactId>
2  groovy/pom.xml
View
@@ -5,7 +5,7 @@
<groupId>info.cukes</groupId>
<artifactId>cucumber-jvm</artifactId>
<relativePath>../pom.xml</relativePath>
- <version>1.0.3</version>
+ <version>1.0.4</version>
</parent>
<artifactId>cucumber-groovy</artifactId>
4 groovy/src/main/java/cucumber/runtime/groovy/GroovySnippet.java
View
@@ -7,7 +7,7 @@
public class GroovySnippet implements Snippet {
@Override
public String template() {
- return "{0}(~\"{1}\") '{' {3}->\n" +
+ return "{0}(~''{1}'') '{' {3}->\n" +
" // {4}\n" +
" throw new PendingException()\n" +
"'}'\n";
@@ -46,6 +46,6 @@ public String namedGroupEnd() {
@Override
public String escapePattern(String pattern) {
- return pattern.replaceAll("\"", "\\\\\"");
+ return pattern;
}
}
20 groovy/src/test/java/cucumber/runtime/groovy/GroovySnippetTest.java
View
@@ -20,7 +20,7 @@
@Test
public void generatesPlainSnippet() {
String expected = "" +
- "Given(~\"^I have (\\d+) cukes in my \\\"([^\\\"]*)\\\" belly$\") { int arg1, String arg2 ->\n" +
+ "Given(~'^I have (\\d+) cukes in my \"([^\"]*)\" belly$') { int arg1, String arg2 ->\n" +
" // Express the Regexp above with the code you wish you had\n" +
" throw new PendingException()\n" +
"}\n";
@@ -30,7 +30,7 @@ public void generatesPlainSnippet() {
@Test
public void generatesCopyPasteReadyStepSnippetForNumberParameters() throws Exception {
String expected = "" +
- "Given(~\"^before (\\d+) after$\") { int arg1 ->\n" +
+ "Given(~'^before (\\d+) after$') { int arg1 ->\n" +
" // Express the Regexp above with the code you wish you had\n" +
" throw new PendingException()\n" +
"}\n";
@@ -41,7 +41,7 @@ public void generatesCopyPasteReadyStepSnippetForNumberParameters() throws Excep
@Test
public void generatesCopyPasteReadySnippetWhenStepHasIllegalJavaIdentifierChars() {
String expected = "" +
- "Given(~\"^I have (\\d+) cukes in: my \\\"([^\\\"]*)\\\" red-belly!$\") { int arg1, String arg2 ->\n" +
+ "Given(~'^I have (\\d+) cukes in: my \"([^\"]*)\" red-belly!$') { int arg1, String arg2 ->\n" +
" // Express the Regexp above with the code you wish you had\n" +
" throw new PendingException()\n" +
"}\n";
@@ -52,7 +52,7 @@ public void generatesCopyPasteReadySnippetWhenStepHasIllegalJavaIdentifierChars(
@Test
public void generatesCopyPasteReadySnippetWhenStepHasIntegersInsideStringParameter() {
String expected = "" +
- "Given(~\"^the DI system receives a message saying \\\"([^\\\"]*)\\\"$\") { String arg1 ->\n" +
+ "Given(~'^the DI system receives a message saying \"([^\"]*)\"$') { String arg1 ->\n" +
" // Express the Regexp above with the code you wish you had\n" +
" throw new PendingException()\n" +
"}\n";
@@ -62,7 +62,7 @@ public void generatesCopyPasteReadySnippetWhenStepHasIntegersInsideStringParamet
@Test
public void generatesSnippetWithEscapedDollarSigns() {
String expected = "" +
- "Given(~\"^I have \\$(\\d+)$\") { int arg1 ->\n" +
+ "Given(~'^I have \\$(\\d+)$') { int arg1 ->\n" +
" // Express the Regexp above with the code you wish you had\n" +
" throw new PendingException()\n" +
"}\n";
@@ -72,7 +72,7 @@ public void generatesSnippetWithEscapedDollarSigns() {
@Test
public void generatesSnippetWithEscapedParentheses() {
String expected = "" +
- "Given(~\"^I have (\\d+) cukes \\(maybe more\\)$\") { int arg1 ->\n" +
+ "Given(~'^I have (\\d+) cukes \\(maybe more\\)$') { int arg1 ->\n" +
" // Express the Regexp above with the code you wish you had\n" +
" throw new PendingException()\n" +
"}\n";
@@ -82,7 +82,7 @@ public void generatesSnippetWithEscapedParentheses() {
@Test
public void generatesSnippetWithEscapedBrackets() {
String expected = "" +
- "Given(~\"^I have (\\d+) cukes \\[maybe more\\]$\") { int arg1 ->\n" +
+ "Given(~'^I have (\\d+) cukes \\[maybe more\\]$') { int arg1 ->\n" +
" // Express the Regexp above with the code you wish you had\n" +
" throw new PendingException()\n" +
"}\n";
@@ -92,7 +92,7 @@ public void generatesSnippetWithEscapedBrackets() {
@Test
public void generatesSnippetWithDocString() {
String expected = "" +
- "Given(~\"^I have:$\") { String arg1 ->\n" +
+ "Given(~'^I have:$') { String arg1 ->\n" +
" // Express the Regexp above with the code you wish you had\n" +
" throw new PendingException()\n" +
"}\n";
@@ -102,7 +102,7 @@ public void generatesSnippetWithDocString() {
@Test
public void generatesSnippetWithDataTable() {
String expected = "" +
- "Given(~\"^I have:$\") { DataTable arg1 ->\n" +
+ "Given(~'^I have:$') { DataTable arg1 ->\n" +
" // Express the Regexp above with the code you wish you had\n" +
" throw new PendingException()\n" +
"}\n";
@@ -124,4 +124,4 @@ private String snippetForDataTable(String name, List<DataTableRow> dataTable) {
Step step = new Step(NO_COMMENTS, "Given ", name, 0, dataTable, null);
return new SnippetGenerator(new GroovySnippet()).getSnippet(step);
}
-}
+}
2  guice/pom.xml
View
@@ -5,7 +5,7 @@
<groupId>info.cukes</groupId>
<artifactId>cucumber-jvm</artifactId>
<relativePath>../pom.xml</relativePath>
- <version>1.0.3</version>
+ <version>1.0.4</version>
</parent>
<artifactId>cucumber-guice</artifactId>
2  ioke/pom.xml
View
@@ -5,7 +5,7 @@
<groupId>info.cukes</groupId>
<artifactId>cucumber-jvm</artifactId>
<relativePath>../pom.xml</relativePath>
- <version>1.0.3</version>
+ <version>1.0.4</version>
</parent>
<artifactId>cucumber-ioke</artifactId>
2  java/pom.xml
View
@@ -5,7 +5,7 @@
<groupId>info.cukes</groupId>
<artifactId>cucumber-jvm</artifactId>
<relativePath>../pom.xml</relativePath>
- <version>1.0.3</version>
+ <version>1.0.4</version>
</parent>
<artifactId>cucumber-java</artifactId>
11 java/src/main/java/cucumber/runtime/java/ClasspathMethodScanner.java
View
@@ -41,7 +41,7 @@ public void scan(JavaBackend javaBackend, List<String> gluePaths) {
}
if (glueCodeClass != null) {
for (Method method : glueCodeClass.getMethods()) {
- scan(javaBackend, method);
+ scan(javaBackend, method, glueCodeClass);
}
}
}
@@ -53,11 +53,18 @@ public void scan(JavaBackend javaBackend, List<String> gluePaths) {
*
* @param javaBackend the backend where stepdefs and hooks will be registered
* @param method a candidate for being a stepdef or hook
+ * @param glueCodeClass
*/
- public void scan(JavaBackend javaBackend, Method method) {
+ public void scan(JavaBackend javaBackend, Method method, Class<?> glueCodeClass) {
for (Class<? extends Annotation> cucumberAnnotationClass : cucumberAnnotationClasses) {
Annotation annotation = method.getAnnotation(cucumberAnnotationClass);
if (annotation != null && !annotation.annotationType().equals(Order.class)) {
+ if(!method.getDeclaringClass().isAssignableFrom(glueCodeClass)) {
+ throw new CucumberException(String.format("%s isn't assignable from %s", method.getDeclaringClass(), glueCodeClass));
+ }
+ if(!glueCodeClass.equals(method.getDeclaringClass())) {
+ throw new CucumberException(String.format("You're not allowed to extend classes that define Step Definitions or hooks. %s extends %s", glueCodeClass, method.getDeclaringClass()));
+ }
if (isHookAnnotation(annotation)) {
javaBackend.addHook(annotation, method);
} else if (isStepdefAnnotation(annotation)) {
5 java/src/main/java/cucumber/runtime/java/JavaBackend.java
View
@@ -64,10 +64,11 @@ public void loadGlue(Glue glue, List<String> gluePaths) {
*
* @param glue where stepdefs and hooks will be added.
* @param method a candidate method.
+ * @param glueCodeClass the class implementing the method. Must not be a subclass of the class implementing the method.
*/
- public void loadGlue(Glue glue, Method method) {
+ public void loadGlue(Glue glue, Method method, Class<?> glueCodeClass) {
this.glue = glue;
- classpathMethodScanner.scan(this, method);
+ classpathMethodScanner.scan(this, method, glueCodeClass);
}
@Override
28 java/src/test/java/cucumber/runtime/java/ClasspathMethodScannerTest.java
View
@@ -2,11 +2,14 @@
import cucumber.annotation.Before;
import cucumber.io.ClasspathResourceLoader;
+import cucumber.runtime.CucumberException;
import cucumber.runtime.Glue;
import org.junit.Test;
import org.mockito.Mockito;
import org.mockito.internal.util.reflection.Whitebox;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.fail;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoMoreInteractions;
@@ -15,7 +18,6 @@
@Test
public void loadGlue_registers_the_methods_declaring_class_in_the_object_factory() throws NoSuchMethodException {
-
ClasspathResourceLoader resourceLoader = new ClasspathResourceLoader(Thread.currentThread().getContextClassLoader());
ClasspathMethodScanner classpathMethodScanner = new ClasspathMethodScanner(resourceLoader);
@@ -25,12 +27,34 @@ public void loadGlue_registers_the_methods_declaring_class_in_the_object_factory
Whitebox.setInternalState(backend, "glue", world);
// this delegates to classpathMethodScanner.scan which we test
- classpathMethodScanner.scan(backend, BaseStepDefs.class.getMethod("m"));
+ classpathMethodScanner.scan(backend, BaseStepDefs.class.getMethod("m"), BaseStepDefs.class);
verify(factory, times(1)).addClass(BaseStepDefs.class);
verifyNoMoreInteractions(factory);
}
+ @Test
+ public void loadGlue_fails_when_class_is_not_method_declaring_class() throws NoSuchMethodException {
+ JavaBackend backend = new JavaBackend((ObjectFactory) null);
+ try {
+ backend.loadGlue(null, BaseStepDefs.class.getMethod("m"), Stepdefs2.class);
+ fail();
+ } catch (CucumberException e) {
+ assertEquals("You're not allowed to extend classes that define Step Definitions or hooks. class cucumber.runtime.java.ClasspathMethodScannerTest$Stepdefs2 extends class cucumber.runtime.java.ClasspathMethodScannerTest$BaseStepDefs", e.getMessage());
+ }
+ }
+
+ @Test
+ public void loadGlue_fails_when_class_is_not_subclass_of_declaring_class() throws NoSuchMethodException {
+ JavaBackend backend = new JavaBackend((ObjectFactory) null);
+ try {
+ backend.loadGlue(null, BaseStepDefs.class.getMethod("m"), String.class);
+ fail();
+ } catch (CucumberException e) {
+ assertEquals("class cucumber.runtime.java.ClasspathMethodScannerTest$BaseStepDefs isn't assignable from class java.lang.String", e.getMessage());
+ }
+ }
+
public static class Stepdefs2 extends BaseStepDefs {
public interface Interface1 {
}
15 java/src/test/java/cucumber/runtime/java/JavaBackendTest.java
View
@@ -6,7 +6,8 @@
import cucumber.runtime.HookDefinition;
import cucumber.runtime.StepDefinition;
import cucumber.runtime.StepDefinitionMatch;
-import cucumber.runtime.java.test.Stepdefs;
+import cucumber.runtime.java.incorrectlysubclassedstepdefs.SubclassesStepdefs;
+import cucumber.runtime.java.stepdefs.Stepdefs;
import gherkin.I18n;
import gherkin.formatter.model.Step;
import org.junit.Test;
@@ -25,7 +26,7 @@ public void doesnt_like_path_like_glue() {
ObjectFactory factory = new DefaultJavaObjectFactory();
JavaBackend backend = new JavaBackend(factory);
GlueStub world = new GlueStub();
- backend.loadGlue(world, asList("cucumber/runtime/java/test"));
+ backend.loadGlue(world, asList("cucumber/runtime/java/stepdefs"));
}
@Test
@@ -33,11 +34,19 @@ public void finds_step_definitions_by_scanning_for_annotations() {
ObjectFactory factory = new DefaultJavaObjectFactory();
JavaBackend backend = new JavaBackend(factory);
GlueStub world = new GlueStub();
- backend.loadGlue(world, asList("cucumber.runtime.java.test"));
+ backend.loadGlue(world, asList("cucumber.runtime.java.stepdefs"));
backend.buildWorld();
assertEquals(Stepdefs.class, factory.getInstance(Stepdefs.class).getClass());
}
+ @Test(expected = CucumberException.class)
+ public void detects_subclassed_glue_and_throws_exception() {
+ ObjectFactory factory = new DefaultJavaObjectFactory();
+ JavaBackend backend = new JavaBackend(factory);
+ GlueStub world = new GlueStub();
+ backend.loadGlue(world, asList("cucumber.runtime.java.stepdefs", "cucumber.runtime.java.incorrectlysubclassedstepdefs"));
+ }
+
private class GlueStub implements Glue {
public final List<StepDefinition> stepDefinitions = new ArrayList<StepDefinition>();
1  java/src/test/java/cucumber/runtime/java/JavaStepDefinitionTest.java
View
@@ -31,7 +31,6 @@
public class JavaStepDefinitionTest {
private static final List<Comment> NO_COMMENTS = Collections.emptyList();
- private static final List<String> NO_PATHS = Collections.emptyList();
private static final Method THREE_DISABLED_MICE;
private static final Method THREE_BLIND_ANIMALS;
private static final I18n ENGLISH = new I18n("en");
6 java/src/test/java/cucumber/runtime/java/incorrectlysubclassedstepdefs/SubclassesStepdefs.java
View
@@ -0,0 +1,6 @@
+package cucumber.runtime.java.incorrectlysubclassedstepdefs;
+
+import cucumber.runtime.java.stepdefs.Stepdefs;
+
+public class SubclassesStepdefs extends Stepdefs {
+}
2  ...est/java/cucumber/runtime/java/test/Stepdefs.java → ...java/cucumber/runtime/java/stepdefs/Stepdefs.java
View
@@ -1,4 +1,4 @@
-package cucumber.runtime.java.test;
+package cucumber.runtime.java.stepdefs;
import cucumber.annotation.en.Given;
2  jruby/pom.xml
View
@@ -5,7 +5,7 @@
<groupId>info.cukes</groupId>
<artifactId>cucumber-jvm</artifactId>
<relativePath>../pom.xml</relativePath>
- <version>1.0.3</version>
+ <version>1.0.4</version>
</parent>
<artifactId>cucumber-jruby</artifactId>
2  junit/pom.xml
View
@@ -5,7 +5,7 @@
<groupId>info.cukes</groupId>
<artifactId>cucumber-jvm</artifactId>
<relativePath>../pom.xml</relativePath>
- <version>1.0.3</version>
+ <version>1.0.4</version>
</parent>
<artifactId>cucumber-junit</artifactId>
8 junit/src/main/java/cucumber/junit/Cucumber.java
View
@@ -56,8 +56,7 @@ public Cucumber(Class clazz) throws InitializationError, IOException {
RuntimeOptions runtimeOptions = runtimeOptionsFactory.create();
runtime = new Runtime(resourceLoader, classLoader, runtimeOptions);
- jUnitReporter = new JUnitReporter(runtimeOptions.reporter(classLoader), runtimeOptions.formatter(classLoader)
- , runtimeOptions.strict);
+ jUnitReporter = new JUnitReporter(runtimeOptions.reporter(classLoader), runtimeOptions.formatter(classLoader), runtimeOptions.strict);
addChildren(runtimeOptions.cucumberFeatures(resourceLoader));
}
@@ -120,7 +119,8 @@ private void addChildren(List<CucumberFeature> cucumberFeatures) throws Initiali
boolean dryRun() default false;
/**
- * Scenarios fail if
+ * Scenarios fail if
+ *
* @return
*/
boolean strict() default false;
@@ -136,7 +136,7 @@ private void addChildren(List<CucumberFeature> cucumberFeatures) throws Initiali
String[] glue() default {};
/**
- * @return what tags in the feature should be executed
+ * @return what tags in the features should be executed
*/
String[] tags() default {};
2  jython/pom.xml
View
@@ -5,7 +5,7 @@
<groupId>info.cukes</groupId>
<artifactId>cucumber-jvm</artifactId>
<relativePath>../pom.xml</relativePath>
- <version>1.0.3</version>
+ <version>1.0.4</version>
</parent>
<artifactId>cucumber-jython</artifactId>
2  openejb/pom.xml
View
@@ -5,7 +5,7 @@
<groupId>info.cukes</groupId>
<artifactId>cucumber-jvm</artifactId>
<relativePath>../pom.xml</relativePath>
- <version>1.0.3</version>
+ <version>1.0.4</version>
</parent>
<artifactId>cucumber-openejb</artifactId>
2  picocontainer/pom.xml
View
@@ -5,7 +5,7 @@
<groupId>info.cukes</groupId>
<artifactId>cucumber-jvm</artifactId>
<relativePath>../pom.xml</relativePath>
- <version>1.0.3</version>
+ <version>1.0.4</version>
</parent>
<artifactId>cucumber-picocontainer</artifactId>
1  picocontainer/src/test/java/cucumber/runtime/java/picocontainer/RunCukesTest.java
View
@@ -4,5 +4,6 @@
import org.junit.runner.RunWith;
@RunWith(Cucumber.class)
+//@Cucumber.Options(features = "cucumber/runtime/java/picocontainer/dates.feature:2:10")
public class RunCukesTest {
}
18 picocontainer/src/test/resources/.cucumber/stepdefs.json
View
@@ -125,6 +125,15 @@
]
},
{
+ "name": "the date should be Mar 1 2013",
+ "args": [
+ {
+ "offset": 19,
+ "val": "Mar 1 2013"
+ }
+ ]
+ },
+ {
"name": "the date should be Oct 25 2011",
"args": [
{
@@ -147,6 +156,15 @@
"val": "2012-03-01T06:54:14"
}
]
+ },
+ {
+ "name": "the iso calendar is 2013-03-01T06:54:14",
+ "args": [
+ {
+ "offset": 20,
+ "val": "2013-03-01T06:54:14"
+ }
+ ]
}
]
},
4 picocontainer/src/test/resources/cucumber/runtime/java/picocontainer/dates.feature
View
@@ -10,3 +10,7 @@ Feature: Dates
Scenario: An ISO 8601 date as Calendar
Given the iso calendar is 2012-03-01T06:54:14
Then the date should be Mar 1 2012
+
+ Scenario: Another ISO 8601 date as Calendar
+ Given the iso calendar is 2013-03-01T06:54:14
+ Then the date should be Mar 1 2013
8 pom.xml
View
@@ -2,7 +2,7 @@
<modelVersion>4.0.0</modelVersion>
<groupId>info.cukes</groupId>
<artifactId>cucumber-jvm</artifactId>
- <version>1.0.3</version>
+ <version>1.0.4</version>
<packaging>pom</packaging>
<name>Cucumber-JVM</name>
<url>http://cukes.info/</url>
@@ -168,12 +168,12 @@
<dependency>
<groupId>org.seleniumhq.selenium</groupId>
<artifactId>selenium-chrome-driver</artifactId>
- <version>2.20.0</version>
+ <version>2.21.0</version>
</dependency>
<dependency>
<groupId>org.seleniumhq.selenium</groupId>
<artifactId>selenium-server</artifactId>
- <version>2.20.0</version>
+ <version>2.21.0</version>
</dependency>
<dependency>
<groupId>org.webbitserver</groupId>
@@ -183,7 +183,7 @@
<dependency>
<groupId>org.jruby</groupId>
<artifactId>jruby-complete</artifactId>
- <version>1.6.7</version>
+ <version>1.6.7.1</version>
</dependency>
<dependency>
<groupId>org.jboss.weld.se</groupId>
2  rhino/pom.xml
View
@@ -5,7 +5,7 @@
<groupId>info.cukes</groupId>
<artifactId>cucumber-jvm</artifactId>
<relativePath>../pom.xml</relativePath>
- <version>1.0.3</version>
+ <version>1.0.4</version>
</parent>
<artifactId>cucumber-rhino</artifactId>
1  rhino/src/main/java/cucumber/runtime/rhino/RhinoBackend.java
View
@@ -15,7 +15,6 @@
import org.mozilla.javascript.regexp.NativeRegExp;
import org.mozilla.javascript.tools.shell.Global;
-import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.List;
2  scala/pom.xml
View
@@ -5,7 +5,7 @@
<groupId>info.cukes</groupId>
<artifactId>cucumber-jvm</artifactId>
<relativePath>../pom.xml</relativePath>
- <version>1.0.3</version>
+ <version>1.0.4</version>
</parent>
<artifactId>cucumber-scala</artifactId>
2  spring/pom.xml
View
@@ -5,7 +5,7 @@
<groupId>info.cukes</groupId>
<artifactId>cucumber-jvm</artifactId>
<relativePath>../pom.xml</relativePath>
- <version>1.0.3</version>
+ <version>1.0.4</version>
</parent>
<artifactId>cucumber-spring</artifactId>
2  weld/pom.xml
View
@@ -5,7 +5,7 @@
<groupId>info.cukes</groupId>
<artifactId>cucumber-jvm</artifactId>
<relativePath>../pom.xml</relativePath>
- <version>1.0.3</version>
+ <version>1.0.4</version>
</parent>
<artifactId>cucumber-weld</artifactId>

Showing you all comments on commits in this comparison.

Christian Zulehner

Executing a Cucumber-JVM Junit Test fails with a ClassCastException as the given line-number makes it into the filters Object-Array as Long (from class PathWithLines) and the gherkin.TagExpresison only handles Strings ??

java.lang.ClassCastException: java.lang.Long cannot be cast to java.lang.String
    at gherkin.TagExpression.<init>(TagExpression.java:16)
    at gherkin.formatter.TagFilter.<init>(TagFilter.java:14)
    at gherkin.formatter.FilterFormatter.detectFilter(FilterFormatter.java:54)
    at gherkin.formatter.FilterFormatter.<init>(FilterFormatter.java:39)
    at cucumber.runtime.FeatureBuilder.parse(FeatureBuilder.java:108)
    at cucumber.runtime.model.CucumberFeature.load(CucumberFeature.java:40)
    at cucumber.runtime.RuntimeOptions.cucumberFeatures(RuntimeOptions.java:86)
    at cucumber.junit.Cucumber.<init>(Cucumber.java:60)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:39)
    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:27)
    at java.lang.reflect.Constructor.newInstance(Constructor.java:513)
    at org.junit.internal.builders.AnnotatedBuilder.buildRunner(AnnotatedBuilder.java:31)
    at org.junit.internal.builders.AnnotatedBuilder.runnerForClass(AnnotatedBuilder.java:24)
    at org.junit.runners.model.RunnerBuilder.safeRunnerForClass(RunnerBuilder.java:57)
    at org.junit.internal.builders.AllDefaultPossibilitiesBuilder.runnerForClass(AllDefaultPossibilitiesBuilder.java:29)
    at org.junit.runners.model.RunnerBuilder.safeRunnerForClass(RunnerBuilder.java:57)
    at org.junit.internal.requests.ClassRequest.getRunner(ClassRequest.java:24)
    at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.<init>(JUnit4TestReference.java:33)
    at org.eclipse.jdt.internal.junit4.runner.JUnit4TestClassReference.<init>(JUnit4TestClassReference.java:25)
    at org.eclipse.jdt.internal.junit4.runner.JUnit4TestLoader.createTest(JUnit4TestLoader.java:48)
    at org.eclipse.jdt.internal.junit4.runner.JUnit4TestLoader.loadTests(JUnit4TestLoader.java:38)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:452)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)

Am I missing something?

Aslak Hellesøy

How can I reproduce this? Are you passing both tags and line numbers?

Christian Zulehner

Good hint!

Yes, I passed in both, tags and a line number:

@RunWith(Cucumber.class)
@Cucumber.Options(format = {"pretty", "html:target/cucumber"},
    features = {"tree/Maintenance/SalutationMaintenance.feature:16"},
    tags = {"~@Obsolete", "~@Manual"},
    glue = {" ... "}, 
    monochrome = true)
public class MaintenanceFeaturesTest
{
  ....

After removing the tags-Option it works, so this seems to be ok for me now,
but maybe adding a line of documentation in Cucumber.Options would help :-)
Or implementing a check to raise an error if specifiying both the tags option and adding a line number...

Aslak Hellesøy

Yeah I'll add that. It needs to go into gherkin

restagner

I'm encountering a similar issue to the one noted by @czulehner. In my case, the Cucumber.Options look like

@RunWith(Cucumber.class)
@Cucumber.Options(
        features = { "src/test/resources/features/se_drag_n_drop.feature:4" }
        , monochrome = true
        , format = {"pretty", "html:target/results" }
        , glue = { "org.stag.hello" }
        , tags = { "@drag_n_drop" })
public class HelloTest {
}

This produces the following exception when it's executed. Is using the 'tags' option, in combination with the feature + line number option something I should avoid?

java.lang.ClassCastException: java.lang.Long cannot be cast to java.lang.String
    at gherkin.TagExpression.<init>(TagExpression.java:16)
    at gherkin.formatter.TagFilter.<init>(TagFilter.java:14)
    at gherkin.formatter.FilterFormatter.detectFilter(FilterFormatter.java:54)
    at gherkin.formatter.FilterFormatter.<init>(FilterFormatter.java:39)
    at cucumber.runtime.FeatureBuilder.parse(FeatureBuilder.java:108)
    at cucumber.runtime.model.CucumberFeature.load(CucumberFeature.java:40)
    at cucumber.runtime.RuntimeOptions.cucumberFeatures(RuntimeOptions.java:86)
    at cucumber.junit.Cucumber.<init>(Cucumber.java:61)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:39)
    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:27)
    at java.lang.reflect.Constructor.newInstance(Constructor.java:513)
    at org.junit.internal.builders.AnnotatedBuilder.buildRunner(AnnotatedBuilder.java:31)
    at org.junit.internal.builders.AnnotatedBuilder.runnerForClass(AnnotatedBuilder.java:24)
    at org.junit.runners.model.RunnerBuilder.safeRunnerForClass(RunnerBuilder.java:57)
    at org.junit.internal.builders.AllDefaultPossibilitiesBuilder.runnerForClass(AllDefaultPossibilitiesBuilder.java:29)
    at org.junit.runners.model.RunnerBuilder.safeRunnerForClass(RunnerBuilder.java:57)
    at org.junit.internal.requests.ClassRequest.getRunner(ClassRequest.java:24)
    at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.<init>(JUnit4TestReference.java:33)
    at org.eclipse.jdt.internal.junit4.runner.JUnit4TestClassReference.<init>(JUnit4TestClassReference.java:25)
    at org.eclipse.jdt.internal.junit4.runner.JUnit4TestLoader.createTest(JUnit4TestLoader.java:48)
    at org.eclipse.jdt.internal.junit4.runner.JUnit4TestLoader.loadTests(JUnit4TestLoader.java:38)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:452)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)
Aslak Hellesøy

Yes. You can specify tags or line numbers, but not both. I'll create a ticket.

Something went wrong with that request. Please try again.