Commit 5a121649 authored by Alex Segers's avatar Alex Segers
parents
/.idea/
*.iml
/target/
/lib
.classpath
.project
.settings
language: java
# java-cucumber-example
A sample project for Cucumber and/or Selenium tests.
# Instructions
Clone the repo:
Git:
```
$ git clone git@github.com:testdouble/java-cucumber-example.git
```
Svn:
```
$ svn co https://github.com/testdouble/java-cucumber-example
```
Or download a ZIP of master [manually](https://github.com/testdouble/java-cucumber-example/archive/master.zip) and expand the contents someplace on your system
## Prerequisites
In order to run browser tests, Selenium will need to be able to drive a browser
installed to your system.
(TODO after testing on Windows)
## Verify installation
## Use Maven
Open a command window and run:
mvn test
This runs Cucumber features using Cucumber's JUnit runner. The `@RunWith(Cucumber.class)` annotation on the `RunCukesTest`
class tells JUnit to kick off Cucumber.
## Use Ant
Open a command window and run:
ant download
ant runcukes
This runs Cucumber features using Cucumber's Command Line Interface (CLI) runner. Note that the `RunCukesTest` junit class is not used at all.
If you remove it (and the `cucumber-junit` jar dependency), it will run just the same.
## Overriding options
The Cucumber runtime parses command line options to know what features to run, where the glue code lives, what plugins to use etc.
When you use the JUnit runner, these options are generated from the `@CucumberOptions` annotation on your test.
Sometimes it can be useful to override these options without changing or recompiling the JUnit class. This can be done with the
`cucumber.options` system property. The general form is:
Using Maven:
mvn -Dcucumber.options="..." test
Using Ant:
JAVA_OPTIONS='-Dcucumber.options="..."' ant runcukes
Let's look at some things you can do with `cucumber.options`. Try this:
-Dcucumber.options="--help"
That should list all the available options.
*IMPORTANT*
When you override options with `-Dcucumber.options`, you will completely override whatever options are hard-coded in
your `@CucumberOptions` or in the script calling `cucumber.api.cli.Main`. There is one exception to this rule, and that
is the `--plugin` option. This will not _override_, but _add_ a plugin. The reason for this is to make it easier
for 3rd party tools (such as [Cucumber Pro](https://cucumber.pro/)) to automatically configure additional plugins by appending arguments to a `cucumber.properties`
file.
### Run a subset of Features or Scenarios
Specify a particular scenario by *line* (and use the pretty plugin, which prints the scenario back)
-Dcucumber.options="classpath:skeleton/belly.feature:4 --plugin pretty"
This works because Maven puts `./src/test/resources` on your `classpath`.
You can also specify files to run by filesystem path:
-Dcucumber.options="src/test/resources/skeleton/belly.feature:4 --plugin pretty"
You can also specify what to run by *tag*:
-Dcucumber.options="--tags @bar --plugin pretty"
### Running only the scenarios that failed in the previous run
-Dcucumber.options="@target/rerun.txt"
This works as long as you have the `rerun` formatter enabled.
### Specify a different formatter:
For example a JUnit formatter:
-Dcucumber.options="--plugin junit:target/cucumber-junit-report.xml"
<project name="java-helloworld" basedir="." default="runcukes">
<property name="repo" value="https://repo1.maven.org/maven2"/>
<!-- To figure out compatible combinations of versions, you should examine dependencies in the Maven POM files -->
<property name="cucumber-jvm.version" value="1.2.4"/>
<property name="cucumber-jvm-deps.version" value="1.0.5"/>
<property name="gherkin.version" value="2.12.2"/>
<property name="cucumber-html.version" value="0.2.3"/>
<property name="junit.version" value="4.12"/>
<property name="jars" value="lib"/>
<target name="download">
<mkdir dir="${jars}"/>
<get src="${repo}/info/cukes/cucumber-core/${cucumber-jvm.version}/cucumber-core-${cucumber-jvm.version}.jar"
dest="${jars}/cucumber-core-${cucumber-jvm.version}.jar"/>
<get src="${repo}/info/cukes/cucumber-java/${cucumber-jvm.version}/cucumber-java-${cucumber-jvm.version}.jar"
dest="${jars}/cucumber-java-${cucumber-jvm.version}.jar"/>
<get src="${repo}/info/cukes/cucumber-junit/${cucumber-jvm.version}/cucumber-junit-${cucumber-jvm.version}.jar"
dest="${jars}/cucumber-junit-${cucumber-jvm.version}.jar"/>
<get src="${repo}/info/cukes/cucumber-jvm-deps/${cucumber-jvm-deps.version}/cucumber-jvm-deps-${cucumber-jvm-deps.version}.jar"
dest="${jars}/cucumber-jvm-deps-${cucumber-jvm-deps.version}.jar"/>
<get src="${repo}/info/cukes/gherkin/${gherkin.version}/gherkin-${gherkin.version}.jar"
dest="${jars}/gherkin-${gherkin.version}.jar"/>
<get src="${repo}/info/cukes/cucumber-html/${cucumber-html.version}/cucumber-html-${cucumber-html.version}.jar"
dest="${jars}/cucumber-html-${cucumber-html.version}.jar"/>
<get src="${repo}/junit/junit/${junit.version}/junit-${junit.version}.jar"
dest="${jars}/junit-${junit.version}.jar"/>
</target>
<target name="classpath">
<path id="classpath">
<fileset dir="${jars}">
<include name="**/*.jar"/>
</fileset>
<pathelement location="src/test/resources"/>
<pathelement location="target/classes"/>
<pathelement location="target/test-classes"/>
</path>
</target>
<target name="compile" depends="classpath">
<mkdir dir="target/classes"/>
<javac srcdir="src/main/java" destdir="target/classes" classpathref="classpath" includeantruntime="false"/>
</target>
<target name="compile-test" depends="compile,classpath">
<mkdir dir="target/test-classes"/>
<javac srcdir="src/test/java" destdir="target/test-classes" classpathref="classpath" includeantruntime="false"/>
</target>
<target name="runcukes" depends="compile-test">
<mkdir dir="target/cucumber-junit-report"/>
<java classname="cucumber.api.cli.Main" fork="true" failonerror="false" resultproperty="cucumber.exitstatus">
<classpath refid="classpath"/>
<arg value="--plugin"/>
<arg value="junit:target/cucumber-junit-report.xml"/>
<arg value="--plugin"/>
<arg value="pretty"/>
<arg value="--plugin"/>
<arg value="html:target/cucumber-html-report"/>
<arg value="--glue"/>
<arg value="skeleton"/>
<arg value="src/test/resources"/>
</java>
<junitreport todir="target/cucumber-junit-report">
<fileset dir="target">
<include name="cucumber-junit-report.xml"/>
</fileset>
<report format="frames" todir="target/cucumber-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>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>cucumber</groupId>
<artifactId>java-cucumber-example</artifactId>
<version>0.0.1</version>
<packaging>jar</packaging>
<properties>
<browser>firefox</browser>
</properties>
<dependencies>
<dependency>
<groupId>info.cukes</groupId>
<artifactId>cucumber-java</artifactId>
<version>RELEASE</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>info.cukes</groupId>
<artifactId>cucumber-junit</artifactId>
<version>RELEASE</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>RELEASE</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.hamcrest</groupId>
<artifactId>hamcrest-all</artifactId>
<version>RELEASE</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.seleniumhq.selenium</groupId>
<artifactId>selenium-java</artifactId>
<version>RELEASE</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.seleniumhq.selenium</groupId>
<artifactId>selenium-ie-driver</artifactId>
<version>RELEASE</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.seleniumhq.selenium</groupId>
<artifactId>selenium-chrome-driver</artifactId>
<version>RELEASE</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.19.1</version>
<configuration>
<systemPropertyVariables>
<browser>chrome</browser>
</systemPropertyVariables>
</configuration>
</plugin>
</plugins>
</build>
</project>
package skeleton;
public class Belly {
public void eat(int cukes) {
}
}
package bank;
import cucumber.api.CucumberOptions;
import cucumber.api.junit.Cucumber;
import org.junit.runner.RunWith;
@RunWith(Cucumber.class)
@CucumberOptions(plugin = {"pretty"}, monochrome = true)
public class RunCukesTest {
//This test is intentionally blank
//See:
// * src/test/resources for Gherkin Feature files
// * bank.Stepdefs for step definitions
}
package bank;
public class Stepdefs {
}
package selenium;
import org.junit.Test;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeDriver;
import support.Browser;
public class SimpleTest {
@Test
public void sometest() {
//http://www.seleniumhq.org/download/maven.jsp
//https://code.google.com/p/selenium/wiki/GettingStarted
WebDriver driver = Browser.launch();
driver.get("https://www.google.com");
WebElement element = driver.findElement(By.name("q"));
element.sendKeys("Cheese!");
element.submit();
System.out.println("Page title is: " + driver.getTitle());
driver.quit();
}
}
package selenium;
import org.junit.runner.RunWith;
import cucumber.api.CucumberOptions;
import cucumber.api.junit.Cucumber;
@RunWith(Cucumber.class)
@CucumberOptions(plugin = {"pretty"}, monochrome = true)
public class TodoCukeTest {
}
package selenium;
import static org.hamcrest.Matchers.*;
import static org.junit.Assert.*;
import static selenium.TodoUtil.*;
import org.openqa.selenium.WebDriver;
import cucumber.api.java.After;
import cucumber.api.java.en.Given;
import cucumber.api.java.en.Then;
import cucumber.api.java.en.When;
import support.Browser;
public class TodoSteps {
WebDriver driver;
@After
public void quitBrowser() {
driver.quit();
}
@Given("^am I on the todo page$")
public void am_I_on_the_todo_page() throws Throwable {
TodoUtil.driver = driver = Browser.launch();
driver.get("http://testdouble.github.io/todos/");
}
@When("^I type the todo \"([^\"]*)\"$")
public void i_type_the_todo(String todoText) throws Throwable {
addTodo(todoText);
}
@Then("^todo list item (\\d+) has text \"([^\"]*)\"$")
public void todo_list_item_has_text(int ordinal, String expected) throws Throwable {
assertThat(todoAt(ordinal - 1).getText(), is(expected));
}
}
package selenium;
import static org.hamcrest.Matchers.*;
import static org.junit.Assert.*;
import static selenium.TodoUtil.*;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.openqa.selenium.WebDriver;
import support.Browser;
public class TodoTest {
WebDriver driver = Browser.launch();
@Before
public void setup() {
TodoUtil.driver = driver;
driver.get("http://testdouble.github.io/todos/");
}
@After
public void teardown() {
driver.quit();
}
@Test
public void createTodo() {
addTodo("Mow the Lawn");
assertThat(todoAt(0).getText(), is("Mow the Lawn"));
}
@Test
public void createTwoTodos() {
addTodo("Shower");
addTodo("Get dressed");
assertThat(todoAt(0).getText(), is("Shower"));
assertThat(todoAt(1).getText(), is("Get dressed"));
}
@Test
public void marksATodoDone() {
addTodo("Eat Food");
assertThat(isDone(todoAt(0)), is(false));
markTodoDone(todoAt(0));
assertThat(isDone(todoAt(0)), is(true));
}
@Test
public void canDeleteATodo() {
addTodo("Thing");
deleteTodo(todoAt(0));
assertThat(todoAt(0), is(nullValue()));
}
@Test
public void clearCompletedTodos() {
addTodo("Do Stuff");
markTodoDone(todoAt(0));
clearDoneTodos();
assertThat(todoAt(0), is(nullValue()));
}
}
\ No newline at end of file
package selenium;
import org.openqa.selenium.By;
import org.openqa.selenium.NoSuchElementException;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.interactions.Actions;
public class TodoUtil {
public static WebDriver driver;
public static WebElement any(String css) {
return any(driver.findElement(By.cssSelector("html")), css);
}
public static WebElement any(WebElement parent, String css) {
try {
return parent.findElement(By.cssSelector(css));
} catch(NoSuchElementException e) {
return null;
}
}
public static void addTodo(String text) {
any("#new-todo").sendKeys(text + "\n");
}
public static WebElement todoAt(int index) {
return any("#todo-list li:nth-child("+(index + 1)+")");
}
public static void markTodoDone(WebElement todo) {
any(todo, "input.check").click();
}
public static boolean isDone(WebElement todo) {
return any(todo, ".todo.done") != null;
}
public static void deleteTodo(WebElement todo) {
new Actions(driver)
.moveToElement(todo)
.moveToElement(any(todo, ".todo-destroy"))
.click().build().perform();
}
public static void clearDoneTodos() {
any(".todo-clear").click();
}
}
package skeleton;
import cucumber.api.CucumberOptions;
import cucumber.api.junit.Cucumber;
import org.junit.runner.RunWith;
@RunWith(Cucumber.class)
@CucumberOptions(plugin = {"pretty"}, monochrome = true)
public class RunCukesTest {
}
package skeleton;
import cucumber.api.java.en.Given;
public class Stepdefs {
@Given("^I have (\\d+) cukes in my belly$")
public void I_have_cukes_in_my_belly(int cukes) throws Throwable {
Belly belly = new Belly();
belly.eat(cukes);
}
}
package support;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.openqa.selenium.ie.InternetExplorerDriver;
public class Browser {
public static WebDriver launch() {
String browser = System.getProperty("browser");
if(browser.equals("firefox")) {
return new FirefoxDriver();
} else if(browser.equals("chrome")) {
return new ChromeDriver();
} else if(browser.equals("msie")) {
return new InternetExplorerDriver();
} else {
throw new RuntimeException("Unrecognized system property 'browser': " + browser);
}
}
}
Feature: Bank OCR Kata
See details: https://github.com/testdouble/contributing-tests/wiki/Bank-OCR-Kata-in-Cucumber
Scenario: read account numbers
Given I have an account file with contents:
"""
_ _ _ _ _ _ _
| _| _||_||_ |_ ||_||_|
||_ _| | _||_| ||_| _|
"""
When I parse the file
Then the first account number is "123456789"
Feature: Todo Lists
Background:
Given am I on the todo page
Scenario: Creating a todo
When I type the todo "Do Things!"
Then todo list item 1 has text "Do Things!"
\ No newline at end of file
Feature: Belly
Scenario: a few cukes
Given I have 42 cukes in my belly
When I wait 1 hour
Then my belly should growl
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment