Test Automation
with Cucumber-JVM
Boston Java Meetup, 13/06/2013
Alan Parkinson
@alan_parkinson
Cucumber is a tool that executes plain-text
functional descriptions as automated tests
Tests written in business-facing text
Supports over 40 spoken languages
This test is called Gherkin
Automation written in target language
Ruby, Java, Scala, Groovy, etc.. .net, python, PHP
Behaviour Driven
Development
Software - What can go wrong?
IMPLEMENTATION DEFECT
Program does not do what it is intended
Fixed in development/QA
REQUIREMENTS DEFECT
Program does what is intended
Unstated, misunderstood or tacit
requirements
A woman asks her husband, a
programmer, to go shopping.
She tells him please, go to the nearby
grocery store to buy some bread. Also,
if they have eggs, buy 6
50-60%
of issues identified by testers can be chalked down as
Requirements Defects
100-200%
more expensive to fix than other defects because
the code is already written
How does BDD help?
All stakeholders involved in the discussion drives out clear and concise
specifications centred around business value.
Write specifications in natural language so everyone is on the same page
Turn the specification into acceptance tests that guarantees the software
does as it is intended
Use those tests as the software evolves to guarantee that it continues to
work as intended.
Specifications are documentation each scenario describes how the
system is being used
Cucumber, The Origins
Cucumber
Ruby
Born 2007-2008
Cuke4Duke
First seen in 2008
JRuby
Cucumber-JVM
Released April 2012
Java, Groovy, Clojure, Scala, Ioke, Jython, Rhino (JavaScript) and JRuby
Maven Dependencies
cucumberjava
cucumberjunit
cucumberpicocontainer
cucumberguice
cucumberspring
Maven Dependencies
< dependency>
< groupId> [Link]< /groupId>
< artifactId> cucum ber-picocontainer< /artifactId>
< version> ${cucum [Link]}< /version>
< /dependency>
< dependency>
< groupId> [Link]< /groupId>
< artifactId> cucum ber-junit< /artifactId>
< version> ${cucum [Link]}< /version>
< /dependency>
Scenarios - Given When Then
Given an owner with a registered pet called Sly
When the owner registers a new pet called Sly
Then the user should be warned that the pet
already exists
Writing Scenario's in Cucumber
Scenarios are organized together into features
Each feature is represented as a plain text file.
Feature files must have the .feature extension
Each feature can contain many scenarios
JUnit Runner
i m p o r t o r g . j u n i t . r u n n e r. R u n W i t h ;
i m p o r t c u c u m b e r. j u n i t . C u c u m b e r ;
@ R u n W i t h ( C u c u m b e r. c l a s s )
public class RunnerIT {
}
JUnit Runner 2
Body
of the class should be empty
No @Test annotated methods
No @Before or @After methods
Arguments
can be provided with an
additional annotation
JUnit Runner - Arguments
@ R u n W i t h ( C u c u m b e r. c l a s s )
@ C u c u m b e r. O p t i o n s (
features =
"src/test/resources/features
)
public class RunnerIT {
}
Step Definitions
A single Method representing a Step from a Feature file
The Method is annotated with information about the step
it represents
Cucumber generates Code Snippet's for Step Definition
it cant find
Step Annotations
import [Link].*;
Each Gherkin step keyword has a Annotation
@ W h e n ( " ^ we wa n t t o st o p t ra ffi c $ " )
p u b l i c vo i d m eth o d Na m e ( ) { }
Passing and Failing
Each step has it own result state
Passed
Pending
Skipped
Failed
Individual step result state combined determine the
Scenarios success or failure
Steps can be failed on exceptions or JUnit Assertion
failures
Regex Lesson
Cucumber uses Regular Expressions to match steps to
definitions.
@When("^we want to stop traffic$")
^ Matches the starting position
$ Matches the ending position
Capturing Arguments
@ G iven ("^ an ow ner w ith a pet called \"Sly\"$")
p u b lic void an _ow n er_w ith _a_p et_called () {
@ G iven ("^ an ow ner w ith a pet called \"([^ \"]*)\"$")
p u b lic void an _ow n er_w ith _a_p et_called (S trin g n am e) {
Capturing Arguments 2
The pair of brackets is a capture group
Everything captured is passed to method parameter
Cucumber will automatically convert to the method
parameter type
Equal number of method parameters and capture groups
Type Conversion
If the captured string is not in the correct format for type
conversion an error will be thrown
Use regular expressions to capture the correct format
string for the type
Note: Escape regular expression characters with backslash
Typical Capture Groups
(.+)
Good for capturing strings and dates
\"([^\"]*)\" Captures a string within Double quotes
(\\d) Capture decimal numbers only
(\\d+\\.\\d+) Capture floating point numbers
(true|false) Captures a Boolean value
Date Formats
@Given ("^today is (.+)$")
public void today_is(Date date) {
.
}
Dates are recognized if its a format from the DateFormat
class
Date Formats
SHORT is completely numeric, such as 12.13.52 or 3:30pm
MEDIUM is longer, such as Jan 12, 1952
LONG is longer, such as January 12, 1952 or [Link]pm
FULL is pretty completely specified, such as Tuesday, April
12, 1952 AD or [Link]pm PST.
Date Formats
import [Link];
@Given ("^today is (.+)$")
public void today_is(
@DateFormat ("yyyy-MM-dd") Date date) {
.
}
Tag use cases
Grouping Scenarios together
Identify slow running test that shouldnt be run frequently
Identify tests that require a particular library or server
Running Scenarios with a Tag
@ C u c u m b e r. O pt i o n s (
tags = {@WebDriver}, )
Running Scenarios without a Tag
Cucumber can exclude Scenarios with a particular tag by
inserting the tilde character before the tag
For the following command will run all Scenarios without
the WebDriver tag
@ C u c u m b e r. O p t i o n s (
tags = {~@WebDriver}, )
Tag expressions Logical OR
Separate a list of tags by commas for a Logical OR tag
expression
@ C u c u m b e r. O p t i o n s (
tags = {@WebDriver,@email}, )
Tag expressions Logical AND
Specifying multiple tag arguments creates a logical AND
between each tag expression.
@ C u c u m b e r. O p t i o n s (
tags = {@WebDriver, @email}, )
Tag expressions AND OR
Run scenarios that are tagged with @WebDriver or @email
but not @slow
@ C u c u m b e r. O p t i o n s (
tags = {@WebDriver,@email, ~@slow}, )
Further information
Official website: [Link]
Github: [Link]/cucumber/cucumber-jvm
Hindsight Software: [Link]
Thank you
Alan Parkinson
CEO and Co-founder, Hindsight Software Ltd
[Link]@[Link]
@alan_parkinson