cucumber 0.9.2 → 0.9.3
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/Gemfile +0 -8
- data/History.txt +8 -0
- data/cucumber.gemspec +1 -1
- data/features/api/list_step_defs_as_json.feature +11 -6
- data/features/api/run_cli_main_with_existing_runtime.feature +34 -0
- data/features/step_definitions/cucumber_steps.rb +1 -2
- data/lib/cucumber.rb +1 -0
- data/lib/cucumber/cli/main.rb +8 -14
- data/lib/cucumber/cli/options.rb +1 -1
- data/lib/cucumber/core_ext/disable_mini_unit_autorun.rb +10 -0
- data/lib/cucumber/platform.rb +1 -1
- data/lib/cucumber/rb_support/rb_step_definition.rb +8 -0
- data/lib/cucumber/runtime.rb +12 -62
- data/lib/cucumber/runtime/for_programming_languages.rb +65 -0
- data/lib/cucumber/runtime/results.rb +4 -0
- data/lib/cucumber/runtime/support_code.rb +29 -11
- data/lib/cucumber/step_definitions.rb +1 -3
- data/spec/cucumber/cli/main_spec.rb +30 -4
- data/spec/cucumber/formatter/spec_helper.rb +3 -3
- data/spec/cucumber/rb_support/rb_language_spec.rb +215 -29
- data/spec/cucumber/rb_support/rb_step_definition_spec.rb +30 -24
- data/spec/cucumber/runtime/support_code_spec.rb +112 -0
- data/spec/cucumber/runtime_spec.rb +21 -274
- metadata +15 -9
data/Gemfile
CHANGED
@@ -1,10 +1,2 @@
|
|
1
1
|
source "http://rubygems.org"
|
2
2
|
gemspec
|
3
|
-
|
4
|
-
# Use source from sibling folders (if available) instead of gems
|
5
|
-
%w[gherkin].each do |g|
|
6
|
-
if File.directory?(File.dirname(__FILE__) + "/../#{g}")
|
7
|
-
@dependencies.reject!{|dep| dep.name == g}
|
8
|
-
gem g, :path => "../#{g}"
|
9
|
-
end
|
10
|
-
end
|
data/History.txt
CHANGED
@@ -1,3 +1,11 @@
|
|
1
|
+
== 0.9.3 (2010-10-24)
|
2
|
+
|
3
|
+
=== Bugfixes
|
4
|
+
* Better JSON representation of Regexps (Aslak Hellesøy)
|
5
|
+
* Update to work with latest spork (Matt Wynne)
|
6
|
+
* Prevent MiniTest::Unit#autorun from running in at_exit hook. (Aslak Hellesøy)
|
7
|
+
* Fixed incorect --help for --strict. It fails on both pending and undefined. (Aslak Hellesøy)
|
8
|
+
|
1
9
|
== 0.9.2 (2010-10-04)
|
2
10
|
|
3
11
|
=== Bugfixes
|
data/cucumber.gemspec
CHANGED
@@ -24,7 +24,7 @@ for important information about this release. Happy cuking!
|
|
24
24
|
|
25
25
|
}
|
26
26
|
|
27
|
-
s.add_dependency 'gherkin', '~> 2.2.
|
27
|
+
s.add_dependency 'gherkin', '~> 2.2.9'
|
28
28
|
s.add_dependency 'term-ansicolor', '~> 1.0.5'
|
29
29
|
s.add_dependency 'builder', '~> 2.1.2'
|
30
30
|
s.add_dependency 'diff-lcs', '~> 1.1.2'
|
@@ -9,8 +9,8 @@ Feature: List step defs as json
|
|
9
9
|
Scenario: Two Ruby step definitions, in the same file
|
10
10
|
Given a file named "features/step_definitions/foo_steps.rb" with:
|
11
11
|
"""
|
12
|
-
Given(/foo/) {}
|
13
|
-
Given(/b.r/) {}
|
12
|
+
Given(/foo/i) {}
|
13
|
+
Given(/b.r/xm) {}
|
14
14
|
"""
|
15
15
|
When I run the following Ruby code:
|
16
16
|
"""
|
@@ -21,15 +21,17 @@ Feature: List step defs as json
|
|
21
21
|
Then it should pass
|
22
22
|
And the output should contain the following JSON:
|
23
23
|
"""
|
24
|
-
[
|
25
|
-
|
24
|
+
[
|
25
|
+
{"source": "foo", "flags": "i"},
|
26
|
+
{"source": "b.r", "flags": "mx"}
|
27
|
+
]
|
26
28
|
"""
|
27
29
|
|
28
30
|
Scenario: Non-default directory structure
|
29
31
|
Given a file named "my_weird/place/foo_steps.rb" with:
|
30
32
|
"""
|
31
33
|
Given(/foo/) {}
|
32
|
-
Given(/b.r/) {}
|
34
|
+
Given(/b.r/x) {}
|
33
35
|
"""
|
34
36
|
When I run the following Ruby code:
|
35
37
|
"""
|
@@ -40,6 +42,9 @@ Feature: List step defs as json
|
|
40
42
|
Then it should pass
|
41
43
|
And the output should contain the following JSON:
|
42
44
|
"""
|
43
|
-
[
|
45
|
+
[
|
46
|
+
{"source": "foo", "flags": ""},
|
47
|
+
{"source": "b.r", "flags": "x"}
|
48
|
+
]
|
44
49
|
|
45
50
|
"""
|
@@ -0,0 +1,34 @@
|
|
1
|
+
Feature: Run Cli::Main with existing Runtime
|
2
|
+
|
3
|
+
This is the API that Spork uses. It creates an existing runtime then
|
4
|
+
calls load_programming_language('rb') on it to load the RbDsl.
|
5
|
+
When the process forks, Spork them passes the runtime to Cli::Main to
|
6
|
+
run it.
|
7
|
+
|
8
|
+
Background:
|
9
|
+
Given a standard Cucumber project directory structure
|
10
|
+
|
11
|
+
Scenario: Run a single feature
|
12
|
+
Given a file named "features/step_definitions/success.rb" with:
|
13
|
+
"""
|
14
|
+
Given(/pass/) {}
|
15
|
+
"""
|
16
|
+
Given a file named "features/success.feature" with:
|
17
|
+
"""
|
18
|
+
Feature:
|
19
|
+
Scenario:
|
20
|
+
Given I pass
|
21
|
+
"""
|
22
|
+
When I run the following Ruby code:
|
23
|
+
"""
|
24
|
+
require 'cucumber'
|
25
|
+
runtime = Cucumber::Runtime.new
|
26
|
+
runtime.load_programming_language('rb')
|
27
|
+
Cucumber::Cli::Main.new([]).execute!(runtime)
|
28
|
+
|
29
|
+
"""
|
30
|
+
Then it should pass
|
31
|
+
And the output should contain:
|
32
|
+
"""
|
33
|
+
Given I pass
|
34
|
+
"""
|
@@ -61,7 +61,6 @@ When /^I run the following Ruby code:$/ do |code|
|
|
61
61
|
run %{#{Cucumber::RUBY_BINARY} -r rubygems -I #{cucumber_lib_dir} -e "#{code}"}
|
62
62
|
end
|
63
63
|
|
64
|
-
|
65
64
|
Then /^it should (fail|pass)$/ do |success|
|
66
65
|
if success == 'fail'
|
67
66
|
last_exit_status.should_not == 0
|
@@ -77,7 +76,7 @@ Then /^it should (fail|pass) with$/ do |success, output|
|
|
77
76
|
Then("it should #{success}")
|
78
77
|
end
|
79
78
|
|
80
|
-
Then /^the output should contain
|
79
|
+
Then /^the output should contain:?$/ do |text|
|
81
80
|
last_stdout.should include(text)
|
82
81
|
end
|
83
82
|
|
data/lib/cucumber.rb
CHANGED
data/lib/cucumber/cli/main.rb
CHANGED
@@ -13,14 +13,6 @@ 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
|
-
|
24
16
|
module Cucumber
|
25
17
|
module Cli
|
26
18
|
class Main
|
@@ -42,15 +34,17 @@ module Cucumber
|
|
42
34
|
@configuration = nil
|
43
35
|
end
|
44
36
|
|
45
|
-
def execute!(
|
46
|
-
if legacy_step_mother
|
47
|
-
warn("Passing a step_mother to #execute! is deprecated, and has been ignored: #{caller[0]}")
|
48
|
-
end
|
49
|
-
|
37
|
+
def execute!(existing_runtime = nil)
|
50
38
|
trap_interrupt
|
51
39
|
return @drb_output if run_drb_client
|
52
40
|
|
53
|
-
runtime =
|
41
|
+
runtime = if existing_runtime
|
42
|
+
existing_runtime.configure(configuration)
|
43
|
+
existing_runtime
|
44
|
+
else
|
45
|
+
Runtime.new(configuration)
|
46
|
+
end
|
47
|
+
|
54
48
|
runtime.run!
|
55
49
|
runtime.results.failure?
|
56
50
|
rescue ProfilesNotDefinedError, YmlLoadError, ProfileNotFound => e
|
data/lib/cucumber/cli/options.rb
CHANGED
@@ -229,7 +229,7 @@ module Cucumber
|
|
229
229
|
opts.on("-b", "--backtrace", "Show full backtrace for all errors.") do
|
230
230
|
Cucumber.use_full_backtrace = true
|
231
231
|
end
|
232
|
-
opts.on("-S", "--strict", "Fail if there are any undefined steps.") do
|
232
|
+
opts.on("-S", "--strict", "Fail if there are any undefined or pending steps.") do
|
233
233
|
@options[:strict] = true
|
234
234
|
end
|
235
235
|
opts.on("-w", "--wip", "Fail if there are any passing scenarios.") do
|
data/lib/cucumber/platform.rb
CHANGED
@@ -4,7 +4,7 @@ require 'rbconfig'
|
|
4
4
|
|
5
5
|
module Cucumber
|
6
6
|
unless defined?(Cucumber::VERSION)
|
7
|
-
VERSION = '0.9.
|
7
|
+
VERSION = '0.9.3'
|
8
8
|
BINARY = File.expand_path(File.dirname(__FILE__) + '/../../bin/cucumber')
|
9
9
|
LIBDIR = File.expand_path(File.dirname(__FILE__) + '/../../lib')
|
10
10
|
JRUBY = defined?(JRUBY_VERSION)
|
@@ -38,6 +38,14 @@ module Cucumber
|
|
38
38
|
@regexp.inspect
|
39
39
|
end
|
40
40
|
|
41
|
+
def to_hash
|
42
|
+
flags = ''
|
43
|
+
flags += 'm' if (@regexp.options & Regexp::MULTILINE) != 0
|
44
|
+
flags += 'i' if (@regexp.options & Regexp::IGNORECASE) != 0
|
45
|
+
flags += 'x' if (@regexp.options & Regexp::EXTENDED) != 0
|
46
|
+
{'source' => @regexp.source, 'flags' => flags}
|
47
|
+
end
|
48
|
+
|
41
49
|
def ==(step_definition)
|
42
50
|
regexp_source == step_definition.regexp_source
|
43
51
|
end
|
data/lib/cucumber/runtime.rb
CHANGED
@@ -18,10 +18,21 @@ module Cucumber
|
|
18
18
|
def initialize(configuration = Configuration.default)
|
19
19
|
@current_scenario = nil
|
20
20
|
@configuration = Configuration.parse(configuration)
|
21
|
-
@support_code = SupportCode.new(self, @configuration
|
21
|
+
@support_code = SupportCode.new(self, @configuration)
|
22
22
|
@results = Results.new(@configuration)
|
23
23
|
end
|
24
24
|
|
25
|
+
# Allows you to take an existing runtime and change it's configuration
|
26
|
+
def configure(new_configuration)
|
27
|
+
@configuration = Configuration.parse(new_configuration)
|
28
|
+
@support_code.configure(@configuration)
|
29
|
+
@results.configure(@configuration)
|
30
|
+
end
|
31
|
+
|
32
|
+
def load_programming_language(language)
|
33
|
+
@support_code.load_programming_language(language)
|
34
|
+
end
|
35
|
+
|
25
36
|
def run!
|
26
37
|
load_step_definitions
|
27
38
|
fire_after_configuration_hook
|
@@ -48,67 +59,6 @@ module Cucumber
|
|
48
59
|
@results.steps(status)
|
49
60
|
end
|
50
61
|
|
51
|
-
# Loads and registers programming language implementation.
|
52
|
-
# Instances are cached, so calling with the same argument
|
53
|
-
# twice will return the same instance.
|
54
|
-
#
|
55
|
-
def load_programming_language(ext)
|
56
|
-
@support_code.load_programming_language!(ext)
|
57
|
-
end
|
58
|
-
|
59
|
-
def invoke(step_name, multiline_argument=nil)
|
60
|
-
# It is very important to leave multiline_argument=nil as a vararg. Cuke4Duke needs it that way.
|
61
|
-
@support_code.invoke(step_name, multiline_argument)
|
62
|
-
end
|
63
|
-
|
64
|
-
# Invokes a series of steps +steps_text+. Example:
|
65
|
-
#
|
66
|
-
# invoke(%Q{
|
67
|
-
# Given I have 8 cukes in my belly
|
68
|
-
# Then I should not be thirsty
|
69
|
-
# })
|
70
|
-
def invoke_steps(steps_text, i18n, file_colon_line)
|
71
|
-
@support_code.invoke_steps(steps_text, i18n, file_colon_line)
|
72
|
-
end
|
73
|
-
|
74
|
-
# Returns a Cucumber::Ast::Table for +text_or_table+, which can either
|
75
|
-
# be a String:
|
76
|
-
#
|
77
|
-
# table(%{
|
78
|
-
# | account | description | amount |
|
79
|
-
# | INT-100 | Taxi | 114 |
|
80
|
-
# | CUC-101 | Peeler | 22 |
|
81
|
-
# })
|
82
|
-
#
|
83
|
-
# or a 2D Array:
|
84
|
-
#
|
85
|
-
# table([
|
86
|
-
# %w{ account description amount },
|
87
|
-
# %w{ INT-100 Taxi 114 },
|
88
|
-
# %w{ CUC-101 Peeler 22 }
|
89
|
-
# ])
|
90
|
-
#
|
91
|
-
def table(text_or_table, file=nil, line_offset=0)
|
92
|
-
if Array === text_or_table
|
93
|
-
Ast::Table.new(text_or_table)
|
94
|
-
else
|
95
|
-
Ast::Table.parse(text_or_table, file, line_offset)
|
96
|
-
end
|
97
|
-
end
|
98
|
-
|
99
|
-
# Returns a regular String for +string_with_triple_quotes+. Example:
|
100
|
-
#
|
101
|
-
# """
|
102
|
-
# hello
|
103
|
-
# world
|
104
|
-
# """
|
105
|
-
#
|
106
|
-
# Is retured as: " hello\nworld"
|
107
|
-
#
|
108
|
-
def py_string(string_with_triple_quotes, file=nil, line_offset=0)
|
109
|
-
Ast::PyString.parse(string_with_triple_quotes)
|
110
|
-
end
|
111
|
-
|
112
62
|
def step_match(step_name, name_to_report=nil) #:nodoc:
|
113
63
|
@support_code.step_match(step_name, name_to_report)
|
114
64
|
end
|
@@ -0,0 +1,65 @@
|
|
1
|
+
require 'forwardable'
|
2
|
+
|
3
|
+
module Cucumber
|
4
|
+
class Runtime
|
5
|
+
# This is what a programming language will consider to be a runtime.
|
6
|
+
#
|
7
|
+
# It's a thin class that directs the handul of methods needed by the
|
8
|
+
# programming languages to the right place.
|
9
|
+
class ForProgrammingLanguages
|
10
|
+
extend Forwardable
|
11
|
+
|
12
|
+
def initialize(support_code, user_interface)
|
13
|
+
@support_code, @user_interface = support_code, user_interface
|
14
|
+
end
|
15
|
+
|
16
|
+
def_delegators :@user_interface,
|
17
|
+
:embed,
|
18
|
+
:ask,
|
19
|
+
:announce
|
20
|
+
|
21
|
+
def_delegators :@support_code,
|
22
|
+
:invoke_steps,
|
23
|
+
:invoke,
|
24
|
+
:load_programming_language
|
25
|
+
|
26
|
+
# Returns a Cucumber::Ast::Table for +text_or_table+, which can either
|
27
|
+
# be a String:
|
28
|
+
#
|
29
|
+
# table(%{
|
30
|
+
# | account | description | amount |
|
31
|
+
# | INT-100 | Taxi | 114 |
|
32
|
+
# | CUC-101 | Peeler | 22 |
|
33
|
+
# })
|
34
|
+
#
|
35
|
+
# or a 2D Array:
|
36
|
+
#
|
37
|
+
# table([
|
38
|
+
# %w{ account description amount },
|
39
|
+
# %w{ INT-100 Taxi 114 },
|
40
|
+
# %w{ CUC-101 Peeler 22 }
|
41
|
+
# ])
|
42
|
+
#
|
43
|
+
def table(text_or_table, file=nil, line_offset=0)
|
44
|
+
if Array === text_or_table
|
45
|
+
Ast::Table.new(text_or_table)
|
46
|
+
else
|
47
|
+
Ast::Table.parse(text_or_table, file, line_offset)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
# Returns a regular String for +string_with_triple_quotes+. Example:
|
52
|
+
#
|
53
|
+
# """
|
54
|
+
# hello
|
55
|
+
# world
|
56
|
+
# """
|
57
|
+
#
|
58
|
+
# Is retured as: " hello\nworld"
|
59
|
+
#
|
60
|
+
def py_string(string_with_triple_quotes, file=nil, line_offset=0)
|
61
|
+
Ast::PyString.parse(string_with_triple_quotes)
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
@@ -1,9 +1,12 @@
|
|
1
1
|
require 'cucumber/constantize'
|
2
|
+
require 'cucumber/runtime/for_programming_languages'
|
2
3
|
|
3
4
|
module Cucumber
|
4
5
|
class Runtime
|
5
6
|
|
6
7
|
class SupportCode
|
8
|
+
|
9
|
+
require 'forwardable'
|
7
10
|
class StepInvoker
|
8
11
|
include Gherkin::Rubify
|
9
12
|
|
@@ -31,25 +34,39 @@ module Cucumber
|
|
31
34
|
end
|
32
35
|
|
33
36
|
include Constantize
|
34
|
-
|
35
|
-
def initialize(
|
36
|
-
@
|
37
|
-
@
|
37
|
+
|
38
|
+
def initialize(user_interface, configuration={})
|
39
|
+
@configuration = Configuration.parse(configuration)
|
40
|
+
@runtime_facade = Runtime::ForProgrammingLanguages.new(self, user_interface)
|
38
41
|
@unsupported_programming_languages = []
|
39
42
|
@programming_languages = []
|
40
43
|
@language_map = {}
|
41
44
|
end
|
45
|
+
|
46
|
+
def configure(new_configuration)
|
47
|
+
@configuration = Configuration.parse(new_configuration)
|
48
|
+
end
|
42
49
|
|
50
|
+
# Invokes a series of steps +steps_text+. Example:
|
51
|
+
#
|
52
|
+
# invoke(%Q{
|
53
|
+
# Given I have 8 cukes in my belly
|
54
|
+
# Then I should not be thirsty
|
55
|
+
# })
|
43
56
|
def invoke_steps(steps_text, i18n, file_colon_line)
|
44
57
|
file, line = file_colon_line.split(':')
|
45
58
|
parser = Gherkin::Parser::Parser.new(StepInvoker.new(self), true, 'steps')
|
46
59
|
parser.parse(steps_text, file, line.to_i)
|
47
60
|
end
|
48
|
-
|
49
|
-
|
61
|
+
|
62
|
+
# Loads and registers programming language implementation.
|
63
|
+
# Instances are cached, so calling with the same argument
|
64
|
+
# twice will return the same instance.
|
65
|
+
#
|
66
|
+
def load_programming_language(ext)
|
50
67
|
return @language_map[ext] if @language_map[ext]
|
51
68
|
programming_language_class = constantize("Cucumber::#{ext.capitalize}Support::#{ext.capitalize}Language")
|
52
|
-
programming_language = programming_language_class.new(@
|
69
|
+
programming_language = programming_language_class.new(@runtime_facade)
|
53
70
|
@programming_languages << programming_language
|
54
71
|
@language_map[ext] = programming_language
|
55
72
|
programming_language
|
@@ -75,7 +92,7 @@ module Cucumber
|
|
75
92
|
end
|
76
93
|
|
77
94
|
def snippet_text(step_keyword, step_name, multiline_arg_class) #:nodoc:
|
78
|
-
load_programming_language
|
95
|
+
load_programming_language('rb') if unknown_programming_language?
|
79
96
|
@programming_languages.map do |programming_language|
|
80
97
|
programming_language.snippet_text(step_keyword, step_name, multiline_arg_class)
|
81
98
|
end.join("\n")
|
@@ -116,6 +133,7 @@ module Cucumber
|
|
116
133
|
end
|
117
134
|
|
118
135
|
def invoke(step_name, multiline_argument=nil)
|
136
|
+
# It is very important to leave multiline_argument=nil as a vararg. Cuke4Duke needs it that way.
|
119
137
|
begin
|
120
138
|
step_match(step_name).invoke(multiline_argument)
|
121
139
|
rescue Exception => e
|
@@ -127,7 +145,7 @@ module Cucumber
|
|
127
145
|
private
|
128
146
|
|
129
147
|
def guess_step_matches?
|
130
|
-
@
|
148
|
+
@configuration.guess?
|
131
149
|
end
|
132
150
|
|
133
151
|
def matches(step_name, name_to_report)
|
@@ -165,11 +183,11 @@ module Cucumber
|
|
165
183
|
Cucumber.logger
|
166
184
|
end
|
167
185
|
|
168
|
-
def programming_language_for(step_def_file)
|
186
|
+
def programming_language_for(step_def_file)
|
169
187
|
if ext = File.extname(step_def_file)[1..-1]
|
170
188
|
return nil if @unsupported_programming_languages.index(ext)
|
171
189
|
begin
|
172
|
-
load_programming_language
|
190
|
+
load_programming_language(ext)
|
173
191
|
rescue LoadError => e
|
174
192
|
log.debug("Failed to load '#{ext}' programming language for file #{step_def_file}: #{e.message}\n")
|
175
193
|
@unsupported_programming_languages << ext
|