cucumber 0.8.7 → 0.9.0
Sign up to get free protection for your applications and to get access to all the features.
- 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.",
|