cucumber 0.8.7 → 0.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.gitignore +24 -0
- data/Gemfile +5 -0
- data/History.txt +16 -3
- data/Rakefile +4 -50
- data/cucumber.gemspec +36 -600
- data/features/cucumber_cli.feature +1 -1
- data/features/json_formatter.feature +1 -1
- data/features/junit_formatter.feature +10 -6
- data/features/post_configuration_hook.feature +15 -2
- data/features/step_definitions/cucumber_steps.rb +5 -1
- data/features/step_definitions/wire_steps.rb +1 -0
- data/features/support/env.rb +2 -5
- data/features/wire_protocol.feature +1 -1
- data/lib/cucumber.rb +8 -0
- data/lib/cucumber/ast/outline_table.rb +4 -4
- data/lib/cucumber/ast/step_invocation.rb +14 -13
- data/lib/cucumber/ast/table.rb +2 -1
- data/lib/cucumber/ast/tree_walker.rb +3 -3
- data/lib/cucumber/cli/configuration.rb +32 -7
- data/lib/cucumber/cli/main.rb +26 -30
- data/lib/cucumber/cli/options.rb +1 -3
- data/lib/cucumber/cli/profile_loader.rb +2 -0
- data/lib/cucumber/configuration.rb +37 -0
- data/lib/cucumber/errors.rb +40 -0
- data/lib/cucumber/feature_file.rb +5 -12
- data/lib/cucumber/formatter/junit.rb +2 -2
- data/lib/cucumber/formatter/tag_cloud.rb +1 -1
- data/lib/cucumber/js_support/js_dsl.js +4 -4
- data/lib/cucumber/js_support/js_language.rb +9 -5
- data/lib/cucumber/language_support.rb +2 -2
- data/lib/cucumber/parser/gherkin_builder.rb +19 -19
- data/lib/cucumber/platform.rb +3 -4
- data/lib/cucumber/rake/task.rb +1 -7
- data/lib/cucumber/rb_support/rb_dsl.rb +1 -0
- data/lib/cucumber/rb_support/rb_language.rb +1 -0
- data/lib/cucumber/rspec/doubles.rb +3 -3
- data/lib/cucumber/runtime.rb +192 -0
- data/lib/cucumber/runtime/features_loader.rb +62 -0
- data/lib/cucumber/runtime/results.rb +46 -0
- data/lib/cucumber/runtime/support_code.rb +174 -0
- data/lib/cucumber/runtime/user_interface.rb +80 -0
- data/lib/cucumber/step_mother.rb +6 -427
- data/lib/cucumber/wire_support/configuration.rb +2 -0
- data/lib/cucumber/wire_support/wire_language.rb +1 -8
- data/spec/cucumber/ast/background_spec.rb +3 -3
- data/spec/cucumber/ast/feature_spec.rb +2 -2
- data/spec/cucumber/ast/scenario_outline_spec.rb +1 -1
- data/spec/cucumber/ast/scenario_spec.rb +1 -2
- data/spec/cucumber/ast/tree_walker_spec.rb +1 -1
- data/spec/cucumber/cli/configuration_spec.rb +31 -5
- data/spec/cucumber/cli/drb_client_spec.rb +1 -1
- data/spec/cucumber/cli/main_spec.rb +8 -37
- data/spec/cucumber/cli/options_spec.rb +20 -0
- data/spec/cucumber/formatter/spec_helper.rb +5 -7
- data/spec/cucumber/rb_support/rb_language_spec.rb +2 -2
- data/spec/cucumber/rb_support/rb_step_definition_spec.rb +1 -1
- data/spec/cucumber/runtime_spec.rb +294 -0
- data/spec/cucumber/step_match_spec.rb +10 -8
- data/spec/cucumber/world/pending_spec.rb +1 -1
- data/spec/spec_helper.rb +2 -21
- metadata +215 -84
- data/Caliper.yml +0 -4
- data/VERSION.yml +0 -5
- data/spec/cucumber/step_mother_spec.rb +0 -302
@@ -337,7 +337,7 @@ Feature: Cucumber command line
|
|
337
337
|
"""
|
338
338
|
|
339
339
|
Scenario: Multiple formatters and outputs
|
340
|
-
When I run cucumber --format progress --out tmp/progress.txt --format pretty --out tmp/pretty.txt --no-source --dry-run features/lots_of_undefined.feature
|
340
|
+
When I run cucumber --format progress --out tmp/progress.txt --format pretty --out tmp/pretty.txt --no-source --dry-run --no-snippets features/lots_of_undefined.feature
|
341
341
|
Then STDERR should be empty
|
342
342
|
Then "fixtures/self_test/tmp/progress.txt" should contain
|
343
343
|
"""
|
@@ -176,7 +176,7 @@ Feature: JSON output formatter
|
|
176
176
|
],
|
177
177
|
"exception": {
|
178
178
|
"class": "RSpec::Expectations::ExpectationNotMetError",
|
179
|
-
"message": "expected: 4,\n got: 5 (using ==)
|
179
|
+
"message": "expected: 4,\n got: 5 (using ==)",
|
180
180
|
"backtrace": [
|
181
181
|
"./features/step_definitions/steps.rb:18:in `/^I the result should be (\\d+)$/'",
|
182
182
|
"features/tables.feature:8:in `Then I the result should be <c>'"
|
@@ -20,13 +20,15 @@ Feature: JUnit output formatter
|
|
20
20
|
</testcase>
|
21
21
|
<testcase classname="One passing scenario, one failing scenario.Failing" name="Failing" time="0.005">
|
22
22
|
<failure message="failed Failing" type="failed">
|
23
|
-
|
23
|
+
<![CDATA[Scenario: Failing
|
24
24
|
|
25
25
|
Given a failing scenario
|
26
26
|
|
27
27
|
Message:
|
28
|
-
|
29
|
-
|
28
|
+
]]>
|
29
|
+
<![CDATA[ (RuntimeError)
|
30
|
+
features/one_passing_one_failing.feature:7:in `Given a failing scenario']]>
|
31
|
+
</failure>
|
30
32
|
</testcase>
|
31
33
|
</testsuite>
|
32
34
|
|
@@ -58,10 +60,12 @@ Feature: JUnit output formatter
|
|
58
60
|
<testsuite errors="0" failures="1" name="Pending step" tests="1" time="0.000160">
|
59
61
|
<testcase classname="Pending step.Pending" name="Pending" time="0.000160">
|
60
62
|
<failure message="pending Pending" type="pending">
|
61
|
-
|
63
|
+
<![CDATA[Scenario: Pending
|
62
64
|
|
63
|
-
|
64
|
-
|
65
|
+
]]>
|
66
|
+
<![CDATA[TODO (Cucumber::Pending)
|
67
|
+
features/pending.feature:4:in `Given a pending step']]>
|
68
|
+
</failure>
|
65
69
|
</testcase>
|
66
70
|
</testsuite>
|
67
71
|
|
@@ -4,13 +4,26 @@ Feature: Post Configuration Hook [#423]
|
|
4
4
|
As a developer
|
5
5
|
I want to manipulate the Cucumber configuration after it has been created
|
6
6
|
|
7
|
-
Scenario:
|
7
|
+
Scenario: Using options directly gets a deprecation warning
|
8
8
|
|
9
9
|
Given a standard Cucumber project directory structure
|
10
10
|
And a file named "features/support/env.rb" with:
|
11
11
|
"""
|
12
12
|
AfterConfiguration do |config|
|
13
|
-
config.options[:
|
13
|
+
config.options[:blah]
|
14
|
+
end
|
15
|
+
"""
|
16
|
+
When I run cucumber features
|
17
|
+
Then STDERR should match
|
18
|
+
"""
|
19
|
+
Deprecated
|
20
|
+
"""
|
21
|
+
|
22
|
+
Given a standard Cucumber project directory structure
|
23
|
+
And a file named "features/support/env.rb" with:
|
24
|
+
"""
|
25
|
+
AfterConfiguration do |config|
|
26
|
+
config.formats << ['html', config.out_stream]
|
14
27
|
end
|
15
28
|
"""
|
16
29
|
When I run cucumber features
|
@@ -50,7 +50,11 @@ Given /^I have environment variable (\w+) set to "([^"]*)"$/ do |variable, value
|
|
50
50
|
end
|
51
51
|
|
52
52
|
When /^I run cucumber (.*)$/ do |cucumber_opts|
|
53
|
-
|
53
|
+
# Don't use Cucumber::BINARY (which is the binary used to start the "outer" cucumber)
|
54
|
+
# Instead we force the use of this codebase's cucumber bin script.
|
55
|
+
# This allows us to run cucumber's cukes with an older, stable cucumber.
|
56
|
+
cucumber_bin = File.expand_path(File.dirname(__FILE__) + '/../../bin/cucumber')
|
57
|
+
run "#{Cucumber::RUBY_BINARY} -I rubygems #{cucumber_bin} --no-color #{cucumber_opts} CUCUMBER_OUTPUT_ENCODING=UTF-8"
|
54
58
|
end
|
55
59
|
|
56
60
|
When /^I run rake (.*)$/ do |rake_opts|
|
data/features/support/env.rb
CHANGED
@@ -67,7 +67,7 @@ Feature: Wire Protocol
|
|
67
67
|
Given there is a wire server running on port 54321 which understands the following protocol:
|
68
68
|
| request | response |
|
69
69
|
| ["step_matches",{"name_to_match":"we're all wired"}] | ["success",[]] |
|
70
|
-
When I run cucumber --dry-run -f progress
|
70
|
+
When I run cucumber --dry-run --no-snippets -f progress
|
71
71
|
And it should pass with
|
72
72
|
"""
|
73
73
|
U
|
data/lib/cucumber.rb
CHANGED
@@ -21,7 +21,7 @@ module Cucumber
|
|
21
21
|
return if Cucumber.wants_to_quit
|
22
22
|
init
|
23
23
|
cells_rows.each_with_index do |row, n|
|
24
|
-
if(visitor.
|
24
|
+
if(visitor.configuration.expand?)
|
25
25
|
row.accept(visitor)
|
26
26
|
else
|
27
27
|
visitor.visit_table_row(row)
|
@@ -96,7 +96,7 @@ module Cucumber
|
|
96
96
|
|
97
97
|
def accept(visitor)
|
98
98
|
return if Cucumber.wants_to_quit
|
99
|
-
visitor.
|
99
|
+
visitor.configuration.expand? ? accept_expand(visitor) : accept_plain(visitor)
|
100
100
|
end
|
101
101
|
|
102
102
|
def accept_plain(visitor)
|
@@ -108,7 +108,7 @@ module Cucumber
|
|
108
108
|
else
|
109
109
|
visitor.step_mother.with_hooks(self) do
|
110
110
|
@step_invocations.each do |step_invocation|
|
111
|
-
step_invocation.invoke(visitor.step_mother, visitor.
|
111
|
+
step_invocation.invoke(visitor.step_mother, visitor.configuration)
|
112
112
|
@exception ||= step_invocation.reported_exception
|
113
113
|
end
|
114
114
|
|
@@ -127,7 +127,7 @@ module Cucumber
|
|
127
127
|
visitor.step_mother.with_hooks(self) do
|
128
128
|
@table.visit_scenario_name(visitor, self)
|
129
129
|
@step_invocations.each do |step_invocation|
|
130
|
-
step_invocation.invoke(visitor.step_mother, visitor.
|
130
|
+
step_invocation.invoke(visitor.step_mother, visitor.configuration)
|
131
131
|
@exception ||= step_invocation.reported_exception
|
132
132
|
step_invocation.visit_step_result(visitor)
|
133
133
|
end
|
@@ -1,3 +1,4 @@
|
|
1
|
+
require 'cucumber/errors'
|
1
2
|
require 'cucumber/step_match'
|
2
3
|
require 'cucumber/ast/table'
|
3
4
|
require 'gherkin/rubify'
|
@@ -38,7 +39,7 @@ module Cucumber
|
|
38
39
|
|
39
40
|
def accept(visitor)
|
40
41
|
return if Cucumber.wants_to_quit
|
41
|
-
invoke(visitor.step_mother, visitor.
|
42
|
+
invoke(visitor.step_mother, visitor.configuration)
|
42
43
|
visit_step_result(visitor)
|
43
44
|
end
|
44
45
|
|
@@ -54,53 +55,53 @@ module Cucumber
|
|
54
55
|
)
|
55
56
|
end
|
56
57
|
|
57
|
-
def invoke(step_mother,
|
58
|
-
find_step_match!(step_mother)
|
59
|
-
unless @skip_invoke ||
|
58
|
+
def invoke(step_mother, configuration)
|
59
|
+
find_step_match!(step_mother, configuration)
|
60
|
+
unless @skip_invoke || configuration.dry_run? || @exception || @step_collection.exception
|
60
61
|
@skip_invoke = true
|
61
62
|
begin
|
62
63
|
@step_match.invoke(@multiline_arg)
|
63
64
|
step_mother.after_step
|
64
65
|
status!(:passed)
|
65
66
|
rescue Pending => e
|
66
|
-
failed(
|
67
|
+
failed(configuration, e, false)
|
67
68
|
status!(:pending)
|
68
69
|
rescue Undefined => e
|
69
|
-
failed(
|
70
|
+
failed(configuration, e, false)
|
70
71
|
status!(:undefined)
|
71
72
|
rescue Cucumber::Ast::Table::Different => e
|
72
73
|
@different_table = e.table
|
73
|
-
failed(
|
74
|
+
failed(configuration, e, false)
|
74
75
|
status!(:failed)
|
75
76
|
rescue Exception => e
|
76
|
-
failed(
|
77
|
+
failed(configuration, e, false)
|
77
78
|
status!(:failed)
|
78
79
|
end
|
79
80
|
end
|
80
81
|
end
|
81
82
|
|
82
|
-
def find_step_match!(step_mother)
|
83
|
+
def find_step_match!(step_mother, configuration)
|
83
84
|
return if @step_match
|
84
85
|
begin
|
85
86
|
@step_match = step_mother.step_match(@name)
|
86
87
|
rescue Undefined => e
|
87
|
-
failed(
|
88
|
+
failed(configuration, e, true)
|
88
89
|
status!(:undefined)
|
89
90
|
@step_match = NoStepMatch.new(@step, @name)
|
90
91
|
rescue Ambiguous => e
|
91
|
-
failed(
|
92
|
+
failed(configuration, e, false)
|
92
93
|
status!(:failed)
|
93
94
|
@step_match = NoStepMatch.new(@step, @name)
|
94
95
|
end
|
95
96
|
step_mother.step_visited(self)
|
96
97
|
end
|
97
98
|
|
98
|
-
def failed(
|
99
|
+
def failed(configuration, e, clear_backtrace)
|
99
100
|
e = filter_backtrace(e)
|
100
101
|
e.set_backtrace([]) if clear_backtrace
|
101
102
|
e.backtrace << @step.backtrace_line unless @step.backtrace_line.nil?
|
102
103
|
@exception = e
|
103
|
-
if(
|
104
|
+
if(configuration.strict? || !(Undefined === e) || e.nested?)
|
104
105
|
@reported_exception = e
|
105
106
|
else
|
106
107
|
@reported_exception = nil
|
data/lib/cucumber/ast/table.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'gherkin/rubify'
|
2
|
+
require 'gherkin/lexer/i18n_lexer'
|
2
3
|
require 'gherkin/formatter/escaping'
|
3
4
|
|
4
5
|
module Cucumber
|
@@ -60,7 +61,7 @@ module Cucumber
|
|
60
61
|
|
61
62
|
def self.parse(text, uri, offset)
|
62
63
|
builder = Builder.new
|
63
|
-
lexer = Gherkin::I18nLexer.new(builder)
|
64
|
+
lexer = Gherkin::Lexer::I18nLexer.new(builder)
|
64
65
|
lexer.scan(text)
|
65
66
|
new(builder.rows)
|
66
67
|
end
|
@@ -2,11 +2,11 @@ module Cucumber
|
|
2
2
|
module Ast
|
3
3
|
# Walks the AST, executing steps and notifying listeners
|
4
4
|
class TreeWalker
|
5
|
-
attr_accessor :
|
5
|
+
attr_accessor :configuration #:nodoc:
|
6
6
|
attr_reader :step_mother #:nodoc:
|
7
7
|
|
8
|
-
def initialize(step_mother, listeners = [],
|
9
|
-
@step_mother, @listeners, @
|
8
|
+
def initialize(step_mother, listeners = [], configuration = Cucumber::Configuration.default)
|
9
|
+
@step_mother, @listeners, @configuration = step_mother, listeners, configuration
|
10
10
|
end
|
11
11
|
|
12
12
|
def visit_features(features)
|
@@ -12,7 +12,7 @@ module Cucumber
|
|
12
12
|
class Configuration
|
13
13
|
include Constantize
|
14
14
|
|
15
|
-
attr_reader :
|
15
|
+
attr_reader :out_stream
|
16
16
|
|
17
17
|
def initialize(out_stream = STDOUT, error_stream = STDERR)
|
18
18
|
@out_stream = out_stream
|
@@ -56,8 +56,16 @@ module Cucumber
|
|
56
56
|
@options[:drb_port].to_i if @options[:drb_port]
|
57
57
|
end
|
58
58
|
|
59
|
-
def
|
60
|
-
|
59
|
+
def dry_run?
|
60
|
+
@options[:dry_run]
|
61
|
+
end
|
62
|
+
|
63
|
+
def expand?
|
64
|
+
@options[:expand]
|
65
|
+
end
|
66
|
+
|
67
|
+
def build_tree_walker(step_mother)
|
68
|
+
Ast::TreeWalker.new(step_mother, formatters(step_mother), self)
|
61
69
|
end
|
62
70
|
|
63
71
|
def formatter_class(format)
|
@@ -121,7 +129,27 @@ module Cucumber
|
|
121
129
|
logger.level = Logger::DEBUG if self.verbose?
|
122
130
|
logger
|
123
131
|
end
|
124
|
-
|
132
|
+
|
133
|
+
def tag_expression
|
134
|
+
Gherkin::TagExpression.new(@options[:tag_expressions])
|
135
|
+
end
|
136
|
+
|
137
|
+
def filters
|
138
|
+
@options.filters
|
139
|
+
end
|
140
|
+
|
141
|
+
def formats
|
142
|
+
@options[:formats]
|
143
|
+
end
|
144
|
+
|
145
|
+
def options
|
146
|
+
warn("Deprecated: Configuration#options will be removed from the next release of Cucumber. Please use the configuration object directly instead.")
|
147
|
+
@options
|
148
|
+
end
|
149
|
+
|
150
|
+
def paths
|
151
|
+
@options[:paths].empty? ? ['features'] : @options[:paths]
|
152
|
+
end
|
125
153
|
private
|
126
154
|
|
127
155
|
def formatters(step_mother)
|
@@ -151,9 +179,6 @@ module Cucumber
|
|
151
179
|
end
|
152
180
|
end
|
153
181
|
|
154
|
-
def paths
|
155
|
-
@options[:paths].empty? ? ['features'] : @options[:paths]
|
156
|
-
end
|
157
182
|
|
158
183
|
def set_environment_variables
|
159
184
|
@options[:env_vars].each do |var, value|
|
data/lib/cucumber/cli/main.rb
CHANGED
@@ -13,16 +13,20 @@ require 'cucumber/formatter/color_io'
|
|
13
13
|
require 'cucumber/cli/configuration'
|
14
14
|
require 'cucumber/cli/drb_client'
|
15
15
|
|
16
|
+
if defined?(Spork::TestFramework::Cucumber)
|
17
|
+
class Spork::TestFramework::Cucumber < Spork::TestFramework
|
18
|
+
def run_tests(argv, stderr, stdout)
|
19
|
+
::Cucumber::Cli::Main.new(argv, stdout, stderr).execute!
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
16
24
|
module Cucumber
|
17
25
|
module Cli
|
18
26
|
class Main
|
19
27
|
class << self
|
20
|
-
def step_mother
|
21
|
-
@step_mother ||= StepMother.new
|
22
|
-
end
|
23
|
-
|
24
28
|
def execute(args)
|
25
|
-
new(args).execute!
|
29
|
+
new(args).execute!
|
26
30
|
end
|
27
31
|
end
|
28
32
|
|
@@ -38,34 +42,17 @@ module Cucumber
|
|
38
42
|
@configuration = nil
|
39
43
|
end
|
40
44
|
|
41
|
-
def execute!(
|
42
|
-
|
43
|
-
|
44
|
-
begin
|
45
|
-
return DRbClient.run(@args, @error_stream, @out_stream, configuration.drb_port)
|
46
|
-
rescue DRbClientError => e
|
47
|
-
@error_stream.puts "WARNING: #{e.message} Running features locally:"
|
48
|
-
end
|
45
|
+
def execute!(legacy_step_mother = nil)
|
46
|
+
if legacy_step_mother
|
47
|
+
warn("Passing a step_mother to #execute! is deprecated, and has been ignored: #{caller[0]}")
|
49
48
|
end
|
50
|
-
step_mother.options = configuration.options
|
51
|
-
step_mother.log = configuration.log
|
52
49
|
|
53
|
-
|
54
|
-
|
55
|
-
features = step_mother.load_plain_text_features(configuration.feature_files)
|
56
|
-
step_mother.load_code_files(configuration.step_defs_to_load)
|
57
|
-
|
58
|
-
runner = configuration.build_runner(step_mother, @out_stream)
|
59
|
-
step_mother.visitor = runner # Needed to support World#announce
|
50
|
+
trap_interrupt
|
51
|
+
return @drb_output if run_drb_client
|
60
52
|
|
61
|
-
|
62
|
-
|
63
|
-
failure
|
64
|
-
step_mother.scenarios(:passed).any?
|
65
|
-
else
|
66
|
-
step_mother.scenarios(:failed).any? ||
|
67
|
-
(configuration.strict? && (step_mother.steps(:undefined).any? || step_mother.steps(:pending).any?))
|
68
|
-
end
|
53
|
+
runtime = Runtime.new(configuration)
|
54
|
+
runtime.run!
|
55
|
+
runtime.results.failure?
|
69
56
|
rescue ProfilesNotDefinedError, YmlLoadError, ProfileNotFound => e
|
70
57
|
@error_stream.puts e.message
|
71
58
|
true
|
@@ -76,10 +63,19 @@ module Cucumber
|
|
76
63
|
|
77
64
|
@configuration = Configuration.new(@out_stream, @error_stream)
|
78
65
|
@configuration.parse!(@args)
|
66
|
+
Cucumber.logger = @configuration.log
|
79
67
|
@configuration
|
80
68
|
end
|
81
69
|
|
82
70
|
private
|
71
|
+
|
72
|
+
def run_drb_client
|
73
|
+
return false unless configuration.drb?
|
74
|
+
@drb_output = DRbClient.run(@args, @error_stream, @out_stream, configuration.drb_port)
|
75
|
+
true
|
76
|
+
rescue DRbClientError => e
|
77
|
+
@error_stream.puts "WARNING: #{e.message} Running features locally:"
|
78
|
+
end
|
83
79
|
|
84
80
|
def trap_interrupt
|
85
81
|
trap('INT') do
|
data/lib/cucumber/cli/options.rb
CHANGED
@@ -199,10 +199,8 @@ module Cucumber
|
|
199
199
|
Term::ANSIColor.coloring = v
|
200
200
|
end
|
201
201
|
opts.on("-d", "--dry-run", "Invokes formatters without executing the steps.",
|
202
|
-
"This also omits the loading of your support/env.rb file if it exists."
|
203
|
-
"Implies --no-snippets.") do
|
202
|
+
"This also omits the loading of your support/env.rb file if it exists.") do
|
204
203
|
@options[:dry_run] = true
|
205
|
-
@options[:snippets] = false
|
206
204
|
end
|
207
205
|
opts.on("-a", "--autoformat DIR",
|
208
206
|
"Reformats (pretty prints) feature files and write them to DIRECTORY.",
|