Features
After Hooks
After hooks can be used to clean up any state you’ve altered during your
scenario, or to check the status of the scenario and act accordingly.
You can ask a scenario whether it has failed, for example.
Mind you, even if it hasn’t failed yet, you can still make the scenario
fail if your After hook throws an error.
Retreive the status of a scenario as a symbol
- Given
a file named "features/support/debug_hook.rb" with: (000ms)
After do |scenario| puts scenario.status.inspect end
- And
a file named "features/result.feature" with: (000ms)
Feature:
Scenario:
Given this step passes
- When
I run cucumber -f progress (015ms)
- Then
the output should contain ":passed" (000ms)
Retreive the status of a scenario as a symbol
- Given
a file named "features/support/debug_hook.rb" with: (000ms)
After do |scenario| puts scenario.status.inspect end
- And
a file named "features/result.feature" with: (000ms)
Feature:
Scenario:
Given this step fails
- When
I run cucumber -f progress (015ms)
- Then
the output should contain ":failed" (000ms)
Retreive the status of a scenario as a symbol
- Given
a file named "features/support/debug_hook.rb" with: (000ms)
After do |scenario| puts scenario.status.inspect end
- And
a file named "features/result.feature" with: (000ms)
Feature:
Scenario:
Given this step is pending
- When
I run cucumber -f progress (013ms)
- Then
the output should contain ":pending" (000ms)
Check the failed status of a scenario in a hook
- Given
a file named "features/support/debug_hook.rb" with: (000ms)
After do |scenario|
if scenario.failed?
puts "eek"
end
end
- And
a file named "features/fail.feature" with: (000ms)
Feature:
Scenario:
Given this step fails
- When
I run cucumber -f progress (012ms)
- Then
the output should contain: (000ms)
eek
Make a scenario fail from an After hook
- Given
a file named "features/support/bad_hook.rb" with: (000ms)
After do fail 'yikes' end
- And
a file named "features/pass.feature" with: (000ms)
Feature:
Scenario:
Given this step passes
- When
I run cucumber -f pretty (011ms)
- Then
it should fail with: (000ms)
Scenario: # features/pass.feature:2
Given this step passes # features/step_definitions/steps.rb:1
yikes (RuntimeError)
./features/support/bad_hook.rb:2:in `After'
After hooks are executed in reverse order of definition
- Given
a file named "features/support/hooks.rb" with: (000ms)
After do puts "First" end After do puts "Second" end
- And
a file named "features/pass.feature" with: (000ms)
Feature:
Scenario:
Given this step passes
- When
I run cucumber -f progress (007ms)
- Then
the output should contain: (000ms)
Second First
Around hooks
In order to support transactional scenarios for database libraries
that provide only a block syntax for transactions, Cucumber should
permit definition of Around hooks.
A single Around hook
tags: @spawn,@spawn
- Given
a file named "features/step_definitions/steps.rb" with: (000ms)
Then /^the hook is called$/ do expect($hook_called).to be true end
- And
a file named "features/support/hooks.rb" with: (000ms)
Around do |scenario, block| $hook_called = true block.call end
- And
a file named "features/f.feature" with: (000ms)
Feature: Around hooks
Scenario: using hook
Then the hook is called
- When
I run cucumber features/f.feature (605ms)
- Then
it should pass with: (001ms)
Feature: Around hooks
Scenario: using hook # features/f.feature:2
Then the hook is called # features/step_definitions/steps.rb:1
1 scenario (1 passed)
1 step (1 passed)
Multiple Around hooks
tags: @spawn,@spawn
- Given
a file named "features/step_definitions/steps.rb" with: (001ms)
Then /^the hooks are called in the correct order$/ do expect($hooks_called).to eq ['A', 'B', 'C'] end
- And
a file named "features/support/hooks.rb" with: (000ms)
Around do |scenario, block| $hooks_called ||= [] $hooks_called << 'A' block.call end Around do |scenario, block| $hooks_called ||= [] $hooks_called << 'B' block.call end Around do |scenario, block| $hooks_called ||= [] $hooks_called << 'C' block.call end
- And
a file named "features/f.feature" with: (000ms)
Feature: Around hooks
Scenario: using multiple hooks
Then the hooks are called in the correct order
- When
I run cucumber features/f.feature (607ms)
- Then
it should pass with: (000ms)
Feature: Around hooks
Scenario: using multiple hooks # features/f.feature:2
Then the hooks are called in the correct order # features/step_definitions/steps.rb:1
1 scenario (1 passed)
1 step (1 passed)
Mixing Around, Before, and After hooks
tags: @spawn,@spawn
- Given
a file named "features/step_definitions/steps.rb" with: (000ms)
Then /^the Around hook is called around Before and After hooks$/ do expect($hooks_called).to eq ['Around', 'Before'] end
- And
a file named "features/support/hooks.rb" with: (000ms)
Around do |scenario, block| $hooks_called ||= [] $hooks_called << 'Around' block.call $hooks_called << 'Around' $hooks_called.should == ['Around', 'Before', 'After', 'Around'] #TODO: Find out why this fails using the new rspec expect syntax. end Before do |scenario| $hooks_called ||= [] $hooks_called << 'Before' end After do |scenario| $hooks_called ||= [] $hooks_called << 'After' expect($hooks_called).to eq ['Around', 'Before', 'After'] end
- And
a file named "features/f.feature" with: (000ms)
Feature: Around hooks
Scenario: Mixing Around, Before, and After hooks
Then the Around hook is called around Before and After hooks
- When
I run cucumber features/f.feature (607ms)
- Then
it should pass with: (001ms)
Feature: Around hooks
Scenario: Mixing Around, Before, and After hooks # features/f.feature:2
Then the Around hook is called around Before and After hooks # features/step_definitions/steps.rb:1
1 scenario (1 passed)
1 step (1 passed)
Around hooks with tags
tags: @spawn,@spawn
- Given
a file named "features/step_definitions/steps.rb" with: (000ms)
Then /^the Around hooks with matching tags are called$/ do expect($hooks_called).to eq ['one', 'one or two'] end
- And
a file named "features/support/hooks.rb" with: (000ms)
Around('@one') do |scenario, block|
$hooks_called ||= []
$hooks_called << 'one'
block.call
end
Around('@one,@two') do |scenario, block|
$hooks_called ||= []
$hooks_called << 'one or two'
block.call
end
Around('@one', '@two') do |scenario, block|
$hooks_called ||= []
$hooks_called << 'one and two'
block.call
end
Around('@two') do |scenario, block|
$hooks_called ||= []
$hooks_called << 'two'
block.call
end
- And
a file named "features/f.feature" with: (000ms)
Feature: Around hooks
@one
Scenario: Around hooks with tags
Then the Around hooks with matching tags are called
- When
I run cucumber -q -t @one features/f.feature (708ms)
- Then
it should pass with: (000ms)
Feature: Around hooks
@one
Scenario: Around hooks with tags
Then the Around hooks with matching tags are called
1 scenario (1 passed)
1 step (1 passed)
Around hooks with scenario outlines
tags: @spawn,@spawn
- Given
a file named "features/step_definitions/steps.rb" with: (000ms)
Then /^the hook is called$/ do expect($hook_called).to be true end
- And
a file named "features/support/hooks.rb" with: (000ms)
Around do |scenario, block| $hook_called = true block.call end
- And
a file named "features/f.feature" with: (000ms)
Feature: Around hooks with scenario outlines
Scenario Outline: using hook
Then the hook is called
Examples:
| Number |
| one |
| two |
- When
I run cucumber features/f.feature (607ms)
- Then
it should pass with: (001ms)
Feature: Around hooks with scenario outlines
Scenario Outline: using hook # features/f.feature:2
Then the hook is called # features/f.feature:3
Examples:
| Number |
| one |
| two |
2 scenarios (2 passed)
2 steps (2 passed)
Around Hooks and the Custom World
tags: @spawn,@spawn
- Given
a file named "features/step_definitions/steps.rb" with: (000ms)
Then /^the world should be available in the hook$/ do $previous_world = self expect($hook_world).to eq(self) end Then /^what$/ do expect($hook_world).not_to eq($previous_world) end
- And
a file named "features/support/hooks.rb" with: (000ms)
Around do |scenario, block| $hook_world = self block.call end
- And
a file named "features/f.feature" with: (000ms)
Feature: Around hooks
Scenario: using hook
Then the world should be available in the hook
Scenario: using the same hook
Then what
- When
I run cucumber features/f.feature (608ms)
- Then
it should pass (000ms)
Background
Often you find that several scenarios in the same feature start with
a common context.
Cucumber provides a mechanism for this, by providing a Background keyword
where you can specify steps that should be run before each scenario in the
feature. Typically these will be Given steps, but you can use any steps
that you need to.
Hint: if you find that some of the scenarios don’t fit the background,
consider splitting them into a separate feature.
Background
- Given
a file named "features/passing_background.feature" with: (000ms)
Feature: Passing background sample
Background:
Given '10' cukes
Scenario: passing background
Then I should have '10' cukes
Scenario: another passing background
Then I should have '10' cukes
- And
a file named "features/scenario_outline_passing_background.feature" with: (000ms)
Feature: Passing background with scenario outlines sample
Background:
Given '10' cukes
Scenario Outline: passing background
Then I should have '<count>' cukes
Examples:
|count|
| 10 |
Scenario Outline: another passing background
Then I should have '<count>' cukes
Examples:
|count|
| 10 |
- And
a file named "features/background_tagged_before_on_outline.feature" with: (000ms)
@background_tagged_before_on_outline
Feature: Background tagged Before on Outline
Background:
Given this step passes
Scenario Outline: passing background
Then I should have '<count>' cukes
Examples:
| count |
| 888 |
- And
a file named "features/failing_background.feature" with: (000ms)
Feature: Failing background sample
Background:
Given this step raises an error
And '10' cukes
Scenario: failing background
Then I should have '10' cukes
Scenario: another failing background
Then I should have '10' cukes
- And
a file named "features/scenario_outline_failing_background.feature" with: (000ms)
Feature: Failing background with scenario outlines sample
Background:
Given this step raises an error
Scenario Outline: failing background
Then I should have '<count>' cukes
Examples:
|count|
| 10 |
Scenario Outline: another failing background
Then I should have '<count>' cukes
Examples:
|count|
| 10 |
- And
a file named "features/pending_background.feature" with: (000ms)
Feature: Pending background sample
Background:
Given this step is pending
Scenario: pending background
Then I should have '10' cukes
Scenario: another pending background
Then I should have '10' cukes
- And
a file named "features/failing_background_after_success.feature" with: (000ms)
Feature: Failing background after previously successful background sample
Background:
Given this step passes
And '10' global cukes
Scenario: passing background
Then I should have '10' global cukes
Scenario: failing background
Then I should have '10' global cukes
- And
a file named "features/failing_background_after_success_outline.feature" with: (000ms)
Feature: Failing background after previously successful background sample
Background:
Given this step passes
And '10' global cukes
Scenario Outline: passing background
Then I should have '<count>' global cukes
Examples:
| count |
| 10 |
Scenario Outline: failing background
Then I should have '<count>' global cukes
Examples:
| count |
| 10 |
- And
a file named "features/multiline_args_background.feature" with: (000ms)
Feature: Passing background with multiline args
Background:
Given table
|a|b|
|c|d|
And multiline string
"""
I'm a cucumber and I'm okay.
I sleep all night and I test all day
"""
Scenario: passing background
Then the table should be
|a|b|
|c|d|
Then the multiline string should be
"""
I'm a cucumber and I'm okay.
I sleep all night and I test all day
"""
Scenario: another passing background
Then the table should be
|a|b|
|c|d|
Then the multiline string should be
"""
I'm a cucumber and I'm okay.
I sleep all night and I test all day
"""
- And
the standard step definitions (000ms)
- And
a file named "features/step_definitions/cuke_steps.rb" with: (000ms)
Given /^'(.+)' cukes$/ do |cukes| x=1
raise "We already have #{@cukes} cukes!" if @cukes
@cukes = cukes
end
Given /^'(.+)' global cukes$/ do |cukes| x=1
$scenario_runs ||= 0
raise 'FAIL' if $scenario_runs >= 1
$cukes = cukes
$scenario_runs += 1
end
Then /^I should have '(.+)' global cukes$/ do |cukes| x=1
expect($cukes).to eq cukes
end
Then /^I should have '(.+)' cukes$/ do |cukes| x=1
expect(@cukes).to eq cukes
end
Before('@background_tagged_before_on_outline') do
@cukes = '888'
end
After('@background_tagged_before_on_outline') do
expect(@cukes).to eq '888'
end
run a specific scenario with a background
- When
I run cucumber -q features/passing_background.feature:9 (013ms)
- Then
it should pass with exactly: (000ms)
Feature: Passing background sample
Background:
Given '10' cukes
Scenario: another passing background
Then I should have '10' cukes
1 scenario (1 passed)
2 steps (2 passed)
run a feature with a background that passes
- When
I run cucumber -q features/passing_background.feature (014ms)
- Then
it should pass with exactly: (000ms)
Feature: Passing background sample
Background:
Given '10' cukes
Scenario: passing background
Then I should have '10' cukes
Scenario: another passing background
Then I should have '10' cukes
2 scenarios (2 passed)
4 steps (4 passed)
run a feature with scenario outlines that has a background that passes
- When
I run cucumber -q features/scenario_outline_passing_background.feature (012ms)
- Then
it should pass with exactly: (000ms)
Feature: Passing background with scenario outlines sample
Background:
Given '10' cukes
Scenario Outline: passing background
Then I should have '<count>' cukes
Examples:
| count |
| 10 |
Scenario Outline: another passing background
Then I should have '<count>' cukes
Examples:
| count |
| 10 |
2 scenarios (2 passed)
4 steps (4 passed)
run a feature with scenario outlines that has a background that passes
- When
I run cucumber -q features/background_tagged_before_on_outline.feature (009ms)
- Then
it should pass with exactly: (000ms)
@background_tagged_before_on_outline
Feature: Background tagged Before on Outline
Background:
Given this step passes
Scenario Outline: passing background
Then I should have '<count>' cukes
Examples:
| count |
| 888 |
1 scenario (1 passed)
2 steps (2 passed)
run a feature with a background that fails
tags: @spawn
- When
I run cucumber -q features/failing_background.feature (505ms)
- Then
it should fail with exactly: (001ms)
Feature: Failing background sample
Background:
Given this step raises an error
error (RuntimeError)
./features/step_definitions/steps.rb:2:in `/^this step raises an error$/'
features/failing_background.feature:4:in `Given this step raises an error'
And '10' cukes
Scenario: failing background
Then I should have '10' cukes
Scenario: another failing background
Then I should have '10' cukes
Failing Scenarios:
cucumber features/failing_background.feature:7
cucumber features/failing_background.feature:10
2 scenarios (2 failed)
6 steps (2 failed, 4 skipped)
run a feature with scenario outlines that has a background that fails
tags: @spawn
- When
I run cucumber -q features/scenario_outline_failing_background.feature (605ms)
- Then
it should fail with exactly: (001ms)
Feature: Failing background with scenario outlines sample
Background:
Given this step raises an error
error (RuntimeError)
./features/step_definitions/steps.rb:2:in `/^this step raises an error$/'
features/scenario_outline_failing_background.feature:4:in `Given this step raises an error'
Scenario Outline: failing background
Then I should have '<count>' cukes
Examples:
| count |
| 10 |
Scenario Outline: another failing background
Then I should have '<count>' cukes
Examples:
| count |
| 10 |
Failing Scenarios:
cucumber features/scenario_outline_failing_background.feature:10
cucumber features/scenario_outline_failing_background.feature:16
2 scenarios (2 failed)
4 steps (2 failed, 2 skipped)
run a feature with a background that is pending
- When
I run cucumber -q features/pending_background.feature (024ms)
- Then
it should pass with exactly: (000ms)
Feature: Pending background sample
Background:
Given this step is pending
TODO (Cucumber::Pending)
./features/step_definitions/steps.rb:3:in `/^this step is pending$/'
features/pending_background.feature:4:in `Given this step is pending'
Scenario: pending background
Then I should have '10' cukes
Scenario: another pending background
Then I should have '10' cukes
2 scenarios (2 pending)
4 steps (2 skipped, 2 pending)
background passes with first scenario but fails with second
tags: @spawn
- When
I run cucumber -q features/failing_background_after_success.feature (605ms)
- Then
it should fail with exactly: (001ms)
Feature: Failing background after previously successful background sample
Background:
Given this step passes
And '10' global cukes
Scenario: passing background
Then I should have '10' global cukes
Scenario: failing background
And '10' global cukes
FAIL (RuntimeError)
./features/step_definitions/cuke_steps.rb:8:in `/^'(.+)' global cukes$/'
features/failing_background_after_success.feature:5:in `And '10' global cukes'
Then I should have '10' global cukes
Failing Scenarios:
cucumber features/failing_background_after_success.feature:10
2 scenarios (1 failed, 1 passed)
6 steps (1 failed, 1 skipped, 4 passed)
background passes with first outline scenario but fails with second
tags: @spawn
- When
I run cucumber -q features/failing_background_after_success_outline.feature (605ms)
- Then
it should fail with exactly: (001ms)
Feature: Failing background after previously successful background sample
Background:
Given this step passes
And '10' global cukes
Scenario Outline: passing background
Then I should have '<count>' global cukes
Examples:
| count |
| 10 |
Scenario Outline: failing background
Then I should have '<count>' global cukes
Examples:
| count |
| 10 |
FAIL (RuntimeError)
./features/step_definitions/cuke_steps.rb:8:in `/^'(.+)' global cukes$/'
features/failing_background_after_success_outline.feature:5:in `And '10' global cukes'
Failing Scenarios:
cucumber features/failing_background_after_success_outline.feature:19
2 scenarios (1 failed, 1 passed)
6 steps (1 failed, 1 skipped, 4 passed)
background passes with first outline scenario but fails with second (--expand)
tags: @spawn
- When
I run cucumber -x -q features/failing_background_after_success_outline.feature (606ms)
- Then
it should fail with exactly: (000ms)
Feature: Failing background after previously successful background sample
Background:
Given this step passes
And '10' global cukes
Scenario Outline: passing background
Then I should have '<count>' global cukes
Examples:
Scenario: | 10 |
Then I should have '10' global cukes
Scenario Outline: failing background
Then I should have '<count>' global cukes
Examples:
Scenario: | 10 |
And '10' global cukes
FAIL (RuntimeError)
./features/step_definitions/cuke_steps.rb:8:in `/^'(.+)' global cukes$/'
features/failing_background_after_success_outline.feature:5:in `And '10' global cukes'
Then I should have '10' global cukes
Failing Scenarios:
cucumber features/failing_background_after_success_outline.feature:19
2 scenarios (1 failed, 1 passed)
6 steps (1 failed, 1 skipped, 4 passed)
background with multline args
- Given
a file named "features/step_definitions/steps.rb" with: (000ms)
Given /^table$/ do |table| x=1 @table = table end Given /^multiline string$/ do |string| x=1 @multiline = string end Then /^the table should be$/ do |table| x=1 expect(@table.raw).to eq table.raw end Then /^the multiline string should be$/ do |string| x=1 expect(@multiline).to eq string end
- When
I run cucumber -q features/multiline_args_background.feature (025ms)
- Then
it should pass with exactly: (000ms)
Feature: Passing background with multiline args
Background:
Given table
| a | b |
| c | d |
And multiline string
"""
I'm a cucumber and I'm okay.
I sleep all night and I test all day
"""
Scenario: passing background
Then the table should be
| a | b |
| c | d |
Then the multiline string should be
"""
I'm a cucumber and I'm okay.
I sleep all night and I test all day
"""
Scenario: another passing background
Then the table should be
| a | b |
| c | d |
Then the multiline string should be
"""
I'm a cucumber and I'm okay.
I sleep all night and I test all day
"""
2 scenarios (2 passed)
8 steps (8 passed)
Before Hook
Examine names of scenario and feature
- Given
a file named "features/foo.feature" with: (000ms)
Feature: Feature name
Scenario: Scenario name
Given a step
- And
a file named "features/support/hook.rb" with: (000ms)
names = []
Before do |scenario|
expect(scenario).to_not respond_to(:scenario_outline)
names << scenario.feature.name.split("\n").first
names << scenario.name.split("\n").first
if(names.size == 2)
raise "NAMES:\n" + names.join("\n") + "\n"
end
end
- When
I run cucumber (028ms)
- Then
the output should contain: (000ms)
NAMES: Feature name Scenario name
Examine names of scenario outline and feature
- Given
a file named "features/foo.feature" with: (000ms)
Feature: Feature name
Scenario Outline: Scenario Outline name
Given a <placeholder>
Examples: Examples Table name
| <placeholder> |
| step |
- And
a file named "features/support/hook.rb" with: (000ms)
names = []
Before do |scenario|
names << scenario.scenario_outline.feature.name.split("\n").first
names << scenario.scenario_outline.name.split("\n").first
names << scenario.name.split("\n").first
if(names.size == 3)
raise "NAMES:\n" + names.join("\n") + "\n"
end
end
- When
I run cucumber (015ms)
- Then
the output should contain: (000ms)
NAMES:
Feature name
Scenario Outline name, Examples Table name (#1)
Scenario Outline name, Examples Table name (#1)
Choosing the language from the feature file header
In order to simplify command line and settings in IDEs, Cucumber picks
up the parser language from a # language comment at the beginning of
any feature file. See the examples below for the exact syntax.
LOLCAT
- Given
a file named "features/lolcat.feature" with: (000ms)
# language: en-lol
OH HAI: STUFFING
B4: HUNGRY
I CAN HAZ EMPTY BELLY
MISHUN: CUKES
DEN KTHXBAI
- When
I run cucumber -i features/lolcat.feature -q (010ms)
- Then
it should pass with: (000ms)
# language: en-lol
OH HAI: STUFFING
B4: HUNGRY
I CAN HAZ EMPTY BELLY
MISHUN: CUKES
DEN KTHXBAI
1 scenario (1 undefined)
2 steps (2 undefined)
Cucumber --work-in-progress switch
In order to ensure that feature scenarios do not pass until they are expected to
Developers should be able to run cucumber in a mode that
- will fail if any scenario passes completely
- will not fail otherwise
A passing and a pending feature
tags: @spawn
- Given
the standard step definitions (000ms)
- And
a file named "features/wip.feature" with: (000ms)
Feature: WIP
@failing
Scenario: Failing
Given this step raises an error
@undefined
Scenario: Undefined
Given this step is undefined
@pending
Scenario: Pending
Given this step is pending
@passing
Scenario: Passing
Given this step passes
- And
a file named "features/passing_outline.feature" with: (000ms)
Feature: Not WIP
Scenario Outline: Passing
Given this step <what>
Examples:
| what |
| passes |
Pass with Failing Scenarios
tags: @spawn,@spawn
- When
I run cucumber -q -w -t @failing features/wip.feature (606ms)
- Then
the stderr should not contain anything (000ms)
- Then
it should pass with: (000ms)
Feature: WIP
@failing
Scenario: Failing
Given this step raises an error
error (RuntimeError)
./features/step_definitions/steps.rb:2:in `/^this step raises an error$/'
features/wip.feature:4:in `Given this step raises an error'
Failing Scenarios:
cucumber features/wip.feature:3
1 scenario (1 failed)
1 step (1 failed)
- And
the output should contain: (000ms)
The --wip switch was used, so the failures were expected. All is good.
Pass with Undefined Scenarios
tags: @spawn,@spawn
- When
I run cucumber -q -w -t @undefined features/wip.feature (608ms)
- Then
it should pass with: (000ms)
Feature: WIP
@undefined
Scenario: Undefined
Given this step is undefined
1 scenario (1 undefined)
1 step (1 undefined)
- And
the output should contain: (000ms)
The --wip switch was used, so the failures were expected. All is good.
Pass with Undefined Scenarios
tags: @spawn,@spawn
- When
I run cucumber -q -w -t @pending features/wip.feature (606ms)
- Then
it should pass with: (001ms)
Feature: WIP
@pending
Scenario: Pending
Given this step is pending
TODO (Cucumber::Pending)
./features/step_definitions/steps.rb:3:in `/^this step is pending$/'
features/wip.feature:12:in `Given this step is pending'
1 scenario (1 pending)
1 step (1 pending)
- And
the output should contain: (000ms)
The --wip switch was used, so the failures were expected. All is good.
Fail with Passing Scenarios
tags: @spawn,@spawn
- When
I run cucumber -q -w -t @passing features/wip.feature (607ms)
- Then
it should fail with: (000ms)
Feature: WIP
@passing
Scenario: Passing
Given this step passes
1 scenario (1 passed)
1 step (1 passed)
- And
the output should contain: (000ms)
The --wip switch was used, so I didn't expect anything to pass. These scenarios passed: (::) passed scenarios (::) features/wip.feature:15:in `Scenario: Passing'
Fail with Passing Scenario Outline
tags: @spawn,@spawn
- When
I run cucumber -q -w features/passing_outline.feature (707ms)
- Then
it should fail with: (001ms)
Feature: Not WIP
Scenario Outline: Passing
Given this step <what>
Examples:
| what |
| passes |
1 scenario (1 passed)
1 step (1 passed)
- And
the output should contain: (000ms)
The --wip switch was used, so I didn't expect anything to pass. These scenarios passed: (::) passed scenarios (::) features/passing_outline.feature:7:in `Scenario Outline: Passing, Examples (#1)'
Custom Formatter
Background
- Given
a file named "features/f.feature" with: (000ms)
Feature: I'll use my own
Scenario: Just print me
Given this step passes
- And
the standard step definitions (000ms)
Use the new API
- Given
a file named "features/support/custom_formatter.rb" with: (000ms)
module MyCustom
class Formatter
def initialize(runtime, io, options)
@io = io
end
def before_test_case(test_case)
feature = test_case.source.first
scenario = test_case.source.last
@io.puts feature.short_name.upcase
@io.puts " #{scenario.name.upcase}"
end
end
end
- When
I run cucumber features/f.feature --format MyCustom::Formatter (009ms)
- Then
it should pass with exactly: (000ms)
I'LL USE MY OWN JUST PRINT ME
Use the legacy API
- Given
a file named "features/support/custom_legacy_formatter.rb" with: (000ms)
module MyCustom
class LegacyFormatter
def initialize(runtime, io, options)
@io = io
end
def before_feature(feature)
@io.puts feature.short_name.upcase
end
def scenario_name(keyword, name, file_colon_line, source_indent)
@io.puts " #{name.upcase}"
end
end
end
- When
I run cucumber features/f.feature --format MyCustom::LegacyFormatter (008ms)
- Then
it should pass with exactly: (000ms)
I'LL USE MY OWN JUST PRINT ME
Use both
You can use a specific shim to opt-in to both APIs at once.
- Given
a file named "features/support/custom_mixed_formatter.rb" with: (000ms)
module MyCustom
class MixedFormatter
def initialize(runtime, io, options)
@io = io
end
def before_test_case(test_case)
feature = test_case.source.first
@io.puts feature.short_name.upcase
end
def scenario_name(keyword, name, file_colon_line, source_indent)
@io.puts " #{name.upcase}"
end
end
end
- When
I run cucumber features/f.feature --format MyCustom::MixedFormatter (007ms)
- Then
it should pass with exactly: (000ms)
I'LL USE MY OWN JUST PRINT ME
Custom filter
Add a custom filter via AfterConfiguration hook
- Given
a file named "features/test.feature" with: (000ms)
Feature:
Scenario:
Given my special step
- And
a file named "features/support/my_filter.rb" with: (000ms)
require 'cucumber/core/filter'
MakeAnythingPass = Cucumber::Core::Filter.new do
def test_case(test_case)
activated_steps = test_case.test_steps.map do |test_step|
test_step.with_action { }
end
test_case.with_steps(activated_steps).describe_to receiver
end
end
AfterConfiguration do |config|
config.filters << MakeAnythingPass.new
end
- When
I run cucumber --strict (009ms)
- Then
it should pass (000ms)
Debug formatter
In order to help you easily visualise the listener API, you can use
the debug formatter that prints the calls to the listener as a
feature is run.
title
- Given
a file named "features/test.feature" with: (000ms)
Feature:
Scenario:
Given this step passes
- When
I run cucumber -f debug (007ms)
- Then
the stderr should not contain anything (000ms)
- Then
it should pass with: (000ms)
before_test_case before_features before_feature before_tags after_tags feature_name before_test_step after_test_step before_test_step before_feature_element before_tags after_tags scenario_name before_steps before_step before_step_result step_name after_step_result after_step after_test_step after_steps after_feature_element after_test_case after_feature after_features done
Doc strings
If you need to specify information in a scenario that won’t fit on a single line,
you can use a DocString.
A DocString follows a step, and starts and ends with three double quotes, like this:
When I ask to reset my password
Then I should receive an email with:
"""
Dear bozo,
Please click this link to reset your password
"""
It’s possible to annotate the DocString with the type of content it contains. This is used by
formatting tools like http://relishapp.com which will render the contents of the DocString
appropriately. You specify the content type after the triple quote, like this:
Given there is some Ruby code:
"""ruby
puts "hello world"
"""
You can read the content type from the argument passed into your step definition, as shown
in the example below.
Plain text Docstring
- Given
a scenario with a step that looks like this: (000ms)
Given I have a lot to say: """ One Two Three """
- And
a step definition that looks like this: (000ms)
Given /say/ do |text| puts text end
- When
I run the feature with the progress formatter (010ms)
- Then
the output should contain: (000ms)
One Two Three
DocString with interesting content type
- Given
a scenario with a step that looks like this: (000ms)
Given I have some code for you: """ruby # hello """
- And
a step definition that looks like this: (000ms)
Given /code/ do |text| puts text.content_type end
- When
I run the feature with the progress formatter (008ms)
- Then
the output should contain: (000ms)
ruby
Dry Run
Dry run gives you a way to quickly scan your features without actually running them.
-
Invokes formatters without executing the steps.
-
This also omits the loading of your support/env.rb file if it exists.
With a failing step
- Given
a file named "features/test.feature" with: (000ms)
Feature: test
Scenario:
Given this step fails
- And
the standard step definitions (000ms)
- When
I run cucumber --dry-run (020ms)
- Then
it should pass with exactly: (000ms)
Feature: test
Scenario: # features/test.feature:2
Given this step fails # features/step_definitions/steps.rb:4
1 scenario (1 skipped)
1 step (1 skipped)
In strict mode
- Given
a file named "features/test.feature" with: (000ms)
Feature: test
Scenario:
Given this step fails
- And
the standard step definitions (000ms)
- When
I run cucumber --dry-run --strict (013ms)
- Then
it should pass with exactly: (000ms)
Feature: test
Scenario: # features/test.feature:2
Given this step fails # features/step_definitions/steps.rb:4
1 scenario (1 skipped)
1 step (1 skipped)
In strict mode with an undefined step
- Given
a file named "features/test.feature" with: (000ms)
Feature: test
Scenario:
Given this step is undefined
- When
I run cucumber --dry-run --strict (009ms)
- Then
it should fail with: (000ms)
Feature: test
Scenario: # features/test.feature:2
Given this step is undefined # features/test.feature:3
Undefined step: "this step is undefined" (Cucumber::Undefined)
features/test.feature:3:in `Given this step is undefined'
1 scenario (1 undefined)
1 step (1 undefined)
ERB configuration
As a developer on server with multiple users
I want to be able to configure which port my wire server runs on
So that I can avoid port conflicts
Background
tags: @wire
- Given
a file named "features/wired.feature" with: (000ms)
Feature: High strung
Scenario: Wired
Given we're all wired
ERB is used in the wire file which references an environment variable that is not set
tags: @wire,@wire
- Given
a file named "features/step_definitions/server.wire" with: (000ms)
host: localhost port: <%= ENV['PORT'] || 12345 %>
- And
there is a wire server running on port 12345 which understands the following protocol: (002ms)
- When
I run cucumber --dry-run --no-snippets -f progress (073ms)
- Then
it should pass with: (000ms)
U 1 scenario (1 undefined) 1 step (1 undefined)
ERB is used in the wire file which references an environment variable
tags: @wire,@wire
- Given
I have environment variable PORT set to "16816" (000ms)
- And
a file named "features/step_definitions/server.wire" with: (000ms)
host: localhost port: <%= ENV['PORT'] || 12345 %>
- And
there is a wire server running on port 16816 which understands the following protocol: (002ms)
- When
I run cucumber --dry-run --no-snippets -f progress (061ms)
- Then
it should pass with: (001ms)
U 1 scenario (1 undefined) 1 step (1 undefined)
Exception in After Block
In order to use custom assertions at the end of each scenario
As a developer
I want exceptions raised in After blocks to be handled gracefully and reported by the formatters
Background
- Given
the standard step definitions (000ms)
- And
a file named "features/step_definitions/naughty_steps.rb" with: (000ms)
Given /^this step does something naughty$/ do x=1 @naughty = true end
- And
a file named "features/support/env.rb" with: (000ms)
class NaughtyScenarioException < Exception; end
After do
if @naughty
raise NaughtyScenarioException.new("This scenario has been very very naughty")
end
end
Handle Exception in standard scenario step and carry on
tags: @spawn
- Given
a file named "features/naughty_step_in_scenario.feature" with: (000ms)
Feature: Sample
Scenario: Naughty Step
Given this step does something naughty
Scenario: Success
Given this step passes
- When
I run cucumber features (604ms)
- Then
it should fail with: (000ms)
Feature: Sample
Scenario: Naughty Step # features/naughty_step_in_scenario.feature:3
Given this step does something naughty # features/step_definitions/naughty_steps.rb:1
This scenario has been very very naughty (NaughtyScenarioException)
./features/support/env.rb:4:in `After'
Scenario: Success # features/naughty_step_in_scenario.feature:6
Given this step passes # features/step_definitions/steps.rb:1
Failing Scenarios:
cucumber features/naughty_step_in_scenario.feature:3 # Scenario: Naughty Step
2 scenarios (1 failed, 1 passed)
2 steps (2 passed)
Handle Exception in scenario outline table row and carry on
tags: @spawn
- Given
a file named "features/naughty_step_in_scenario_outline.feature" with: (000ms)
Feature: Sample
Scenario Outline: Naughty Step
Given this step <Might Work>
Examples:
| Might Work |
| passes |
| does something naughty |
| passes |
Scenario: Success
Given this step passes
- When
I run cucumber features -q (606ms)
- Then
it should fail with: (000ms)
Feature: Sample
Scenario Outline: Naughty Step
Given this step <Might Work>
Examples:
| Might Work |
| passes |
| does something naughty |
This scenario has been very very naughty (NaughtyScenarioException)
./features/support/env.rb:4:in `After'
| passes |
Scenario: Success
Given this step passes
Failing Scenarios:
cucumber features/naughty_step_in_scenario_outline.feature:9
4 scenarios (1 failed, 3 passed)
4 steps (4 passed)
Handle Exception using the progress format
- Given
a file named "features/naughty_step_in_scenario.feature" with: (000ms)
Feature: Sample
Scenario: Naughty Step
Given this step does something naughty
Scenario: Success
Given this step passes
- When
I run cucumber features --format progress (026ms)
- Then
it should fail with: (000ms)
.F. Failing Scenarios: cucumber features/naughty_step_in_scenario.feature:3 # Scenario: Naughty Step 2 scenarios (1 failed, 1 passed) 2 steps (2 passed)
Exception in AfterStep Block
In order to use custom assertions at the end of each step
As a developer
I want exceptions raised in AfterStep blocks to be handled gracefully and reported by the formatters
Background
- Given
the standard step definitions (000ms)
- And
a file named "features/step_definitions/naughty_steps.rb" with: (000ms)
Given /^this step does something naughty$/ do x=1 @naughty = true end
- And
a file named "features/support/env.rb" with: (000ms)
class NaughtyStepException < Exception; end
AfterStep do
if @naughty
raise NaughtyStepException.new("This step has been very very naughty")
end
end
Handle Exception in standard scenario step and carry on
- Given
a file named "features/naughty_step_in_scenario.feature" with: (000ms)
Feature: Sample
Scenario: Naughty Step
Given this step does something naughty
Scenario: Success
Given this step passes
- When
I run cucumber features (021ms)
- Then
it should fail with: (000ms)
Feature: Sample
Scenario: Naughty Step # features/naughty_step_in_scenario.feature:3
Given this step does something naughty # features/step_definitions/naughty_steps.rb:1
This step has been very very naughty (NaughtyStepException)
./features/support/env.rb:4:in `AfterStep'
features/naughty_step_in_scenario.feature:4:in `Given this step does something naughty'
Scenario: Success # features/naughty_step_in_scenario.feature:6
Given this step passes # features/step_definitions/steps.rb:1
Failing Scenarios:
cucumber features/naughty_step_in_scenario.feature:3 # Scenario: Naughty Step
2 scenarios (1 failed, 1 passed)
2 steps (2 passed)
Handle Exception in scenario outline table row and carry on
- Given
a file named "features/naughty_step_in_scenario_outline.feature" with: (000ms)
Feature: Sample
Scenario Outline: Naughty Step
Given this step <Might Work>
Examples:
| Might Work |
| passes |
| does something naughty |
| passes |
Scenario: Success
Given this step passes
- When
I run cucumber features (022ms)
- Then
it should fail with: (000ms)
Feature: Sample
Scenario Outline: Naughty Step # features/naughty_step_in_scenario_outline.feature:3
Given this step <Might Work> # features/naughty_step_in_scenario_outline.feature:4
Examples:
| Might Work |
| passes |
| does something naughty |
This step has been very very naughty (NaughtyStepException)
./features/support/env.rb:4:in `AfterStep'
features/naughty_step_in_scenario_outline.feature:9:in `Given this step does something naughty'
features/naughty_step_in_scenario_outline.feature:4:in `Given this step <Might Work>'
| passes |
Scenario: Success # features/naughty_step_in_scenario_outline.feature:12
Given this step passes # features/step_definitions/steps.rb:1
Failing Scenarios:
cucumber features/naughty_step_in_scenario_outline.feature:9 # Scenario Outline: Naughty Step, Examples (#2)
4 scenarios (1 failed, 3 passed)
4 steps (4 passed)
Exception in Before Block
In order to know with confidence that my before blocks have run OK
As a developer
I want exceptions raised in Before blocks to be handled gracefully and reported by the formatters
Background
- Given
the standard step definitions (000ms)
- And
a file named "features/support/env.rb" with: (000ms)
class SomeSetupException < Exception; end
class BadStepException < Exception; end
Before do
raise SomeSetupException.new("I cannot even start this scenario")
end
Handle Exception in standard scenario step and carry on
tags: @spawn
- Given
a file named "features/naughty_step_in_scenario.feature" with: (000ms)
Feature: Sample
Scenario: Run a good step
Given this step passes
- When
I run cucumber features (605ms)
- Then
it should fail with: (001ms)
Feature: Sample
Scenario: Run a good step # features/naughty_step_in_scenario.feature:3
I cannot even start this scenario (SomeSetupException)
./features/support/env.rb:4:in `Before'
Given this step passes # features/step_definitions/steps.rb:1
Failing Scenarios:
cucumber features/naughty_step_in_scenario.feature:3 # Scenario: Run a good step
1 scenario (1 failed)
1 step (1 skipped)
Handle Exception in Before hook for Scenario with Background
- Given
a file named "features/naughty_step_in_before.feature" with: (000ms)
Feature: Sample
Background:
Given this step passes
Scenario: Run a good step
Given this step passes
- When
I run cucumber features (023ms)
- Then
it should fail with exactly: (000ms)
Feature: Sample
Background: # features/naughty_step_in_before.feature:3
I cannot even start this scenario (SomeSetupException)
./features/support/env.rb:4:in `Before'
Given this step passes # features/step_definitions/steps.rb:1
Scenario: Run a good step # features/naughty_step_in_before.feature:6
Given this step passes # features/step_definitions/steps.rb:1
Failing Scenarios:
cucumber features/naughty_step_in_before.feature:6 # Scenario: Run a good step
1 scenario (1 failed)
2 steps (2 skipped)
0m0.012s
Handle Exception using the progress format
- Given
a file named "features/naughty_step_in_scenario.feature" with: (000ms)
Feature: Sample
Scenario: Run a good step
Given this step passes
- When
I run cucumber features --format progress (016ms)
- Then
it should fail with: (000ms)
F- Failing Scenarios: cucumber features/naughty_step_in_scenario.feature:3 # Scenario: Run a good step 1 scenario (1 failed) 1 step (1 skipped)
Exceptions in Around Hooks
Around hooks are awkward beasts to handle internally.
Right now, if there’s an error in your Around hook before you call block.call,
we won’t even print the steps for the scenario.
This is because that block.call invokes all the logic that would tell Cucumber’s
UI about the steps in your scenario. If we never reach that code, we’ll never be
told about them.
There’s another scenario to consider, where the exception occurs after the steps
have been run. How would we want to report in that case?
Exception before the test case is run
- Given
the standard step definitions (000ms)
- And
a file named "features/support/env.rb" with: (000ms)
Around do |scenario, block| fail "this should be reported" block.call end
- And
a file named "features/test.feature" with: (000ms)
Feature:
Scenario:
Given this step passes
- When
I run cucumber -q (010ms)
- Then
it should fail with exactly: (000ms)
Feature: Scenario: this should be reported (RuntimeError) ./features/support/env.rb:2:in `Around' Failing Scenarios: cucumber features/test.feature:2 1 scenario (1 failed) 0 steps
Exception after the test case is run
- Given
the standard step definitions (000ms)
- And
a file named "features/support/env.rb" with: (000ms)
Around do |scenario, block| block.call fail "this should be reported" end
- And
a file named "features/test.feature" with: (000ms)
Feature:
Scenario:
Given this step passes
- When
I run cucumber -q (009ms)
- Then
it should fail with exactly: (000ms)
Feature:
Scenario:
Given this step passes
this should be reported (RuntimeError)
./features/support/env.rb:3:in `Around'
Failing Scenarios:
cucumber features/test.feature:2
1 scenario (1 failed)
1 step (1 passed)
Excluding ruby and feature files from runs
Developers are able to easily exclude files from cucumber runs
This is a nice feature to have in conjunction with profiles, so you can exclude
certain environment files from certain runs.
exclude ruby files
- Given
an empty file named "features/support/dont_require_me.rb" (000ms)
- And
an empty file named "features/step_definitions/fooz.rb" (000ms)
- And
an empty file named "features/step_definitions/foof.rb" (000ms)
- And
an empty file named "features/step_definitions/foot.rb" (000ms)
- And
an empty file named "features/support/require_me.rb" (000ms)
- When
I run cucumber features -q --verbose --exclude features/support/dont --exclude foo[zf] (007ms)
- Then
"features/support/require_me.rb" should be required (000ms)
- And
"features/step_definitions/foot.rb" should be required (000ms)
- And
"features/support/dont_require_me.rb" should not be required (000ms)
- And
"features/step_definitions/foof.rb" should not be required (000ms)
- And
"features/step_definitions/fooz.rb" should not be required (000ms)
[[Formatter-API:-Step-file-path-and-line-number-(Issue-#179), Formatter API: Step file path and line number (Issue #179)]]
=== Formatter API: Step file path and line number (Issue #179)
To all reporter to understand location of current executing step let’s fetch this information
from step/step_invocation and pass to reporters
my own formatter
- Given
a file named "features/f.feature" with: (000ms)
Feature: I'll use my own
because I'm worth it
Scenario: just print step current line and feature file name
Given step at line 4
Given step at line 5
- And
a file named "features/step_definitions/steps.rb" with: (000ms)
Given(/^step at line (.*)$/) {|line| }
- And
a file named "features/support/jb/formatter.rb" with: (000ms)
module Jb
class Formatter
def initialize(runtime, io, options)
@io = io
end
def before_step_result(keyword, step_match, multiline_arg, status, exception, source_indent, background, file_colon_line)
@io.puts "step result event: #{file_colon_line}"
end
def step_name(keyword, step_match, status, source_indent, background, file_colon_line)
@io.puts "step name event: #{file_colon_line}"
end
end
end
- When
I run cucumber features/f.feature --format Jb::Formatter (006ms)
- Then
it should pass with exactly: (000ms)
step result event: features/f.feature:4 step name event: features/f.feature:4 step result event: features/f.feature:5 step name event: features/f.feature:5
Getting started
To get started, just open a command prompt in an empty directory and run
cucumber. You’ll be prompted for what to do next.
Run Cucumber in an empty directory
tags: @spawn
- Given
a directory without standard Cucumber project directory structure (000ms)
- When
I run cucumber (605ms)
- Then
it should fail with: (001ms)
No such file or directory - features. You can use `cucumber --init` to get started.
Accidentally run Cucumber in a folder with Ruby files in it.
- Given
a directory without standard Cucumber project directory structure (000ms)
- And
a file named "should_not_load.rb" with: (000ms)
puts 'this will not be shown'
- When
I run cucumber (007ms)
- Then
the exit status should be 2 (000ms)
- And
the output should not contain: (000ms)
this will not be shown
HTML output formatter
Background
- Given
the standard step definitions (000ms)
- And
a file named "features/scenario_outline_with_undefined_steps.feature" with: (000ms)
Feature:
Scenario Outline:
Given this step is undefined
Examples:
|foo|
|bar|
- And
a file named "features/scenario_outline_with_pending_step.feature" with: (000ms)
Feature: Outline
Scenario Outline: Will it blend?
Given this step is pending
And other step
When I do something with <example>
Then I should see something
Examples:
| example |
| one |
| two |
| three |
- And
a file named "features/failing_background_step.feature" with: (000ms)
Feature: Feature with failing background step
Background:
Given this step fails
Scenario:
When I do something
Then I should see something
an scenario outline, one undefined step, one random example, expand flag on
- When
I run `cucumber features/scenario_outline_with_undefined_steps.feature --format html --expand ` (020ms)
- Then
it should pass (003ms)
an scenario outline, one pending step
- When
I run cucumber features/scenario_outline_with_pending_step.feature --format html --expand (025ms)
- Then
it should pass (003ms)
- And
the output should contain: (004ms)
makeYellow('scenario_1')
- And
the output should not contain: (004ms)
makeRed('scenario_1')
an scenario outline, one pending step
- When
I run `cucumber features/scenario_outline_with_pending_step.feature --format html ` (019ms)
- Then
it should pass (002ms)
- And
the output should contain: (003ms)
makeYellow('scenario_1')
- And
the output should not contain: (004ms)
makeRed('scenario_1')
an scenario outline, one pending step
- When
I run cucumber features/scenario_outline_with_undefined_steps.feature --format html --expand (007ms)
- Then
it should pass (002ms)
- And
the output should contain: (003ms)
makeYellow('scenario_1')
- And
the output should not contain: (003ms)
makeRed('scenario_1')
an scenario outline, one pending step
- When
I run `cucumber features/scenario_outline_with_undefined_steps.feature --format html ` (009ms)
- Then
it should pass (002ms)
- And
the output should contain: (003ms)
makeYellow('scenario_1')
- And
the output should not contain: (003ms)
makeRed('scenario_1')
when using a profile the html shouldn’t include 'Using the default profile…'
- And
a file named "cucumber.yml" with: (000ms)
default: -r features
- When
I run cucumber features/scenario_outline_with_undefined_steps.feature --profile default --format html (009ms)
- Then
it should pass (002ms)
- And
the output should not contain: (003ms)
Using the default profile...
Handle unexpected response
When the server sends us back a message we don’t understand, this is how Cucumber will behave.
Hooks execute in defined order
Background
tags: @spawn
- Given
a file named "features/step_definitions/steps.rb" with: (000ms)
Given /^background step$/ do; $EventOrder.push(:background_step) end Given /^scenario step$/ do; $EventOrder.push(:scenario_step) end
- And
a file named "features/support/hooks.rb" with: (000ms)
$EventOrder = []
Around('@around') do |scenario,block|
$EventOrder.push :around_begin
block.call
$EventOrder.push :around_end
end
Before('@before') do
$EventOrder.push :before
end
After('@after') do |scenario|
$EventOrder.push :after
end
at_exit {
puts "Event order: #{$EventOrder.join(' ')}"
}
- And
a file named "features/around_hook_covers_background.feature" with: (000ms)
@around
Feature: Around hooks cover background steps
Background:
Given background step
Scenario:
Given scenario step
- And
a file named "features/all_hook_order.feature" with: (000ms)
@around
@before
@after
Feature: All hooks execute in expected order
Background:
Given background step
Scenario:
Given scenario step
Invoke message
Assuming a StepMatch was returned for a given step name, when it’s time to
invoke that step definition, Cucumber will send an invoke message.
The invoke message contains the ID of the step definition, as returned by
the wire server in response to the the step_matches call, along with the
arguments that were parsed from the step name during the same step_matches
call.
The wire server will normally reply one of the following:
-
success -
fail -
pending- optionally takes a message argument
This isn’t quite the whole story: see also table_diffing.feature
Background
tags: @wire
- Given
a file named "features/wired.feature" with: (000ms)
Feature: High strung
Scenario: Wired
Given we're all wired
- And
a file named "features/step_definitions/some_remote_place.wire" with: (000ms)
host: localhost port: 54321
Invoke a step definition which is pending
tags: @wire,@wire,@spawn
- Given
there is a wire server running on port 54321 which understands the following protocol: (001ms)
- When
I run cucumber -f pretty -q (806ms)
- And
it should pass with: (001ms)
Feature: High strung
Scenario: Wired
Given we're all wired
I'll do it later (Cucumber::Pending)
features/wired.feature:3:in `Given we're all wired'
1 scenario (1 pending)
1 step (1 pending)
Invoke a step definition which passes
tags: @wire,@wire
- Given
there is a wire server running on port 54321 which understands the following protocol: (002ms)
- When
I run cucumber -f progress (140ms)
- And
it should pass with: (000ms)
. 1 scenario (1 passed) 1 step (1 passed)
Invoke a step definition which fails
tags: @wire,@wire,@spawn
If an invoked step definition fails, it can return details of the exception
in the reply to invoke. This causes a Cucumber::WireSupport::WireException to be
raised.
Valid arguments are:
-
message(mandatory) -
exception -
backtrace
See the specs for Cucumber::WireSupport::WireException for more details
- Given
there is a wire server running on port 54321 which understands the following protocol: (002ms)
- When
I run cucumber -f progress (808ms)
- Then
the stderr should not contain anything (000ms)
- And
it should fail with: (001ms)
F (::) failed steps (::) The wires are down (Some.Foreign.ExceptionType from localhost:54321) features/wired.feature:3:in `Given we're all wired' Failing Scenarios: cucumber features/wired.feature:2 # Scenario: Wired 1 scenario (1 failed) 1 step (1 failed)
Invoke a step definition which takes string arguments (and passes)
tags: @wire,@wire
If the step definition at the end of the wire captures arguments, these are
communicated back to Cucumber in the step_matches message.
Cucumber expects these StepArguments to be returned in the StepMatch. The keys
have the following meanings:
-
val- the value of the string captured for that argument from the step
name passed in step_matches -
pos- the position within the step name that the argument was matched
(used for formatter highlighting)
The argument values are then sent back by Cucumber in the invoke message.
- Given
there is a wire server running on port 54321 which understands the following protocol: (002ms)
- When
I run cucumber -f progress (141ms)
- Then
the stderr should not contain anything (000ms)
- And
it should pass with: (000ms)
. 1 scenario (1 passed) 1 step (1 passed)
Invoke a step definition which takes regular and table arguments (and passes)
tags: @wire,@wire
If the step has a multiline table argument, it will be passed with the
invoke message as an array of array of strings.
In this scenario our step definition takes two arguments - one
captures the "we’re" and the other takes the table.
- Given
a file named "features/wired_on_tables.feature" with: (000ms)
Feature: High strung
Scenario: Wired and more
Given we're all:
| wired |
| high |
| happy |
- And
there is a wire server running on port 54321 which understands the following protocol: (002ms)
- When
I run cucumber -f progress features/wired_on_tables.feature (139ms)
- Then
the stderr should not contain anything (000ms)
- And
it should pass with: (001ms)
. 1 scenario (1 passed) 1 step (1 passed)
Invoke a scenario outline step
tags: @wire,@wire
- Given
a file named "features/wired_in_an_outline.feature" with: (000ms)
Feature:
Scenario Outline:
Given we're all <arg>
Examples:
| arg |
| wired |
- And
there is a wire server running on port 54321 which understands the following protocol: (002ms)
- When
I run cucumber -f progress features/wired_in_an_outline.feature (146ms)
- Then
the stderr should not contain anything (000ms)
- And
it should pass with: (000ms)
. 1 scenario (1 passed) 1 step (1 passed)
- And
the wire server should have received the following messages: (000ms)
JSON output formatter
In order to simplify processing of Cucumber features and results
Developers should be able to consume features as JSON
Background
- Given
the standard step definitions (000ms)
- And
a file named "features/one_passing_one_failing.feature" with: (000ms)
@a
Feature: One passing scenario, one failing scenario
@b
Scenario: Passing
Given this step passes
@c
Scenario: Failing
Given this step fails
- And
a file named "features/step_definitions/json_steps.rb" with: (000ms)
Given /^I embed a screenshot/ do
File.open("screenshot.png", "w") { |file| file << "foo" }
embed "screenshot.png", "image/png"
end
Given /^I print from step definition/ do
puts "from step definition"
end
Given /^I embed data directly/ do
data = "YWJj"
embed data, "mime-type;base64"
end
- And
a file named "features/embed.feature" with: (000ms)
Feature: A screenshot feature
Scenario:
Given I embed a screenshot
- And
a file named "features/outline.feature" with: (000ms)
Feature: An outline feature
Scenario Outline: outline
Given this step <status>
Examples: examples1
| status |
| passes |
| fails |
Examples: examples2
| status |
| passes |
- And
a file named "features/print_from_step_definition.feature" with: (000ms)
Feature: A print from step definition feature
Scenario:
Given I print from step definition
And I print from step definition
- And
a file named "features/print_from_step_definition.feature" with: (000ms)
Feature: A print from step definition feature
Scenario:
Given I print from step definition
And I print from step definition
- And
a file named "features/embed_data_directly.feature" with: (000ms)
Feature: An embed data directly feature
Scenario:
Given I embed data directly
Scenario Outline:
Given I embed data directly
Examples:
| dummy |
| 1 |
| 2 |
- And
a file named "features/out_scenario_out_scenario_outline.feature" with: (000ms)
Feature:
Scenario:
Given this step passes
Scenario Outline:
Given this step <status>
Examples:
| status |
| passes |
one feature, one passing scenario, one failing scenario
tags: @spawn
- When
I run cucumber --format json features/one_passing_one_failing.feature (605ms)
- Then
it should fail with JSON: (001ms)
[
{
"uri": "features/one_passing_one_failing.feature",
"keyword": "Feature",
"id": "one-passing-scenario,-one-failing-scenario",
"name": "One passing scenario, one failing scenario",
"line": 2,
"description": "",
"tags": [
{
"name": "@a",
"line": 1
}
],
"elements": [
{
"keyword": "Scenario",
"id": "one-passing-scenario,-one-failing-scenario;passing",
"name": "Passing",
"line": 5,
"description": "",
"tags": [
{
"name": "@a",
"line": 1
},
{
"name": "@b",
"line": 4
}
],
"type": "scenario",
"steps": [
{
"keyword": "Given ",
"name": "this step passes",
"line": 6,
"match": {
"location": "features/step_definitions/steps.rb:1"
},
"result": {
"status": "passed",
"duration": 1
}
}
]
},
{
"keyword": "Scenario",
"id": "one-passing-scenario,-one-failing-scenario;failing",
"name": "Failing",
"line": 9,
"description": "",
"tags": [
{
"name": "@a",
"line": 1
},
{
"name": "@c",
"line": 8
}
],
"type": "scenario",
"steps": [
{
"keyword": "Given ",
"name": "this step fails",
"line": 10,
"match": {
"location": "features/step_definitions/steps.rb:4"
},
"result": {
"status": "failed",
"error_message": " (RuntimeError)\n./features/step_definitions/steps.rb:4:in `/^this step fails$/'\nfeatures/one_passing_one_failing.feature:10:in `Given this step fails'",
"duration": 1
}
}
]
}
]
}
]
one feature, one passing scenario, one failing scenario with prettyfied json
tags: @spawn
- When
I run cucumber --format json_pretty features/one_passing_one_failing.feature (505ms)
- Then
it should fail with JSON: (002ms)
[
{
"uri": "features/one_passing_one_failing.feature",
"keyword": "Feature",
"id": "one-passing-scenario,-one-failing-scenario",
"name": "One passing scenario, one failing scenario",
"line": 2,
"description": "",
"tags": [
{
"name": "@a",
"line": 1
}
],
"elements": [
{
"keyword": "Scenario",
"id": "one-passing-scenario,-one-failing-scenario;passing",
"name": "Passing",
"line": 5,
"description": "",
"tags": [
{
"name": "@a",
"line": 1
},
{
"name": "@b",
"line": 4
}
],
"type": "scenario",
"steps": [
{
"keyword": "Given ",
"name": "this step passes",
"line": 6,
"match": {
"location": "features/step_definitions/steps.rb:1"
},
"result": {
"status": "passed",
"duration": 1
}
}
]
},
{
"keyword": "Scenario",
"id": "one-passing-scenario,-one-failing-scenario;failing",
"name": "Failing",
"line": 9,
"description": "",
"tags": [
{
"name": "@a",
"line": 1
},
{
"name": "@c",
"line": 8
}
],
"type": "scenario",
"steps": [
{
"keyword": "Given ",
"name": "this step fails",
"line": 10,
"match": {
"location": "features/step_definitions/steps.rb:4"
},
"result": {
"status": "failed",
"error_message": " (RuntimeError)\n./features/step_definitions/steps.rb:4:in `/^this step fails$/'\nfeatures/one_passing_one_failing.feature:10:in `Given this step fails'",
"duration": 1
}
}
]
}
]
}
]
DocString
tags: @spawn
- Given
a file named "features/doc_string.feature" with: (000ms)
Feature: A DocString feature
Scenario:
Then I should fail with
"""
a string
"""
- And
a file named "features/step_definitions/steps.rb" with: (000ms)
Then /I should fail with/ do |s| raise RuntimeError, s end
- When
I run cucumber --format json features/doc_string.feature (605ms)
- Then
it should fail with JSON: (001ms)
[
{
"id": "a-docstring-feature",
"uri": "features/doc_string.feature",
"keyword": "Feature",
"name": "A DocString feature",
"line": 1,
"description": "",
"elements": [
{
"id": "a-docstring-feature;",
"keyword": "Scenario",
"name": "",
"line": 3,
"description": "",
"type": "scenario",
"steps": [
{
"keyword": "Then ",
"name": "I should fail with",
"line": 4,
"doc_string": {
"content_type": "",
"value": "a string",
"line": 5
},
"match": {
"location": "features/step_definitions/steps.rb:1"
},
"result": {
"status": "failed",
"error_message": "a string (RuntimeError)\n./features/step_definitions/steps.rb:2:in `/I should fail with/'\nfeatures/doc_string.feature:4:in `Then I should fail with'",
"duration": 1
}
}
]
}
]
}
]
embedding screenshot
tags: @spawn
- When
I run cucumber -b --format json features/embed.feature (606ms)
- Then
it should pass with JSON: (001ms)
[
{
"uri": "features/embed.feature",
"id": "a-screenshot-feature",
"keyword": "Feature",
"name": "A screenshot feature",
"line": 1,
"description": "",
"elements": [
{
"id": "a-screenshot-feature;",
"keyword": "Scenario",
"name": "",
"line": 3,
"description": "",
"type": "scenario",
"steps": [
{
"keyword": "Given ",
"name": "I embed a screenshot",
"line": 4,
"embeddings": [
{
"mime_type": "image/png",
"data": "Zm9v"
}
],
"match": {
"location": "features/step_definitions/json_steps.rb:1"
},
"result": {
"status": "passed",
"duration": 1
}
}
]
}
]
}
]
scenario outline
tags: @spawn
- When
I run cucumber --format json features/outline.feature (606ms)
- Then
it should fail with JSON: (002ms)
[
{
"uri": "features/outline.feature",
"id": "an-outline-feature",
"keyword": "Feature",
"name": "An outline feature",
"line": 1,
"description": "",
"elements": [
{
"id": "an-outline-feature;outline;examples1;2",
"keyword": "Scenario Outline",
"name": "outline",
"description": "",
"line": 8,
"type": "scenario",
"steps": [
{
"keyword": "Given ",
"name": "this step passes",
"line": 8,
"match": {
"location": "features/step_definitions/steps.rb:1"
},
"result": {
"status": "passed",
"duration": 1
}
}
]
},
{
"id": "an-outline-feature;outline;examples1;3",
"keyword": "Scenario Outline",
"name": "outline",
"description": "",
"line": 9,
"type": "scenario",
"steps": [
{
"keyword": "Given ",
"name": "this step fails",
"line": 9,
"match": {
"location": "features/step_definitions/steps.rb:4"
},
"result": {
"status": "failed",
"error_message": " (RuntimeError)\n./features/step_definitions/steps.rb:4:in `/^this step fails$/'\nfeatures/outline.feature:9:in `Given this step fails'\nfeatures/outline.feature:4:in `Given this step <status>'",
"duration": 1
}
}
]
},
{
"id": "an-outline-feature;outline;examples2;2",
"keyword": "Scenario Outline",
"name": "outline",
"description": "",
"line": 13,
"type": "scenario",
"steps": [
{
"keyword": "Given ",
"name": "this step passes",
"line": 13,
"match": {
"location": "features/step_definitions/steps.rb:1"
},
"result": {
"status": "passed",
"duration": 1
}
}
]
}
]
}
]
print from step definition
- When
I run cucumber --format json features/print_from_step_definition.feature (013ms)
- Then
it should pass with JSON: (000ms)
[
{
"uri": "features/print_from_step_definition.feature",
"id": "a-print-from-step-definition-feature",
"keyword": "Feature",
"name": "A print from step definition feature",
"line": 1,
"description": "",
"elements": [
{
"id": "a-print-from-step-definition-feature;",
"keyword": "Scenario",
"name": "",
"line": 3,
"description": "",
"type": "scenario",
"steps": [
{
"keyword": "Given ",
"name": "I print from step definition",
"line": 4,
"output": [
"from step definition"
],
"match": {
"location": "features/step_definitions/json_steps.rb:6"
},
"result": {
"status": "passed",
"duration": 1
}
},
{
"keyword": "And ",
"name": "I print from step definition",
"line": 5,
"output": [
"from step definition"
],
"match": {
"location": "features/step_definitions/json_steps.rb:6"
},
"result": {
"status": "passed",
"duration": 1
}
}
]
}
]
}
]
scenario outline expanded
tags: @spawn
- When
I run cucumber --expand --format json features/outline.feature (707ms)
- Then
it should fail with JSON: (002ms)
[
{
"uri": "features/outline.feature",
"id": "an-outline-feature",
"keyword": "Feature",
"name": "An outline feature",
"line": 1,
"description": "",
"elements": [
{
"id": "an-outline-feature;outline;examples1;2",
"keyword": "Scenario Outline",
"name": "outline",
"line": 8,
"description": "",
"type": "scenario",
"steps": [
{
"keyword": "Given ",
"name": "this step passes",
"line": 8,
"match": {
"location": "features/step_definitions/steps.rb:1"
},
"result": {
"status": "passed",
"duration": 1
}
}
]
},
{
"id": "an-outline-feature;outline;examples1;3",
"keyword": "Scenario Outline",
"name": "outline",
"line": 9,
"description": "",
"type": "scenario",
"steps": [
{
"keyword": "Given ",
"name": "this step fails",
"line": 9,
"match": {
"location": "features/step_definitions/steps.rb:4"
},
"result": {
"status": "failed",
"error_message" : " (RuntimeError)\n./features/step_definitions/steps.rb:4:in `/^this step fails$/'\nfeatures/outline.feature:9:in `Given this step fails'\nfeatures/outline.feature:4:in `Given this step <status>'",
"duration": 1
}
}
]
},
{
"id": "an-outline-feature;outline;examples2;2",
"keyword": "Scenario Outline",
"name": "outline",
"line": 13,
"description": "",
"type": "scenario",
"steps": [
{
"keyword": "Given ",
"name": "this step passes",
"line": 13,
"match": {
"location": "features/step_definitions/steps.rb:1"
},
"result": {
"status": "passed",
"duration": 1
}
}
]
}
]
}
]
embedding data directly
tags: @spawn
- When
I run cucumber -b --format json -x features/embed_data_directly.feature (607ms)
- Then
it should pass with JSON: (002ms)
[
{
"uri": "features/embed_data_directly.feature",
"id": "an-embed-data-directly-feature",
"keyword": "Feature",
"name": "An embed data directly feature",
"line": 1,
"description": "",
"elements": [
{
"id": "an-embed-data-directly-feature;",
"keyword": "Scenario",
"name": "",
"line": 3,
"description": "",
"type": "scenario",
"steps": [
{
"keyword": "Given ",
"name": "I embed data directly",
"line": 4,
"embeddings": [
{
"mime_type": "mime-type",
"data": "YWJj"
}
],
"match": {
"location": "features/step_definitions/json_steps.rb:10"
},
"result": {
"status": "passed",
"duration": 1
}
}
]
},
{
"keyword": "Scenario Outline",
"name": "",
"line": 11,
"description": "",
"id": "an-embed-data-directly-feature;;;2",
"type": "scenario",
"steps": [
{
"keyword": "Given ",
"name": "I embed data directly",
"line": 11,
"embeddings": [
{
"mime_type": "mime-type",
"data": "YWJj"
}
],
"match": {
"location": "features/step_definitions/json_steps.rb:10"
},
"result": {
"status": "passed",
"duration": 1
}
}
]
},
{
"keyword": "Scenario Outline",
"name": "",
"line": 12,
"description": "",
"id": "an-embed-data-directly-feature;;;3",
"type": "scenario",
"steps": [
{
"keyword": "Given ",
"name": "I embed data directly",
"line": 12,
"embeddings": [
{
"mime_type": "mime-type",
"data": "YWJj"
}
],
"match": {
"location": "features/step_definitions/json_steps.rb:10"
},
"result": {
"status": "passed",
"duration": 1
}
}
]
}
]
}
]
handle output from hooks
tags: @spawn
- Given
a file named "features/step_definitions/output_steps.rb" with: (000ms)
Before do puts "Before hook 1" embed "src", "mime_type", "label" end Before do puts "Before hook 2" embed "src", "mime_type", "label" end AfterStep do puts "AfterStep hook 1" embed "src", "mime_type", "label" end AfterStep do puts "AfterStep hook 2" embed "src", "mime_type", "label" end After do puts "After hook 1" embed "src", "mime_type", "label" end After do puts "After hook 2" embed "src", "mime_type", "label" end
- When
I run cucumber --format json features/out_scenario_out_scenario_outline.feature (707ms)
- Then
it should pass (001ms)
JUnit output formatter
In order for developers to create test reports with ant
Cucumber should be able to output JUnit xml files
Background
tags: @spawn
- Given
the standard step definitions (000ms)
- And
a file named "features/one_passing_one_failing.feature" with: (000ms)
Feature: One passing scenario, one failing scenario
Scenario: Passing
Given this step passes
Scenario: Failing
Given this step fails
- And
a file named "features/some_subdirectory/one_passing_one_failing.feature" with: (000ms)
Feature: Subdirectory - One passing scenario, one failing scenario
Scenario: Passing
Given this step passes
Scenario: Failing
Given this step fails
- And
a file named "features/pending.feature" with: (000ms)
Feature: Pending step
Scenario: Pending
Given this step is pending
Scenario: Undefined
Given this step is undefined
- And
a file named "features/pending.feature" with: (000ms)
Feature: Pending step
Scenario: Pending
Given this step is pending
Scenario: Undefined
Given this step is undefined
- And
a file named "features/scenario_outline.feature" with: (000ms)
Feature: Scenario outlines
Scenario Outline: Using scenario outlines
Given this step <type>
Examples:
| type |
| passes |
| fails |
| is pending |
| is undefined |
one feature, one passing scenario, one failing scenario
tags: @spawn,@spawn
- When
I run cucumber --format junit --out tmp/ features/one_passing_one_failing.feature (706ms)
- Then
it should fail with: (001ms)
- And
the junit output file "tmp/TEST-features-one_passing_one_failing.xml" should contain: (000ms)
<?xml version="1.0" encoding="UTF-8"?>
<testsuite failures="1" errors="0" skipped="0" tests="2" time="0.05" name="One passing scenario, one failing scenario">
<testcase classname="One passing scenario, one failing scenario" name="Passing" time="0.05">
<system-out>
<![CDATA[]]>
</system-out>
<system-err>
<![CDATA[]]>
</system-err>
</testcase>
<testcase classname="One passing scenario, one failing scenario" name="Failing" time="0.05">
<failure message="failed Failing" type="failed">
<![CDATA[Scenario: Failing
Given this step fails
Message:
]]>
<![CDATA[ (RuntimeError)
./features/step_definitions/steps.rb:4:in `/^this step fails$/'
features/one_passing_one_failing.feature:7:in `Given this step fails']]>
</failure>
<system-out>
<![CDATA[]]>
</system-out>
<system-err>
<![CDATA[]]>
</system-err>
</testcase>
</testsuite>
one feature in a subdirectory, one passing scenario, one failing scenario
tags: @spawn,@spawn
- When
I run cucumber --format junit --out tmp/ features/some_subdirectory/one_passing_one_failing.feature --require features (607ms)
- Then
it should fail with: (000ms)
- And
the junit output file "tmp/TEST-features-some_subdirectory-one_passing_one_failing.xml" should contain: (000ms)
<?xml version="1.0" encoding="UTF-8"?>
<testsuite failures="1" errors="0" skipped="0" tests="2" time="0.05" name="Subdirectory - One passing scenario, one failing scenario">
<testcase classname="Subdirectory - One passing scenario, one failing scenario" name="Passing" time="0.05">
<system-out>
<![CDATA[]]>
</system-out>
<system-err>
<![CDATA[]]>
</system-err>
</testcase>
<testcase classname="Subdirectory - One passing scenario, one failing scenario" name="Failing" time="0.05">
<failure message="failed Failing" type="failed">
<![CDATA[Scenario: Failing
Given this step fails
Message:
]]>
<![CDATA[ (RuntimeError)
./features/step_definitions/steps.rb:4:in `/^this step fails$/'
features/some_subdirectory/one_passing_one_failing.feature:7:in `Given this step fails']]>
</failure>
<system-out>
<![CDATA[]]>
</system-out>
<system-err>
<![CDATA[]]>
</system-err>
</testcase>
</testsuite>
pending and undefined steps are reported as skipped
tags: @spawn,@spawn
- When
I run cucumber --format junit --out tmp/ features/pending.feature (606ms)
- Then
it should pass with: (001ms)
- And
the junit output file "tmp/TEST-features-pending.xml" should contain: (000ms)
<?xml version="1.0" encoding="UTF-8"?>
<testsuite failures="0" errors="0" skipped="2" tests="2" time="0.05" name="Pending step">
<testcase classname="Pending step" name="Pending" time="0.05">
<skipped/>
<system-out>
<![CDATA[]]>
</system-out>
<system-err>
<![CDATA[]]>
</system-err>
</testcase>
<testcase classname="Pending step" name="Undefined" time="0.05">
<skipped/>
<system-out>
<![CDATA[]]>
</system-out>
<system-err>
<![CDATA[]]>
</system-err>
</testcase>
</testsuite>
pending and undefined steps with strict option should fail
tags: @spawn,@spawn
- When
I run cucumber --format junit --out tmp/ features/pending.feature --strict (706ms)
- Then
it should fail with: (000ms)
- And
the junit output file "tmp/TEST-features-pending.xml" should contain: (000ms)
<?xml version="1.0" encoding="UTF-8"?>
<testsuite failures="2" errors="0" skipped="0" tests="2" time="0.05" name="Pending step">
<testcase classname="Pending step" name="Pending" time="0.05">
<failure message="pending Pending" type="pending">
<![CDATA[Scenario: Pending
Given this step is pending
Message:
]]>
<![CDATA[TODO (Cucumber::Pending)
./features/step_definitions/steps.rb:3:in `/^this step is pending$/'
features/pending.feature:4:in `Given this step is pending']]>
</failure>
<system-out>
<![CDATA[]]>
</system-out>
<system-err>
<![CDATA[]]>
</system-err>
</testcase>
<testcase classname="Pending step" name="Undefined" time="0.05">
<failure message="undefined Undefined" type="undefined">
<![CDATA[Scenario: Undefined
Given this step is undefined
Message:
]]>
<![CDATA[Undefined step: "this step is undefined" (Cucumber::Core::Test::Result::Undefined)
features/pending.feature:7:in `Given this step is undefined']]>
</failure>
<system-out>
<![CDATA[]]>
</system-out>
<system-err>
<![CDATA[]]>
</system-err>
</testcase>
</testsuite>
run all features
tags: @spawn,@spawn
- When
I run cucumber --format junit --out tmp/ features (707ms)
- Then
it should fail with: (001ms)
- And
a file named "tmp/TEST-features-one_passing_one_failing.xml" should exist (000ms)
- And
a file named "tmp/TEST-features-pending.xml" should exist (000ms)
show correct error message if no --out is passed
tags: @spawn,@spawn
- When
I run cucumber --format junit features (607ms)
- Then
the stderr should not contain: (000ms)
can't convert .* into String \(TypeError\)
- And
the stderr should contain: (000ms)
You *must* specify --out DIR for the junit formatter
strict mode, one feature, one scenario outline, four examples: one passing, one failing, one pending, one undefined
tags: @spawn,@spawn
- When
I run cucumber --strict --format junit --out tmp/ features/scenario_outline.feature (707ms)
- Then
it should fail with: (000ms)
- And
the junit output file "tmp/TEST-features-scenario_outline.xml" should contain: (000ms)
<?xml version="1.0" encoding="UTF-8"?>
<testsuite failures="3" errors="0" skipped="0" tests="4" time="0.05" name="Scenario outlines">
<testcase classname="Scenario outlines" name="Using scenario outlines (outline example : | passes |)" time="0.05">
<system-out>
<![CDATA[]]>
</system-out>
<system-err>
<![CDATA[]]>
</system-err>
</testcase>
<testcase classname="Scenario outlines" name="Using scenario outlines (outline example : | fails |)" time="0.05">
<failure message="failed Using scenario outlines (outline example : | fails |)" type="failed">
<![CDATA[Scenario Outline: Using scenario outlines
Example row: | fails |
Message:
]]>
<![CDATA[ (RuntimeError)
./features/step_definitions/steps.rb:4:in `/^this step fails$/'
features/scenario_outline.feature:9:in `Given this step fails'
features/scenario_outline.feature:4:in `Given this step <type>']]>
</failure>
<system-out>
<![CDATA[]]>
</system-out>
<system-err>
<![CDATA[]]>
</system-err>
</testcase>
<testcase classname="Scenario outlines" name="Using scenario outlines (outline example : | is pending |)" time="0.05">
<failure message="pending Using scenario outlines (outline example : | is pending |)" type="pending">
<![CDATA[Scenario Outline: Using scenario outlines
Example row: | is pending |
Message:
]]>
<![CDATA[TODO (Cucumber::Pending)
./features/step_definitions/steps.rb:3:in `/^this step is pending$/'
features/scenario_outline.feature:10:in `Given this step is pending'
features/scenario_outline.feature:4:in `Given this step <type>']]>
</failure>
<system-out>
<![CDATA[]]>
</system-out>
<system-err>
<![CDATA[]]>
</system-err>
</testcase>
<testcase classname="Scenario outlines" name="Using scenario outlines (outline example : | is undefined |)" time="0.05">
<failure message="undefined Using scenario outlines (outline example : | is undefined |)" type="undefined">
<![CDATA[Scenario Outline: Using scenario outlines
Example row: | is undefined |
Message:
]]>
<![CDATA[Undefined step: "this step is undefined" (Cucumber::Core::Test::Result::Undefined)
features/scenario_outline.feature:11:in `Given this step is undefined'
features/scenario_outline.feature:4:in `Given this step <type>']]>
</failure>
<system-out>
<![CDATA[]]>
</system-out>
<system-err>
<![CDATA[]]>
</system-err>
</testcase>
</testsuite>
strict mode with --expand option, one feature, one scenario outline, four examples: one passing, one failing, one pending, one undefined
tags: @spawn,@spawn
- When
I run cucumber --strict --expand --format junit --out tmp/ features/scenario_outline.feature (706ms)
- Then
it should fail with exactly: (000ms)
- And
the junit output file "tmp/TEST-features-scenario_outline.xml" should contain: (000ms)
<?xml version="1.0" encoding="UTF-8"?>
<testsuite failures="3" errors="0" skipped="0" tests="4" time="0.05" name="Scenario outlines">
<testcase classname="Scenario outlines" name="Using scenario outlines (outline example : | passes |)" time="0.05">
<system-out>
<![CDATA[]]>
</system-out>
<system-err>
<![CDATA[]]>
</system-err>
</testcase>
<testcase classname="Scenario outlines" name="Using scenario outlines (outline example : | fails |)" time="0.05">
<failure message="failed Using scenario outlines (outline example : | fails |)" type="failed">
<![CDATA[Scenario Outline: Using scenario outlines
Example row: | fails |
Message:
]]>
<![CDATA[ (RuntimeError)
./features/step_definitions/steps.rb:4:in `/^this step fails$/'
features/scenario_outline.feature:9:in `Given this step fails'
features/scenario_outline.feature:4:in `Given this step <type>']]>
</failure>
<system-out>
<![CDATA[]]>
</system-out>
<system-err>
<![CDATA[]]>
</system-err>
</testcase>
<testcase classname="Scenario outlines" name="Using scenario outlines (outline example : | is pending |)" time="0.05">
<failure message="pending Using scenario outlines (outline example : | is pending |)" type="pending">
<![CDATA[Scenario Outline: Using scenario outlines
Example row: | is pending |
Message:
]]>
<![CDATA[TODO (Cucumber::Pending)
./features/step_definitions/steps.rb:3:in `/^this step is pending$/'
features/scenario_outline.feature:10:in `Given this step is pending'
features/scenario_outline.feature:4:in `Given this step <type>']]>
</failure>
<system-out>
<![CDATA[]]>
</system-out>
<system-err>
<![CDATA[]]>
</system-err>
</testcase>
<testcase classname="Scenario outlines" name="Using scenario outlines (outline example : | is undefined |)" time="0.05">
<failure message="undefined Using scenario outlines (outline example : | is undefined |)" type="undefined">
<![CDATA[Scenario Outline: Using scenario outlines
Example row: | is undefined |
Message:
]]>
<![CDATA[Undefined step: "this step is undefined" (Cucumber::Core::Test::Result::Undefined)
features/scenario_outline.feature:11:in `Given this step is undefined'
features/scenario_outline.feature:4:in `Given this step <type>']]>
</failure>
<system-out>
<![CDATA[]]>
</system-out>
<system-err>
<![CDATA[]]>
</system-err>
</testcase>
</testsuite>
Language help
It’s possible to ask cucumber which keywords are used for any
particular language by running:
cucumber --i18n <language code> help
This will print a table showing all the different words we use for
that language, to allow you to easily write features in any language
you choose.
Get help for Portuguese language
tags: @needs-many-fonts,@needs-many-fonts
- When
I run cucumber --i18n pt help (007ms)
- Then
it should pass with: (000ms)
| feature | "Funcionalidade", "Característica", "Caracteristica" |
| background | "Contexto", "Cenário de Fundo", "Cenario de Fundo", "Fundo" |
| scenario | "Cenário", "Cenario" |
| scenario_outline | "Esquema do Cenário", "Esquema do Cenario", "Delineação do Cenário", "Delineacao do Cenario" |
| examples | "Exemplos", "Cenários", "Cenarios" |
| given | "* ", "Dado ", "Dada ", "Dados ", "Dadas " |
| when | "* ", "Quando " |
| then | "* ", "Então ", "Entao " |
| and | "* ", "E " |
| but | "* ", "Mas " |
| given (code) | "Dado", "Dada", "Dados", "Dadas" |
| when (code) | "Quando" |
| then (code) | "Então", "Entao" |
| and (code) | "E" |
| but (code) | "Mas" |
List step defs as json
In order to build tools on top of Cucumber
As a tool developer
I want to be able to query a features directory for all the step definitions it contains
Two Ruby step definitions, in the same file
tags: @spawn,@spawn
- Given
a file named "features/step_definitions/steps.rb" with: (000ms)
Given(/foo/i) { }
Given(/b.r/xm) { }
- When
I run the following Ruby code: (610ms)
require 'cucumber' puts Cucumber::StepDefinitions.new.to_json
- Then
it should pass with JSON: (000ms)
[
{"source": "foo", "flags": "i"},
{"source": "b.r", "flags": "mx"}
]
Non-default directory structure
tags: @spawn,@spawn
- Given
a file named "my_weird/place/steps.rb" with: (000ms)
Given(/foo/) { }
Given(/b.r/x) { }
- When
I run the following Ruby code: (608ms)
require 'cucumber' puts Cucumber::StepDefinitions.new(:autoload_code_paths => ['my_weird']).to_json
- Then
it should pass with JSON: (001ms)
[
{"source": "foo", "flags": ""},
{"source": "b.r", "flags": "x"}
]
Loading the steps users expect
As a User
In order to run features in subdirectories without having to pass extra options
I want cucumber to load all step files
- Given
a file named "features/nesting/test.feature" with: (000ms)
Feature: Feature in Subdirectory
Scenario: A step not in the subdirectory
Given not found in subdirectory
- And
a file named "features/step_definitions/steps_no_in_subdirectory.rb" with: (000ms)
Given(/^not found in subdirectory$/) { }
- When
I run cucumber -q features/nesting/test.feature (006ms)
- Then
it should pass with: (000ms)
Feature: Feature in Subdirectory
Scenario: A step not in the subdirectory
Given not found in subdirectory
1 scenario (1 passed)
1 step (1 passed)
Nested Steps
Background
- Given
a scenario with a step that looks like this: (000ms)
Given two turtles
- And
a step definition that looks like this: (000ms)
Given /a turtle/ do puts "turtle!" end
Use #steps to call several steps at once
- Given
a step definition that looks like this: (000ms)
Given /two turtles/ do
steps %{
Given a turtle
And a turtle
}
end
- When
I run the feature with the progress formatter (012ms)
- Then
the output should contain: (000ms)
turtle! turtle!
Use #step to call a single step
- Given
a step definition that looks like this: (000ms)
Given /two turtles/ do step "a turtle" step "a turtle" end
- When
I run the feature with the progress formatter (007ms)
- Then
the output should contain: (000ms)
turtle! turtle!
Use #steps to call a table
- Given
a step definition that looks like this: (000ms)
Given /turtles:/ do |table|
table.hashes.each do |row|
puts row[:name]
end
end
- And
a step definition that looks like this: (000ms)
Given /two turtles/ do
steps %{
Given turtles:
| name |
| Sturm |
| Liouville |
}
end
- When
I run the feature with the progress formatter (008ms)
- Then
the output should contain: (000ms)
Sturm Liouville
Use #steps to call a multi-line string
- Given
a step definition that looks like this: (000ms)
Given /two turtles/ do
steps %Q{
Given turtles:
"""
Sturm
Liouville
"""
}
end
- And
a step definition that looks like this: (000ms)
Given /turtles:/ do |string| puts string end
- When
I run the feature with the progress formatter (007ms)
- Then
the output should contain: (000ms)
Sturm Liouville
Backtrace doesn’t skip nested steps
tags: @spawn
- Given
a step definition that looks like this: (000ms)
Given /two turtles/ do
step "I have a couple turtles"
end
When(/I have a couple turtles/) { raise 'error' }
- When
I run the feature with the progress formatter (607ms)
- Then
it should fail with: (001ms)
error (RuntimeError) ./features/step_definitions/steps2.rb:5:in `/I have a couple turtles/' ./features/step_definitions/steps2.rb:2:in `/two turtles/' features/test_feature_1.feature:3:in `Given two turtles' Failing Scenarios: cucumber features/test_feature_1.feature:2 # Scenario: Test Scenario 1 1 scenario (1 failed) 1 step (1 failed)
Undefined nested step
- Given
a file named "features/call_undefined_step_from_step_def.feature" with: (000ms)
Feature: Calling undefined step
Scenario: Call directly
Given a step that calls an undefined step
Scenario: Call via another
Given a step that calls a step that calls an undefined step
- And
a file named "features/step_definitions/steps.rb" with: (000ms)
Given /^a step that calls an undefined step$/ do step 'this does not exist' end Given /^a step that calls a step that calls an undefined step$/ do step 'a step that calls an undefined step' end
- When
I run cucumber -q features/call_undefined_step_from_step_def.feature (032ms)
- Then
it should fail with exactly: (000ms)
Feature: Calling undefined step
Scenario: Call directly
Given a step that calls an undefined step
Undefined dynamic step: "this does not exist" (Cucumber::UndefinedDynamicStep)
./features/step_definitions/steps.rb:2:in `/^a step that calls an undefined step$/'
features/call_undefined_step_from_step_def.feature:4:in `Given a step that calls an undefined step'
Scenario: Call via another
Given a step that calls a step that calls an undefined step
Undefined dynamic step: "this does not exist" (Cucumber::UndefinedDynamicStep)
./features/step_definitions/steps.rb:2:in `/^a step that calls an undefined step$/'
./features/step_definitions/steps.rb:6:in `/^a step that calls a step that calls an undefined step$/'
features/call_undefined_step_from_step_def.feature:7:in `Given a step that calls a step that calls an undefined step'
Failing Scenarios:
cucumber features/call_undefined_step_from_step_def.feature:3
cucumber features/call_undefined_step_from_step_def.feature:6
2 scenarios (2 failed)
2 steps (2 failed)
Nested Steps in I18n
Nested Steps with either table or doc string
Use #step with table
- Given
a step definition that looks like this: (000ms)
Given /turtles:/ do |table|
table.hashes.each do |row|
puts row[:name]
end
end
- And
a step definition that looks like this: (000ms)
Given /two turtles/ do
step %{turtles:}, table(%{
| name |
| Sturm |
| Liouville |
})
end
- When
I run the feature with the progress formatter (010ms)
- Then
the output should contain: (000ms)
Sturm Liouville
Use #step with docstring
- Given
a step definition that looks like this: (000ms)
Given /two turtles/ do
step %{turtles:}, "Sturm and Lioville"
end
- And
a step definition that looks like this: (000ms)
Given /turtles:/ do |text| puts text end
- When
I run the feature with the progress formatter (009ms)
- Then
the output should contain: (002ms)
Sturm and Lioville
Use #step with docstring and content-type
- Given
a step definition that looks like this: (000ms)
Given /two turtles/ do
step %{turtles:}, doc_string('Sturm and Lioville','math')
end
- And
a step definition that looks like this: (000ms)
Given /turtles:/ do |text| puts text.content_type end
- When
I run the feature with the progress formatter (008ms)
- Then
the output should contain: (000ms)
math
One line step definitions
Everybody knows you can do step definitions in Cucumber
but did you know you can do this?
Call a method in World directly from a step def
- Given
a file named "features/step_definitions/steps.rb" with: (000ms)
module Driver
def do_action
@done = true
end
def assert_done
expect(@done).to be true
end
end
World(Driver)
When /I do the action/, :do_action
Then /The action should be done/, :assert_done
- And
a file named "features/action.feature" with: (000ms)
Feature:
Scenario:
When I do the action
Then the action should be done
- When
I run cucumber (008ms)
- Then
it should pass (000ms)
Call a method on an actor in the World directly from a step def
- Given
a file named "features/step_definitions/steps.rb" with: (000ms)
class Thing
def do_action
@done = true
end
def assert_done
expect(@done).to be true
end
end
module Driver
def thing
@thing ||= Thing.new
end
end
World(Driver)
When /I do the action to the thing/, :do_action, :on => lambda { thing }
Then /The thing should be done/, :assert_done, :on => lambda { thing }
- And
a file named "features/action.feature" with: (000ms)
Feature:
Scenario:
When I do the action to the thing
Then the thing should be done
- When
I run cucumber (008ms)
- Then
it should pass (000ms)
[[Post-Configuration-Hook-[#423], Post Configuration Hook [#423]]]
=== Post Configuration Hook [#423]
In order to extend Cucumber
As a developer
I want to manipulate the Cucumber configuration after it has been created
Using options directly gets a deprecation warning
tags: @spawn,@wip-jruby
- Given
a file named "features/support/env.rb" with: (000ms)
AfterConfiguration do |config| config.options[:blah] end
- When
I run cucumber features (605ms)
- Then
the stderr should contain: (000ms)
Deprecated
Changing the output format
- Given
a file named "features/support/env.rb" with: (000ms)
AfterConfiguration do |config| config.formats << ['html', config.out_stream] end
- When
I run cucumber features (016ms)
- Then
the stderr should not contain anything (000ms)
- And
the output should contain: (008ms)
html
feature directories read from configuration
- Given
a file named "features/support/env.rb" with: (000ms)
AfterConfiguration do |config|
config.out_stream << "AfterConfiguration hook read feature directories: #{config.feature_dirs.join(', ')}"
end
- When
I run cucumber features (006ms)
- Then
the stderr should not contain anything (000ms)
- And
the output should contain: (000ms)
AfterConfiguration hook read feature directories: features
Pretty formatter - Printing messages
When you want to print to Cucumber’s output, just call puts from
a step definition. Cucumber will grab the output and print it via
the formatter that you’re using.
Your message will be printed out after the step has run.
Background
- Given
the standard step definitions (000ms)
- And
a file named "features/step_definitions/puts_steps.rb" with: (000ms)
Given /^I use puts with text "(.*)"$/ do |ann|
puts(ann)
end
Given /^I use multiple putss$/ do
puts("Multiple")
puts("Announce","Me")
end
Given /^I use message (.+) in line (.+) (?:with result (.+))$/ do |ann, line, result|
puts("Last message") if line == "3"
puts("Line: #{line}: #{ann}")
fail if result =~ /fail/i
end
Given /^I use puts and step fails$/ do
puts("Announce with fail")
fail
end
Given /^I puts the world$/ do
puts(self)
end
- And
a file named "features/f.feature" with: (000ms)
Feature:
Scenario:
Given I use puts with text "Ann"
And this step passes
Scenario:
Given I use multiple putss
And this step passes
Scenario Outline:
Given I use message <ann> in line <line>
Examples:
| line | ann |
| 1 | anno1 |
| 2 | anno2 |
| 3 | anno3 |
Scenario:
Given I use puts and step fails
And this step passes
Scenario Outline:
Given I use message <ann> in line <line> with result <result>
Examples:
| line | ann | result |
| 1 | anno1 | fail |
| 2 | anno2 | pass |
- And
a file named "features/puts_world.feature" with: (000ms)
Feature: puts_world
Scenario: puts_world
Given I puts the world
Delayed messages feature
tags: @spawn
- When
I run cucumber --quiet --format pretty features/f.feature (505ms)
- Then
the stderr should not contain anything (000ms)
- And
the output should contain: (000ms)
Feature:
Scenario:
Given I use puts with text "Ann"
Ann
And this step passes
Scenario:
Given I use multiple putss
Multiple
Announce
Me
And this step passes
Scenario Outline:
Given I use message <ann> in line <line>
Examples:
| line | ann |
| 1 | anno1 |
| 2 | anno2 |
| 3 | anno3 |
Scenario:
Given I use puts and step fails
Announce with fail
(RuntimeError)
./features/step_definitions/puts_steps.rb:18:in `/^I use puts and step fails$/'
features/f.feature:21:in `Given I use puts and step fails'
And this step passes
Scenario Outline:
Given I use message <ann> in line <line> with result <result>
Examples:
| line | ann | result |
| 1 | anno1 | fail | Line: 1: anno1
(RuntimeError)
./features/step_definitions/puts_steps.rb:13:in `/^I use message (.+) in line (.+) (?:with result (.+))$/'
features/f.feature:29:in `Given I use message anno1 in line 1 with result fail'
features/f.feature:25:in `Given I use message <ann> in line <line> with result <result>'
| 2 | anno2 | pass | Line: 2: anno2
Pretty output formatter
Background
- Given
a file named "features/scenario_outline_with_undefined_steps.feature" with: (000ms)
Feature:
Scenario Outline:
Given this step is undefined
Examples:
|foo|
|bar|
an scenario outline, one undefined step, one random example, expand flag on
- When
I run `cucumber features/scenario_outline_with_undefined_steps.feature --format pretty --expand ` (017ms)
- Then
it should pass (000ms)
when using a profile the output should include 'Using the default profile…'
- And
a file named "cucumber.yml" with: (000ms)
default: -r features
- When
I run cucumber --profile default --format pretty (018ms)
- Then
it should pass (000ms)
- And
the output should contain: (000ms)
Using the default profile...
Hook output should be printed before hook exception
- Given
the standard step definitions (000ms)
- And
a file named "features/test.feature" with: (000ms)
Feature:
Scenario:
Given this step passes
- And
a file named "features/step_definitions/output_steps.rb" with: (000ms)
Before do puts "Before hook" end AfterStep do puts "AfterStep hook" end After do puts "After hook" raise "error" end
- When
I run cucumber -q -f pretty features/test.feature (015ms)
- Then
the stderr should not contain anything (000ms)
- Then
it should fail with: (000ms)
Feature:
Scenario:
Before hook
Given this step passes
AfterStep hook
After hook
error (RuntimeError)
./features/step_definitions/output_steps.rb:11:in `After'
Failing Scenarios:
cucumber features/test.feature:2
1 scenario (1 failed)
1 step (1 passed)
Profiles
In order to save time and prevent carpal tunnel syndrome
Cucumber users can save and reuse commonly used cucumber flags in a 'cucumber.yml' file.
These named arguments are called profiles and the yml file should be in the root of your project.
Any cucumber argument is valid in a profile. To see all the available flags type 'cucumber --help'
For more information about profiles please see the wiki:
http://wiki.github.com/cucumber/cucumber/cucumber.yml
Basic App
- Given
a file named "features/sample.feature" with: (000ms)
Feature: Sample
Scenario: this is a test
Given this step raises an error
- And
an empty file named "features/support/env.rb" (000ms)
- And
an empty file named "features/support/super_env.rb" (000ms)
- And
the following profiles are defined: (000ms)
default: features/sample.feature --require features/support/env.rb -v super: features/sample.feature --require features/support/super_env.rb -v
Explicitly defining a profile to run
- When
I run cucumber features/sample.feature --profile super (014ms)
- Then
the output should contain: (000ms)
Using the super profile...
- And
exactly these files should be loaded: features/support/super_env.rb (000ms)
Explicitly defining a profile defined in an ERB formatted file
- Given
the following profiles are defined: (000ms)
<% requires = "--require features/support/super_env.rb" %>
super: <%= "features/sample.feature #{requires} -v" %>
- When
I run cucumber features/sample.feature --profile super (013ms)
- Then
the output should contain: (000ms)
Using the super profile...
- And
exactly these files should be loaded: features/support/super_env.rb (000ms)
Defining multiple profiles to run
- When
I run cucumber features/sample.feature --profile default --profile super (013ms)
- Then
the output should contain: (000ms)
Using the default and super profiles...
- And
exactly these files should be loaded: features/support/env.rb, features/support/super_env.rb (000ms)
Arguments passed in but no profile specified
- When
I run cucumber -v (009ms)
- Then
the default profile should be used (000ms)
- And
exactly these files should be loaded: features/support/env.rb (000ms)
Trying to use a missing profile
- When
I run cucumber -p foo (004ms)
- Then
the stderr should contain: (000ms)
Could not find profile: 'foo' Defined profiles in cucumber.yml: * default * super
Disabling the default profile
- When
I run cucumber -v features/ -P (006ms)
- Then
the output should contain: (000ms)
Disabling profiles...
- And
exactly these files should be loaded: features/support/env.rb, features/support/super_env.rb (000ms)
Disabling the default profile
- When
I run cucumber -v features/ --no-profile (006ms)
- Then
the output should contain: (000ms)
Disabling profiles...
- And
exactly these files should be loaded: features/support/env.rb, features/support/super_env.rb (000ms)
Overriding the profile’s features to run
- Given
a file named "features/another.feature" with: (000ms)
Feature: Just this one should be ran
- When
I run cucumber -p default features/another.feature (007ms)
- Then
exactly these features should be ran: features/another.feature (000ms)
Overriding the profile’s formatter
You will most likely want to define a formatter in your default formatter.
However, you often want to run your features with a different formatter
yet still use the other the other arguments in the profile. Cucumber will
allow you to do this by giving precedence to the formatter specified on the
command line and override the one in the profile.
- Given
the following profiles are defined: (000ms)
default: features/sample.feature --require features/support/env.rb -v --format profile
- When
I run cucumber features --format pretty (008ms)
- Then
the output should contain: (000ms)
Feature: Sample
Showing profiles when listing failing scenarios
- Given
the standard step definitions (000ms)
- When
I run cucumber -q -p super -p default -f pretty features/sample.feature --require features/step_definitions/steps.rb (015ms)
- Then
it should fail with: (000ms)
cucumber -p super features/sample.feature:2
Showing profiles when listing failing scenarios
- Given
the standard step definitions (000ms)
- When
I run cucumber -q -p super -p default -f progress features/sample.feature --require features/step_definitions/steps.rb (016ms)
- Then
it should fail with: (000ms)
cucumber -p super features/sample.feature:2
Progress output formatter
Background
- Given
a file named "features/scenario_outline_with_undefined_steps.feature" with: (000ms)
Feature:
Scenario Outline:
Given this step is undefined
Examples:
|foo|
|bar|
an scenario outline, one undefined step, one random example, expand flag on
- When
I run `cucumber features/scenario_outline_with_undefined_steps.feature --format progress --expand ` (009ms)
- Then
it should pass (000ms)
when using a profile the output should include 'Using the default profile…'
- And
a file named "cucumber.yml" with: (000ms)
default: -r features
- When
I run cucumber --profile default --format progress (012ms)
- Then
it should pass (000ms)
- And
the output should contain: (000ms)
Using the default profile...
Rake task
In order to ease the development process
As a developer and CI server administrator
Cucumber features should be executable via Rake
Background
tags: @spawn
- And
a file named "features/missing_step_definitions.feature" with: (000ms)
Feature: Sample
Scenario: Wanted
Given I want to run this
Scenario: Unwanted
Given I don't want this ran
rake task with a defined profile
tags: @spawn,@spawn
- Given
the following profile is defined: (000ms)
foo: --quiet --no-color features/missing_step_definitions.feature:3
- And
a file named "Rakefile" with: (000ms)
require 'cucumber/rake/task' Cucumber::Rake::Task.new do |t| t.profile = "foo" end
- When
I run rake cucumber (01s 206ms)
- Then
it should pass with: (000ms)
Feature: Sample
Scenario: Wanted
Given I want to run this
1 scenario (1 undefined)
1 step (1 undefined)
rake task without a profile
tags: @spawn,@spawn
- Given
a file named "Rakefile" with: (000ms)
require 'cucumber/rake/task'
Cucumber::Rake::Task.new do |t|
t.cucumber_opts = %w{--quiet --no-color}
end
- When
I run rake cucumber (01s 207ms)
- Then
it should pass with: (000ms)
Feature: Sample
Scenario: Wanted
Given I want to run this
Scenario: Unwanted
Given I don't want this ran
2 scenarios (2 undefined)
2 steps (2 undefined)
rake task with a defined profile and cucumber_opts
tags: @spawn,@spawn
- Given
the following profile is defined: (000ms)
bar: ['features/missing_step_definitions.feature:3']
- And
a file named "Rakefile" with: (000ms)
require 'cucumber/rake/task'
Cucumber::Rake::Task.new do |t|
t.profile = "bar"
t.cucumber_opts = %w{--quiet --no-color}
end
- When
I run rake cucumber (01s 207ms)
- Then
it should pass with: (000ms)
Feature: Sample
Scenario: Wanted
Given I want to run this
1 scenario (1 undefined)
1 step (1 undefined)
respect requires
tags: @spawn,@spawn
- Given
an empty file named "features/support/env.rb" (000ms)
- And
an empty file named "features/support/dont_require_me.rb" (000ms)
- And
the following profile is defined: (000ms)
no_bomb: features/missing_step_definitions.feature:3 --require features/support/env.rb --verbose
- And
a file named "Rakefile" with: (000ms)
require 'cucumber/rake/task'
Cucumber::Rake::Task.new do |t|
t.profile = "no_bomb"
t.cucumber_opts = %w{--quiet --no-color}
end
- When
I run rake cucumber (01s 106ms)
- Then
it should pass (000ms)
- And
the output should not contain: (000ms)
* features/support/dont_require_me.rb
feature files with spaces
tags: @spawn,@spawn
- Given
a file named "features/spaces are nasty.feature" with: (000ms)
Feature: The futures green
Scenario: Orange
Given this is missing
- And
a file named "Rakefile" with: (000ms)
require 'cucumber/rake/task'
Cucumber::Rake::Task.new do |t|
t.cucumber_opts = %w{--quiet --no-color}
end
- When
I run rake cucumber (01s 108ms)
- Then
it should pass with: (001ms)
Feature: The futures green
Scenario: Orange
Given this is missing
Raketask
In order to use cucumber’s rake task
As a Cuker
I do not want to see rake’s backtraces when it fails
Also I want to get zero exit status code on failures
And non-zero exit status code when it pases
Background
tags: @spawn
- Given
the standard step definitions (000ms)
- Given
a file named "features/passing_and_failing.feature" with: (000ms)
Feature: Sample
Scenario: Passing
Given this step passes
Scenario: Failing
Given this step raises an error
- Given
a file named "Rakefile" with: (000ms)
require 'cucumber/rake/task'
SAMPLE_FEATURE_FILE = 'features/passing_and_failing.feature'
Cucumber::Rake::Task.new(:pass) do |t|
t.cucumber_opts = "#{SAMPLE_FEATURE_FILE}:3"
end
Cucumber::Rake::Task.new(:fail) do |t|
t.cucumber_opts = "#{SAMPLE_FEATURE_FILE}:6"
end
Randomize
Use the --order random switch to run scenarios in random order.
This is especially helpful for detecting situations where you have state
leaking between scenarios, which can cause flickering or fragile tests.
If you do find a randmon run that exposes dependencies between your tests,
you can reproduce that run by using the seed that’s printed at the end of
the test run.
Background
- Given
a file named "features/bad_practice.feature" with: (000ms)
Feature: Bad practice
Scenario: Set state
Given I set some state
Scenario: Depend on state
When I depend on the state
- And
a file named "features/step_definitions/steps.rb" with: (000ms)
Given(/^I set some state$/) do $global_state = "set" end Given(/^I depend on the state$/) do raise "I expect the state to be set!" unless $global_state == "set" end
Requiring extra step files
Cucumber allows you to require extra files using the -r option.
- Given
a file named "features/test.feature" with: (000ms)
Feature: Sample
Scenario: Sample
Given found in extra file
- And
a file named "tmp/extras.rb" with: (000ms)
Given(/^found in extra file$/) { }
- When
I run cucumber -q -r tmp/extras.rb features/test.feature (011ms)
- Then
it should pass with: (000ms)
Feature: Sample
Scenario: Sample
Given found in extra file
1 scenario (1 passed)
1 step (1 passed)
Rerun formatter
The rerun formatter writes an output that’s perfect for
passing to Cucumber when you want to rerun only the
scenarios that prevented the exit code to be zero.
You can save off the rerun output to a file by using it like this:
cucumber -f rerun --out .cucumber.rerun
Now you can pass that file’s content to Cucumber to tell it
which scenarios to run:
cucumber `cat .cucumber.rerun`
This is useful when debugging in a large suite of features.
Exit code is zero
- Given
a file named "features/mixed.feature" with: (000ms)
Feature: Mixed
Scenario:
Given this step is undefined
Scenario:
Given this step is pending
Scenario:
Given this step passes
- When
I run cucumber -f rerun (013ms)
- Then
it should pass with exactly: (000ms)
Exit code is zero in the dry-run mode
- Given
a file named "features/mixed.feature" with: (000ms)
Feature: Mixed
Scenario:
Given this step fails
Scenario:
Given this step is undefined
Scenario:
Given this step is pending
Scenario:
Given this step passes
- And
a file named "features/all_good.feature" with: (000ms)
Feature: All good
Scenario:
Given this step passes
- When
I run cucumber -f rerun --dry-run (016ms)
- Then
it should pass with exactly: (000ms)
Exit code is not zero, regular scenario
- Given
a file named "features/mixed.feature" with: (000ms)
Feature: Mixed
Scenario:
Given this step fails
Scenario:
Given this step is undefined
Scenario:
Given this step is pending
Scenario:
Given this step passes
- And
a file named "features/all_good.feature" with: (000ms)
Feature: All good
Scenario:
Given this step passes
- When
I run cucumber -f rerun --strict (016ms)
- Then
it should fail with exactly: (000ms)
features/mixed.feature:3:6:9
Exit code is not zero, scenario outlines
For details see https://github.com/cucumber/cucumber/issues/57
- Given
a file named "features/one_passing_one_failing.feature" with: (000ms)
Feature: One passing example, one failing example
Scenario Outline:
Given this step <status>
Examples:
| status |
| passes |
| fails |
- When
I run cucumber -f rerun (010ms)
- Then
it should fail with: (000ms)
features/one_passing_one_failing.feature:9
Exit code is not zero, failing background
- Given
a file named "features/failing_background.feature" with: (000ms)
Feature: Failing background sample
Background:
Given this step fails
Scenario: failing background
Then this step passes
Scenario: another failing background
Then this step passes
- When
I run cucumber -f rerun (012ms)
- Then
it should fail with: (000ms)
features/failing_background.feature:6:9
Exit code is not zero, failing background with scenario outline
- Given
a file named "features/failing_background_outline.feature" with: (000ms)
Feature: Failing background sample with scenario outline
Background:
Given this step fails
Scenario Outline:
Then this step <status>
Examples:
| status |
| passes |
| passes |
- When
I run cucumber features/failing_background_outline.feature -r features -f rerun (011ms)
- Then
it should fail with: (000ms)
features/failing_background_outline.feature:11:12
Exit code is not zero, scenario outlines with expand
For details see https://github.com/cucumber/cucumber/issues/503
- Given
a file named "features/one_passing_one_failing.feature" with: (000ms)
Feature: One passing example, one failing example
Scenario Outline:
Given this step <status>
Examples:
| status |
| passes |
| fails |
- When
I run cucumber --expand -f rerun (012ms)
- Then
it should fail with: (000ms)
features/one_passing_one_failing.feature:9
Run Cli::Main with existing Runtime
This is the API that Spork uses. It creates an existing runtime then
calls load_programming_language('rb') on it to load the RbDsl.
When the process forks, Spork them passes the runtime to Cli::Main to
run it.
Run a single feature
tags: @spawn,@spawn
- Given
the standard step definitions (000ms)
- Given
a file named "features/success.feature" with: (000ms)
Feature:
Scenario:
Given this step passes
- When
I run the following Ruby code: (607ms)
require 'cucumber'
runtime = Cucumber::Runtime.new
runtime.load_programming_language('rb')
Cucumber::Cli::Main.new([]).execute!(runtime)
- Then
it should pass (000ms)
- And
the output should contain: (005ms)
Given this step passes
[[Run-feature-elements-matching-a-name-with---name/-n, Run feature elements matching a name with --name/-n]]
=== Run feature elements matching a name with --name/-n
The --name NAME option runs only scenarios which match a certain
name. The NAME can be a substring of the names of Features, Scenarios,
Scenario Outlines or Example blocks.
Background
- Given
a file named "features/first.feature" with: (000ms)
Feature: first feature
Scenario: foo first
Given missing
Scenario: bar first
Given missing
- Given
a file named "features/second.feature" with: (000ms)
Feature: second
Scenario: foo second
Given missing
Scenario: bar second
Given missing
- Given
a file named "features/outline.feature" with: (000ms)
Feature: outline
Scenario Outline: baz outline
Given outline step <name>
Examples: quux example
| name |
| a |
| b |
Matching Feature names
- When
I run cucumber -q --name feature (012ms)
- Then
it should pass with: (000ms)
Feature: first feature
Scenario: foo first
Given missing
Scenario: bar first
Given missing
2 scenarios (2 undefined)
2 steps (2 undefined)
Matching Scenario names
- When
I run cucumber -q --name foo (011ms)
- Then
it should pass with: (000ms)
Feature: first feature
Scenario: foo first
Given missing
Feature: second
Scenario: foo second
Given missing
2 scenarios (2 undefined)
2 steps (2 undefined)
Run specific scenarios
You can choose to run a specific scenario using the file:line format,
or you can pass in a file with a list of scenarios using @-notation.
The line number can fall anywhere within the body of a scenario, including
steps, tags, comments, description, data tables or doc strings.
For scenario outlines, if the line hits one example row, just that one
will be run. Otherwise all examples in the table or outline will be run.
Two scenarios, run just one of them
- Given
a file named "features/test.feature" with: (000ms)
Feature:
Scenario: Miss
Given this step is undefined
Scenario: Hit
Given this step passes
- When
I run cucumber features/test.feature:7 --format pretty --quiet (008ms)
- Then
it should pass with exactly: (000ms)
Feature:
Scenario: Hit
Given this step passes
1 scenario (1 passed)
1 step (1 passed)
Use @-notation to specify a file containing feature file list
- Given
a file named "features/test.feature" with: (000ms)
Feature: Sample
Scenario: Passing
Given this step passes
- And
a file named "list-of-features.txt" with: (000ms)
features/test.feature:2
- When
I run cucumber -q @list-of-features.txt (006ms)
- Then
it should pass with: (000ms)
Feature: Sample
Scenario: Passing
Given this step passes
1 scenario (1 passed)
1 step (1 passed)
Running multiple formatters
When running cucumber, you are able to using multiple different
formatters and redirect the output to text files.
Two formatters cannot both print to the same file (or to STDOUT)
Background
tags: @spawn
- Given
a file named "features/test.feature" with: (000ms)
Feature: Lots of undefined
Scenario: Implement me
Given it snows in Sahara
Given it's 40 degrees in Norway
And it's 40 degrees in Norway
When I stop procrastinating
And there is world peace
Multiple formatters and outputs
tags: @spawn,@spawn
- When
I run cucumber --no-color --format progress --out progress.txt --format pretty --out pretty.txt --no-source --dry-run --no-snippets features/test.feature (606ms)
- Then
the stderr should not contain anything (006ms)
- Then
the file "progress.txt" should contain: (000ms)
UUUUU 1 scenario (1 undefined) 5 steps (5 undefined)
- And
the file "pretty.txt" should contain: (000ms)
Feature: Lots of undefined
Scenario: Implement me
Given it snows in Sahara
Given it's 40 degrees in Norway
And it's 40 degrees in Norway
When I stop procrastinating
And there is world peace
1 scenario (1 undefined)
5 steps (5 undefined)
Two formatters to stdout
tags: @spawn,@spawn
- When
I run cucumber -f progress -f pretty features/test.feature (607ms)
- Then
it should fail with: (000ms)
All but one formatter must use --out, only one can print to each stream (or STDOUT) (RuntimeError)
Two formatters to stdout when using a profile
tags: @spawn,@spawn
- Given
the following profiles are defined: (000ms)
default: -q
- When
I run cucumber -f progress -f pretty features/test.feature (606ms)
- Then
it should fail with: (000ms)
All but one formatter must use --out, only one can print to each stream (or STDOUT) (RuntimeError)
Scenario outlines
Copying and pasting scenarios to use different values quickly
becomes tedious and repetitive. Scenario outlines allow us to more
concisely express these examples through the use of a template with
placeholders, using Scenario Outline, Examples with tables and < >
delimited parameters.
The Scenario Outline steps provide a template which is never directly
run. A Scenario Outline is run once for each row in the Examples section
beneath it (not counting the first row).
The way this works is via placeholders. Placeholders must be contained
within < > in the Scenario Outline’s steps - see the examples below.
IMPORTANT: Your step definitions will never have to match a
placeholder. They will need to match the values that will replace the
placeholder.
Background
tags: @spawn
- Given
a file named "features/outline_sample.feature" with: (000ms)
Feature: Outline Sample
Scenario: I have no steps
Scenario Outline: Test state
Given <state> without a table
Given <other_state> without a table
Examples: Rainbow colours
| state | other_state |
| missing | passing |
| passing | passing |
| failing | passing |
Examples:Only passing
| state | other_state |
| passing | passing |
- And
a file named "features/step_definitions/steps.rb" with: (000ms)
Given(/^passing without a table$/) { }
Given(/^failing without a table$/) { raise RuntimeError }
Run scenario outline with filtering on outline name
tags: @spawn,@spawn
- When
I run cucumber -q features/outline_sample.feature (706ms)
- Then
it should fail with: (001ms)
Feature: Outline Sample
Scenario: I have no steps
Scenario Outline: Test state
Given <state> without a table
Given <other_state> without a table
Examples: Rainbow colours
| state | other_state |
| missing | passing |
| passing | passing |
| failing | passing |
RuntimeError (RuntimeError)
./features/step_definitions/steps.rb:2:in `/^failing without a table$/'
features/outline_sample.feature:12:in `Given failing without a table'
features/outline_sample.feature:6:in `Given <state> without a table'
Examples: Only passing
| state | other_state |
| passing | passing |
Failing Scenarios:
cucumber features/outline_sample.feature:12
5 scenarios (1 failed, 1 undefined, 3 passed)
8 steps (1 failed, 2 skipped, 1 undefined, 4 passed)
Run scenario outline steps only
tags: @spawn,@spawn
- When
I run cucumber -q features/outline_sample.feature:7 (607ms)
- Then
it should fail with: (000ms)
Feature: Outline Sample
Scenario Outline: Test state
Given <state> without a table
Given <other_state> without a table
Examples: Rainbow colours
| state | other_state |
| missing | passing |
| passing | passing |
| failing | passing |
RuntimeError (RuntimeError)
./features/step_definitions/steps.rb:2:in `/^failing without a table$/'
features/outline_sample.feature:12:in `Given failing without a table'
features/outline_sample.feature:6:in `Given <state> without a table'
Examples: Only passing
| state | other_state |
| passing | passing |
Failing Scenarios:
cucumber features/outline_sample.feature:12
4 scenarios (1 failed, 1 undefined, 2 passed)
8 steps (1 failed, 2 skipped, 1 undefined, 4 passed)
Run single failing scenario outline table row
tags: @spawn,@spawn
- When
I run cucumber -q features/outline_sample.feature:12 (504ms)
- Then
it should fail with: (001ms)
Feature: Outline Sample
Scenario Outline: Test state
Given <state> without a table
Given <other_state> without a table
Examples: Rainbow colours
| state | other_state |
| failing | passing |
RuntimeError (RuntimeError)
./features/step_definitions/steps.rb:2:in `/^failing without a table$/'
features/outline_sample.feature:12:in `Given failing without a table'
features/outline_sample.feature:6:in `Given <state> without a table'
Failing Scenarios:
cucumber features/outline_sample.feature:12
1 scenario (1 failed)
2 steps (1 failed, 1 skipped)
Run all with progress formatter
tags: @spawn,@spawn
- When
I run cucumber -q --format progress features/outline_sample.feature (606ms)
- Then
it should fail with exactly: (000ms)
U-..F-.. (::) failed steps (::) RuntimeError (RuntimeError) ./features/step_definitions/steps.rb:2:in `/^failing without a table$/' features/outline_sample.feature:12:in `Given failing without a table' features/outline_sample.feature:6:in `Given <state> without a table' Failing Scenarios: cucumber features/outline_sample.feature:12 5 scenarios (1 failed, 1 undefined, 3 passed) 8 steps (1 failed, 2 skipped, 1 undefined, 4 passed)
Scenario outlines --expand option
In order to make it easier to write certain editor plugins and also
for some people to understand scenarios, Cucumber will expand examples
in outlines if you add the --expand option when running them.
- Given
a file named "features/test.feature" with: (000ms)
Feature:
Scenario Outline:
Given the secret code is <code>
When I guess <guess>
Then I am <verdict>
Examples:
| code | guess | verdict |
| blue | blue | right |
| red | blue | wrong |
- When
I run cucumber -i -q --expand (013ms)
- Then
the stderr should not contain anything (000ms)
- And
it should pass with: (000ms)
Feature:
Scenario Outline:
Given the secret code is <code>
When I guess <guess>
Then I am <verdict>
Examples:
Scenario: | blue | blue | right |
Given the secret code is blue
When I guess blue
Then I am right
Scenario: | red | blue | wrong |
Given the secret code is red
When I guess blue
Then I am wrong
2 scenarios (2 undefined)
6 steps (6 undefined)
Set up a default load path
When you’re developing a gem, it’s convenient if your project’s lib directory
is already in the load path. Cucumber does this for you.
Showing differences to expected output
Cucumber will helpfully show you the expectation error that your
testing library gives you, in the context of the failing scenario.
When using RSpec, for example, this will show the difference between
the expected and the actual output.
Run single failing scenario with default diff enabled
- Given
a file named "features/failing_expectation.feature" with: (000ms)
Feature: Failing expectation
Scenario: Failing expectation
Given failing expectation
- And
a file named "features/step_definitions/steps.rb" with: (000ms)
Given /^failing expectation$/ do x=1
expect('this').to eq 'that'
end
- When
I run cucumber -q features/failing_expectation.feature (022ms)
- Then
it should fail with: (000ms)
Feature: Failing expectation
Scenario: Failing expectation
Given failing expectation
expected: "that"
got: "this"
(compared using ==)
(RSpec::Expectations::ExpectationNotMetError)
./features/step_definitions/steps.rb:2:in `/^failing expectation$/'
features/failing_expectation.feature:4:in `Given failing expectation'
Failing Scenarios:
cucumber features/failing_expectation.feature:3
1 scenario (1 failed)
1 step (1 failed)
Skip Scenario
With a passing step
- Given
a file named "features/test.feature" with: (000ms)
Feature: test
Scenario: test
Given this step says to skip
And this step passes
- And
the standard step definitions (000ms)
- And
a file named "features/step_definitions/skippy.rb" with: (000ms)
Given /skip/ do skip_this_scenario end
- When
I run cucumber -q (011ms)
- Then
it should pass with exactly: (000ms)
Feature: test
Scenario: test
Given this step says to skip
And this step passes
1 scenario (1 skipped)
2 steps (2 skipped)
Use legacy API from a hook
- Given
a file named "features/test.feature" with: (000ms)
Feature: test
Scenario: test
Given this step passes
And this step passes
- And
the standard step definitions (000ms)
- And
a file named "features/support/hook.rb" with: (000ms)
Before do |scenario| scenario.skip_invoke! end
- When
I run cucumber -q (011ms)
- Then
it should pass with: (000ms)
Feature: test
Scenario: test
Given this step passes
And this step passes
1 scenario (1 skipped)
2 steps (2 skipped)
Snippets
Cucumber helpfully prints out any undefined step definitions as a code
snippet suggestion, which you can then paste into a step definitions
file of your choosing.
Snippet for undefined step with a pystring
- Given
a file named "features/undefined_steps.feature" with: (000ms)
Feature:
Scenario: pystring
Given a pystring
"""
example with <html> entities
"""
When a simple when step
And another when step
Then a simple then step
- When
I run cucumber features/undefined_steps.feature -s (009ms)
- Then
the output should contain: (000ms)
Given(/^a pystring$/) do |string| pending # Write code here that turns the phrase above into concrete actions end When(/^a simple when step$/) do pending # Write code here that turns the phrase above into concrete actions end When(/^another when step$/) do pending # Write code here that turns the phrase above into concrete actions end Then(/^a simple then step$/) do pending # Write code here that turns the phrase above into concrete actions end
Snippet for undefined step with a step table
- Given
a file named "features/undefined_steps.feature" with: (000ms)
Feature:
Scenario: table
Given a table
| table |
|example|
- When
I run cucumber features/undefined_steps.feature -s (007ms)
- Then
the output should contain: (000ms)
Given(/^a table$/) do |table| # table is a Cucumber::Core::Ast::DataTable pending # Write code here that turns the phrase above into concrete actions end
Snippets message
If a step doesn’t match, Cucumber will ask the wire server to return a snippet of code for a
step definition.
Background
tags: @wire
- Given
a file named "features/wired.feature" with: (000ms)
Feature: High strung
Scenario: Wired
Given we're all wired
- And
a file named "features/step_definitions/some_remote_place.wire" with: (000ms)
host: localhost port: 54321
Wire server returns snippets for a step that didn’t match
tags: @wire,@wire,@spawn
- Given
there is a wire server running on port 54321 which understands the following protocol: (002ms)
- When
I run cucumber -f pretty (908ms)
- Then
the stderr should not contain anything (000ms)
- And
it should pass with: (001ms)
Feature: High strung
Scenario: Wired # features/wired.feature:2
Given we're all wired # features/wired.feature:3
1 scenario (1 undefined)
1 step (1 undefined)
- And
the output should contain: (000ms)
You can implement step definitions for undefined steps with these snippets: foo() bar; baz
State
You can pass state between step by setting instance variables,
but those instance variables will be gone when the next scenario runs.
Set an ivar in one scenario, use it in the next step
- Given
a file named "features/test.feature" with: (000ms)
Feature:
Scenario:
Given I have set @flag = true
Then @flag should be true
Scenario:
Then @flag should be nil
- And
a file named "features/step_definitions/steps.rb" with: (000ms)
Given /set @flag/ do @flag = true end Then /flag should be true/ do expect(@flag).to be_truthy end Then /flag should be nil/ do expect(@flag).to be_nil end
- When
I run cucumber (014ms)
- Then
it should pass (000ms)
Step matches message
When the features have been parsed, Cucumber will send a step_matches
message to ask the wire server if it can match a step name. This happens for
each of the steps in each of the features.
The wire server replies with an array of StepMatch objects.
When each StepMatch is returned, it contains the following data:
-
id- identifier for the step definition to be used later when if it
needs to be invoked. The identifier can be any string value and
is simply used for the wire server’s own reference. -
args- any argument values as captured by the wire end’s own regular
expression (or other argument matching) process.
Background
tags: @wire
- Given
a file named "features/wired.feature" with: (000ms)
Feature: High strung
Scenario: Wired
Given we're all wired
- And
a file named "features/step_definitions/some_remote_place.wire" with: (000ms)
host: localhost port: 54321
Dry run finds no step match
tags: @wire,@wire
- Given
there is a wire server running on port 54321 which understands the following protocol: (002ms)
- When
I run cucumber --dry-run --no-snippets -f progress (061ms)
- And
it should pass with: (000ms)
U 1 scenario (1 undefined) 1 step (1 undefined)
Dry run finds a step match
tags: @wire,@wire
- Given
there is a wire server running on port 54321 which understands the following protocol: (002ms)
- When
I run cucumber --dry-run -f progress (024ms)
- And
it should pass with: (000ms)
- 1 scenario (1 skipped) 1 step (1 skipped)
Step matches returns details about the remote step definition
tags: @wire,@wire
Optionally, the StepMatch can also contain a source reference, and a native
regexp string which will be used by some formatters.
- Given
there is a wire server running on port 54321 which understands the following protocol: (001ms)
- When
I run cucumber -f stepdefs --dry-run (015ms)
- Then
it should pass with: (000ms)
- we.* # MyApp.MyClass:123 1 scenario (1 skipped) 1 step (1 skipped)
- And
the stderr should not contain anything (000ms)
Strict mode
Using the --strict flag will cause cucumber to fail unless all the
step definitions have been defined.
Background
- Given
a file named "features/missing.feature" with: (000ms)
Feature: Missing
Scenario: Missing
Given this step passes
- And
a file named "features/pending.feature" with: (000ms)
Feature: Pending
Scenario: Pending
Given this step is pending
Fail with --strict due to undefined step
- When
I run cucumber -q features/missing.feature --strict (016ms)
- Then
it should fail with: (000ms)
Feature: Missing
Scenario: Missing
Given this step passes
Undefined step: "this step passes" (Cucumber::Undefined)
features/missing.feature:3:in `Given this step passes'
1 scenario (1 undefined)
1 step (1 undefined)
Fail with --strict due to pending step
- Given
the standard step definitions (000ms)
- When
I run cucumber -q features/pending.feature --strict (015ms)
- Then
it should fail with: (000ms)
Feature: Pending
Scenario: Pending
Given this step is pending
TODO (Cucumber::Pending)
./features/step_definitions/steps.rb:3:in `/^this step is pending$/'
features/pending.feature:3:in `Given this step is pending'
1 scenario (1 pending)
1 step (1 pending)
Table diffing
To allow you to more easily compare data in tables, you are able
to easily diff a table with expected data and see the diff in your
output.
Extra row
- Given
a file named "features/tables.feature" with: (000ms)
Feature: Tables
Scenario: Extra row
Then the table should be:
| x | y |
| a | b |
- And
a file named "features/step_definitions/steps.rb" with: (000ms)
Then /the table should be:/ do |expected| x=1
expected.diff!(table(%{
| x | y |
| a | c |
}))
end
- When
I run cucumber features/tables.feature (015ms)
- Then
it should fail with exactly: (000ms)
Feature: Tables
Scenario: Extra row # features/tables.feature:2
Then the table should be: # features/step_definitions/steps.rb:1
| x | y |
| a | b |
Tables were not identical:
| x | y |
| (-) a | (-) b |
| (+) a | (+) c |
(Cucumber::MultilineArgument::DataTable::Different)
./features/step_definitions/steps.rb:2:in `/the table should be:/'
features/tables.feature:3:in `Then the table should be:'
Failing Scenarios:
cucumber features/tables.feature:2 # Scenario: Extra row
1 scenario (1 failed)
1 step (1 failed)
0m0.012s
Tag logic
In order to conveniently run subsets of features
As a Cuker
I want to select features using logical AND/OR of tags
Background
- Given
a file named "features/test.feature" with: (000ms)
@feature
Feature: Sample
@one @three
Scenario: Example
Given passing
@one
Scenario: Another Example
Given passing
@three
Scenario: Yet another Example
Given passing
@ignore
Scenario: And yet another Example
ANDing tags
- When
I run cucumber -q -t @one -t @three features/test.feature (008ms)
- Then
it should pass with: (000ms)
@feature
Feature: Sample
@one @three
Scenario: Example
Given passing
1 scenario (1 undefined)
1 step (1 undefined)
ORing tags
- When
I run cucumber -q -t @one,@three features/test.feature (010ms)
- Then
it should pass with: (000ms)
@feature
Feature: Sample
@one @three
Scenario: Example
Given passing
@one
Scenario: Another Example
Given passing
@three
Scenario: Yet another Example
Given passing
3 scenarios (3 undefined)
3 steps (3 undefined)
Negative tags
- When
I run cucumber -q -t ~@three features/test.feature (008ms)
- Then
it should pass with: (000ms)
@feature
Feature: Sample
@one
Scenario: Another Example
Given passing
@ignore
Scenario: And yet another Example
2 scenarios (1 undefined, 1 passed)
1 step (1 undefined)
Run with limited tag count, blowing it on scenario
- When
I run cucumber -q --no-source --tags @one:1 features/test.feature (005ms)
- Then
it fails before running features with: (000ms)
@one occurred 2 times, but the limit was set to 1 features/test.feature:5 features/test.feature:9
Run with limited tag count, blowing it via feature inheritance
- When
I run cucumber -q --no-source --tags @feature:1 features/test.feature (005ms)
- Then
it fails before running features with: (000ms)
@feature occurred 4 times, but the limit was set to 1 features/test.feature:5 features/test.feature:9 features/test.feature:13 features/test.feature:17
Run with limited tag count using negative tag, blowing it via a tag that is not run
- When
I run cucumber -q --no-source --tags ~@one:1 features/test.feature (004ms)
- Then
it fails before running features with: (000ms)
@one occurred 2 times, but the limit was set to 1
Limiting with tags which do not exist in the features
Originally added to check [Lighthouse bug #464](https://rspec.lighthouseapp.com/projects/16211/tickets/464).
- When
I run cucumber -q -t @i_dont_exist features/test.feature (004ms)
- Then
it should pass (000ms)
Tagged hooks
Background
- Given
the standard step definitions (000ms)
- And
a file named "features/support/hooks.rb" with: (000ms)
Before('~@no-boom') do
raise 'boom'
end
- And
a file named "features/f.feature" with: (000ms)
Feature: With and without hooks
Scenario: using hook
Given this step passes
@no-boom
Scenario: omitting hook
Given this step passes
Scenario Outline: omitting hook on specified examples
Given this step passes
Examples:
| Value |
| Irrelevant |
@no-boom
Examples:
| Value |
| Also Irrelevant |
omit tagged hook
- When
I run cucumber features/f.feature:2 (016ms)
- Then
it should fail with exactly: (000ms)
Feature: With and without hooks
Scenario: using hook # features/f.feature:2
boom (RuntimeError)
./features/support/hooks.rb:2:in `Before'
Given this step passes # features/step_definitions/steps.rb:1
Failing Scenarios:
cucumber features/f.feature:2 # Scenario: using hook
1 scenario (1 failed)
1 step (1 skipped)
0m0.012s
omit tagged hook
- When
I run cucumber features/f.feature:6 (010ms)
- Then
it should pass with exactly: (000ms)
Feature: With and without hooks
@no-boom
Scenario: omitting hook # features/f.feature:6
Given this step passes # features/step_definitions/steps.rb:1
1 scenario (1 passed)
1 step (1 passed)
0m0.012s
Omit example hook
- When
I run cucumber features/f.feature:12 (013ms)
- Then
it should fail with exactly: (000ms)
Feature: With and without hooks
Scenario Outline: omitting hook on specified examples # features/f.feature:9
Given this step passes # features/f.feature:10
Examples:
| Value |
boom (RuntimeError)
./features/support/hooks.rb:2:in `Before'
| Irrelevant |
Failing Scenarios:
cucumber features/f.feature:14 # Scenario Outline: omitting hook on specified examples, Examples (#1)
1 scenario (1 failed)
1 step (1 skipped)
0m0.012s
Transforms
If you see certain phrases repeated over and over in your step definitions, you can
use transforms to factor out that duplication, and make your step definitions simpler.
Background
Let’s just create a simple feature for testing out Transforms.
We also have a Person class that we need to be able to build.
- Given
a file named "features/foo.feature" with: (000ms)
Feature:
Scenario:
Given a Person aged 15 with blonde hair
- And
a file named "features/support/person.rb" with: (000ms)
class Person
attr_accessor :age
def to_s
"I am #{age} years old"
end
end
Basic Transform
This is the most basic way to use a transform. Notice that the regular
expression is pretty much duplicated.
- And
a file named "features/step_definitions/steps.rb" with: (000ms)
Transform(/a Person aged (\d+)/) do |age| person = Person.new person.age = age.to_i person end Given /^(a Person aged \d+) with blonde hair$/ do |person| expect(person.age).to eq 15 end
- When
I run cucumber features/foo.feature (009ms)
- Then
it should pass (000ms)
Re-use Transform’s Regular Expression
If you keep a reference to the transform, you can use it in your
regular expressions to avoid repeating the regular expression.
- And
a file named "features/step_definitions/steps.rb" with: (000ms)
A_PERSON = Transform(/a Person aged (\d+)/) do |age|
person = Person.new
person.age = age.to_i
person
end
Given /^(#{A_PERSON}) with blonde hair$/ do |person|
expect(person.age).to eq 15
end
- When
I run cucumber features/foo.feature (012ms)
- Then
it should pass (000ms)
Unicode in tables
You are free to use unicode in your tables: we’ve taken care to
ensure that the tables are properly aligned so that your output is as
readable as possible.
tags: @spawn,@spawn
- Given
a file named "features/unicode.feature" with: (000ms)
Feature: Featuring unicode
Scenario: table with unicode
Given passing
| Brüno | abc |
| Bruno | æøå |
- When
I run cucumber -q --dry-run features/unicode.feature (605ms)
- Then
it should pass with: (000ms)
Feature: Featuring unicode
Scenario: table with unicode
Given passing
| Brüno | abc |
| Bruno | æøå |
1 scenario (1 undefined)
1 step (1 undefined)
Usage formatter
In order to see where step definitions are used
Developers should be able to see a list of step definitions and their use
Background
- Given
a file named "features/f.feature" with: (000ms)
Feature: F
Background: A
Given A
Scenario: B
Given B
Scenario Outline: CA
Given <x>
And B
Examples:
|x|
|C|
|A|
Scenario: AC
Given A
Given C
- And
a file named "features/step_definitions/steps.rb" with: (000ms)
Given(/A/) { }
Given(/B/) { }
Given(/C/) { }
Given(/D/) { }
Run with --format usage
- When
I run cucumber -f usage --dry-run (015ms)
- Then
it should pass with exactly: (000ms)
----------- /A/ # features/step_definitions/steps.rb:1 Given A # features/f.feature:3 Given A # features/f.feature:12 Given A # features/f.feature:14 /B/ # features/step_definitions/steps.rb:2 Given B # features/f.feature:5 And B # features/f.feature:11 And B # features/f.feature:12 /C/ # features/step_definitions/steps.rb:3 Given C # features/f.feature:11 Given C # features/f.feature:15 /D/ # features/step_definitions/steps.rb:4 NOT MATCHED BY ANY STEPS 4 scenarios (4 skipped) 11 steps (11 skipped)
Run with --expand --format usage
- When
I run cucumber -x -f usage --dry-run (018ms)
- Then
it should pass with exactly: (000ms)
----------- /A/ # features/step_definitions/steps.rb:1 Given A # features/f.feature:3 Given A # features/f.feature:12 Given A # features/f.feature:14 /B/ # features/step_definitions/steps.rb:2 Given B # features/f.feature:5 And B # features/f.feature:11 And B # features/f.feature:12 /C/ # features/step_definitions/steps.rb:3 Given C # features/f.feature:11 Given C # features/f.feature:15 /D/ # features/step_definitions/steps.rb:4 NOT MATCHED BY ANY STEPS 4 scenarios (4 skipped) 11 steps (11 skipped)
Run with --format stepdefs
- When
I run cucumber -f stepdefs --dry-run (024ms)
- Then
it should pass with exactly: (000ms)
----------- /A/ # features/step_definitions/steps.rb:1 /B/ # features/step_definitions/steps.rb:2 /C/ # features/step_definitions/steps.rb:3 /D/ # features/step_definitions/steps.rb:4 NOT MATCHED BY ANY STEPS 4 scenarios (4 skipped) 11 steps (11 skipped)
Using descriptions to give features context
When writing your feature files its very helpful to use description
text at the beginning of the feature file, to write a preamble to the
feature describing clearly exactly what the feature does.
You can also write descriptions attached to individual scenarios - see
the examples below for how this can be used.
It’s possible to have your descriptions run over more than one line,
and you can have blank lines too. As long as you don’t start a line
with a Given, When, Then, Background:, Scenario: or similar, you’re
fine: otherwise Gherkin will start to pay attention.
Everything with a description
- Given
a file named "features/test.feature" with: (000ms)
Feature: descriptions everywhere
We can put a useful description here of the feature, which can
span multiple lines.
Background:
We can also put in descriptions showing what the background is
doing.
Given this step passes
Scenario: I'm a scenario with a description
You can also put descriptions in front of individual scenarios.
Given this step passes
Scenario Outline: I'm a scenario outline with a description
Scenario outlines can have descriptions.
Given this step <state>
Examples: Examples
Specific examples for an outline are allowed to have
descriptions, too.
| state |
| passes |
- When
I run cucumber -q (021ms)
- Then
the stderr should not contain anything (000ms)
- Then
it should pass with exactly: (000ms)
Feature: descriptions everywhere
We can put a useful description here of the feature, which can
span multiple lines.
Background:
We can also put in descriptions showing what the background is
doing.
Given this step passes
Scenario: I'm a scenario with a description
You can also put descriptions in front of individual scenarios.
Given this step passes
Scenario Outline: I'm a scenario outline with a description
Scenario outlines can have descriptions.
Given this step <state>
Examples: Examples
Specific examples for an outline are allowed to have
descriptions, too.
| state |
| passes |
2 scenarios (2 passed)
4 steps (4 passed)
[[Using-star-notation-instead-of-Given/When/Then, Using star notation instead of Given/When/Then]]
=== Using star notation instead of Given/When/Then
Cucumber supports the star notation when writing features: instead of
using Given/When/Then, you can simply use a star rather like you would
use a bullet point.
When you run the feature for the first time, you still get a nice
message showing you the code snippet you need to use to implement the
step.
Use some *
- Given
a file named "features/f.feature" with: (000ms)
Feature: Star-notation feature
Scenario: S
* I have some cukes
- When
I run cucumber features/f.feature (010ms)
- Then
the stderr should not contain anything (000ms)
- And
it should pass with: (000ms)
Feature: Star-notation feature
Scenario: S # features/f.feature:2
* I have some cukes # features/f.feature:3
1 scenario (1 undefined)
1 step (1 undefined)
- And
it should pass with: (000ms)
You can implement step definitions for undefined steps with these snippets: Given(/^I have some cukes$/) do pending # Write code here that turns the phrase above into concrete actions end
Wire protocol table diffing
In order to use the amazing functionality in the Cucumber table object
As a wire server
I want to be able to ask for a table diff during a step definition invocation
Background
tags: @wire
- Given
a file named "features/wired.feature" with: (000ms)
Feature: Hello
Scenario: Wired
Given we're all wired
- And
a file named "features/step_definitions/some_remote_place.wire" with: (000ms)
host: localhost port: 54321
Invoke a step definition tries to diff the table and fails
tags: @wire,@wire,@spawn
- Given
there is a wire server running on port 54321 which understands the following protocol: (001ms)
- When
I run cucumber -f progress --backtrace (807ms)
- Then
the stderr should not contain anything (000ms)
- And
it should fail with: (001ms)
F (::) failed steps (::) Not same (DifferentException from localhost:54321) a.cs:12 b.cs:34 features/wired.feature:3:in `Given we're all wired' Failing Scenarios: cucumber features/wired.feature:2 # Scenario: Wired 1 scenario (1 failed) 1 step (1 failed)
Invoke a step definition tries to diff the table and passes
tags: @wire,@wire
- Given
there is a wire server running on port 54321 which understands the following protocol: (002ms)
- When
I run cucumber -f progress (181ms)
- Then
it should pass with: (001ms)
. 1 scenario (1 passed) 1 step (1 passed)
Invoke a step definition which successfully diffs a table but then fails
tags: @wire,@wire,@spawn
- Given
there is a wire server running on port 54321 which understands the following protocol: (002ms)
- When
I run cucumber -f progress (908ms)
- Then
it should fail with: (001ms)
F (::) failed steps (::) I wanted things to be different for us (Cucumber::WireSupport::WireException) features/wired.feature:3:in `Given we're all wired' Failing Scenarios: cucumber features/wired.feature:2 # Scenario: Wired 1 scenario (1 failed) 1 step (1 failed)
Invoke a step definition which asks for an immediate diff that fails
tags: @wire,@wire,@spawn
- Given
there is a wire server running on port 54321 which understands the following protocol: (002ms)
- When
I run cucumber -f progress (808ms)
- And
it should fail with exactly: (001ms)
F (::) failed steps (::) Tables were not identical: | (-) a | (+) b | (Cucumber::MultilineArgument::DataTable::Different) features/wired.feature:3:in `Given we're all wired' Failing Scenarios: cucumber features/wired.feature:2 # Scenario: Wired 1 scenario (1 failed) 1 step (1 failed) 0m0.012s
Wire protocol tags
In order to use Before and After hooks in a wire server, we send tags with the
scenario in the begin_scenario and end_scenario messages
Background
tags: @wire
- And
a file named "features/step_definitions/some_remote_place.wire" with: (000ms)
host: localhost port: 54321
Run a scenario
tags: @wire,@wire
- Given
a file named "features/wired.feature" with: (000ms)
@foo @bar
Feature: Wired
@baz
Scenario: Everybody's Wired
Given we're all wired
- And
there is a wire server running on port 54321 which understands the following protocol: (002ms)
- When
I run cucumber -f pretty -q (145ms)
- Then
the stderr should not contain anything (000ms)
- And
it should pass with: (000ms)
@foo @bar
Feature: Wired
@baz
Scenario: Everybody's Wired
Given we're all wired
1 scenario (1 passed)
1 step (1 passed)
Run a scenario outline example
tags: @wire,@wire
- Given
a file named "features/wired.feature" with: (000ms)
@foo @bar
Feature: Wired
@baz
Scenario Outline: Everybody's Wired
Given we're all <something>
Examples:
| something |
| wired |
- And
there is a wire server running on port 54321 which understands the following protocol: (002ms)
- When
I run cucumber -f pretty -q (147ms)
- Then
the stderr should not contain anything (001ms)
- And
it should pass with: (001ms)
@foo @bar
Feature: Wired
@baz
Scenario Outline: Everybody's Wired
Given we're all <something>
Examples:
| something |
| wired |
1 scenario (1 passed)
1 step (1 passed)
Wire protocol timeouts
We don’t want Cucumber to hang forever on a wire server that’s not even there,
but equally we need to give the user the flexibility to allow step definitions
to take a while to execute, if that’s what they need.
Background
tags: @wire
- And
a file named "features/wired.feature" with: (000ms)
Feature: Telegraphy
Scenario: Wired
Given we're all wired
Try to talk to a server that’s not there
tags: @wire,@wire
- Given
a file named "features/step_definitions/some_remote_place.wire" with: (001ms)
host: localhost port: 54321
- When
I run cucumber -f progress (012ms)
- Then
the stderr should contain: (000ms)
Unable to contact the wire server at localhost:54321
Invoke a step definition that takes longer than its timeout
tags: @wire,@wire,@spawn
- Given
a file named "features/step_definitions/some_remote_place.wire" with: (000ms)
host: localhost port: 54321 timeout: invoke: 0.1
- And
there is a wire server on port 54321 which understands the following protocol: (000ms)
- And
the wire server takes 0.2 seconds to respond to the invoke message (002ms)
- When
I run cucumber -f pretty (908ms)
- Then
the stderr should not contain anything (000ms)
- And
it should fail with: (001ms)
Feature: Telegraphy
Scenario: Wired # features/wired.feature:2
Given we're all wired # Unknown
Timed out calling wire server with message 'invoke' (Timeout::Error)
features/wired.feature:3:in `Given we're all wired'
Failing Scenarios:
cucumber features/wired.feature:2 # Scenario: Wired
1 scenario (1 failed)
1 step (1 failed)