cucumber 0.8.5 → 0.8.6
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/.rspec +1 -1
- data/LICENSE +1 -1
- data/Rakefile +5 -51
- data/bin/cucumber +7 -1
- data/cucumber.gemspec +463 -679
- data/examples/i18n/ar/features/step_definitons/calculator_steps.rb +1 -1
- data/examples/i18n/he/features/step_definitons/calculator_steps.rb +1 -1
- data/examples/i18n/ro/features/step_definitons/calculator_steps.rb +4 -7
- data/examples/i18n/ru/features/division.feature +2 -2
- data/examples/i18n/tr/features/step_definitons/hesap_makinesi_adimlari.rb +3 -3
- data/examples/sinatra/features/support/env.rb +2 -5
- data/examples/v8/features/fibonacci.feature +1 -1
- data/examples/watir/features/step_definitions/search_steps.rb +1 -1
- data/features/background.feature +284 -95
- data/features/custom_formatter.feature +3 -73
- data/features/json_formatter.feature +160 -245
- data/features/step_definitions/cucumber_steps.rb +7 -153
- data/features/support/env.rb +18 -140
- data/fixtures/junit/features/pending.feature +3 -1
- data/fixtures/self_test/features/support/env.rb +8 -0
- data/fixtures/tickets/features.html +1 -1
- data/gem_tasks/examples.rake +1 -1
- data/lib/cucumber.rb +12 -0
- data/lib/cucumber/ast.rb +1 -1
- data/lib/cucumber/ast/background.rb +21 -5
- data/lib/cucumber/ast/examples.rb +12 -4
- data/lib/cucumber/ast/feature.rb +13 -5
- data/lib/cucumber/ast/feature_element.rb +9 -4
- data/lib/cucumber/ast/outline_table.rb +4 -4
- data/lib/cucumber/ast/scenario.rb +7 -5
- data/lib/cucumber/ast/scenario_outline.rb +23 -15
- data/lib/cucumber/ast/step.rb +5 -0
- data/lib/cucumber/ast/step_invocation.rb +21 -15
- data/lib/cucumber/ast/table.rb +14 -8
- data/lib/cucumber/ast/tree_walker.rb +10 -48
- data/lib/cucumber/cli/configuration.rb +33 -8
- data/lib/cucumber/cli/main.rb +20 -35
- data/lib/cucumber/cli/options.rb +8 -7
- data/lib/cucumber/cli/profile_loader.rb +2 -0
- data/lib/cucumber/core_ext/proc.rb +2 -1
- data/lib/cucumber/feature_file.rb +47 -15
- data/lib/cucumber/formatter/ansicolor.rb +3 -5
- data/lib/cucumber/formatter/console.rb +27 -23
- data/lib/cucumber/formatter/cucumber.css +34 -17
- data/lib/cucumber/formatter/cucumber.sass +173 -182
- data/lib/cucumber/formatter/html.rb +46 -11
- data/lib/cucumber/formatter/io.rb +2 -4
- data/lib/cucumber/formatter/json.rb +15 -152
- data/lib/cucumber/formatter/json_pretty.rb +5 -6
- data/lib/cucumber/formatter/junit.rb +28 -22
- data/lib/cucumber/formatter/pdf.rb +6 -6
- data/lib/cucumber/formatter/pretty.rb +5 -5
- data/lib/cucumber/formatter/rerun.rb +22 -11
- data/lib/cucumber/formatter/unicode.rb +41 -20
- data/lib/cucumber/js_support/js_dsl.js +4 -4
- data/lib/cucumber/js_support/js_language.rb +9 -5
- data/lib/cucumber/js_support/js_snippets.rb +2 -2
- data/lib/cucumber/language_support.rb +2 -2
- data/lib/cucumber/parser/gherkin_builder.rb +35 -30
- data/lib/cucumber/platform.rb +8 -8
- data/lib/cucumber/py_support/py_language.rb +2 -2
- data/lib/cucumber/rake/task.rb +80 -31
- data/lib/cucumber/rb_support/rb_dsl.rb +1 -0
- data/lib/cucumber/rb_support/rb_language.rb +10 -8
- data/lib/cucumber/rb_support/rb_step_definition.rb +8 -0
- data/lib/cucumber/rb_support/rb_transform.rb +17 -0
- data/lib/cucumber/rb_support/rb_world.rb +26 -18
- data/lib/cucumber/rspec/doubles.rb +3 -3
- data/lib/cucumber/step_match.rb +6 -2
- data/lib/cucumber/step_mother.rb +6 -427
- data/lib/cucumber/wire_support/configuration.rb +4 -1
- data/lib/cucumber/wire_support/wire_language.rb +3 -10
- data/spec/cucumber/ast/background_spec.rb +68 -6
- data/spec/cucumber/ast/feature_factory.rb +5 -4
- data/spec/cucumber/ast/feature_spec.rb +4 -4
- data/spec/cucumber/ast/outline_table_spec.rb +1 -1
- data/spec/cucumber/ast/scenario_outline_spec.rb +15 -11
- data/spec/cucumber/ast/scenario_spec.rb +4 -4
- data/spec/cucumber/ast/step_spec.rb +3 -3
- data/spec/cucumber/ast/table_spec.rb +38 -2
- data/spec/cucumber/ast/tree_walker_spec.rb +2 -2
- data/spec/cucumber/broadcaster_spec.rb +1 -1
- data/spec/cucumber/cli/configuration_spec.rb +32 -6
- data/spec/cucumber/cli/drb_client_spec.rb +2 -3
- data/spec/cucumber/cli/main_spec.rb +43 -43
- data/spec/cucumber/cli/options_spec.rb +28 -1
- data/spec/cucumber/cli/profile_loader_spec.rb +1 -1
- data/spec/cucumber/core_ext/proc_spec.rb +1 -1
- data/spec/cucumber/formatter/ansicolor_spec.rb +1 -1
- data/spec/cucumber/formatter/duration_spec.rb +1 -1
- data/spec/cucumber/formatter/html_spec.rb +3 -5
- data/spec/cucumber/formatter/junit_spec.rb +16 -2
- data/spec/cucumber/formatter/progress_spec.rb +1 -1
- data/spec/cucumber/formatter/spec_helper.rb +11 -12
- data/spec/cucumber/rb_support/rb_language_spec.rb +241 -28
- data/spec/cucumber/rb_support/rb_step_definition_spec.rb +33 -28
- data/spec/cucumber/rb_support/regexp_argument_matcher_spec.rb +1 -1
- data/spec/cucumber/step_match_spec.rb +11 -9
- data/spec/cucumber/wire_support/configuration_spec.rb +1 -1
- data/spec/cucumber/wire_support/connection_spec.rb +1 -1
- data/spec/cucumber/wire_support/wire_exception_spec.rb +1 -1
- data/spec/cucumber/wire_support/wire_language_spec.rb +1 -1
- data/spec/cucumber/wire_support/wire_packet_spec.rb +1 -1
- data/spec/cucumber/wire_support/wire_step_definition_spec.rb +1 -1
- data/spec/cucumber/world/pending_spec.rb +2 -2
- data/spec/spec_helper.rb +13 -20
- metadata +11 -222
- data/.gitignore +0 -20
- data/Caliper.yml +0 -4
- data/History.txt +0 -1552
- data/README.rdoc +0 -26
- data/VERSION.yml +0 -5
- data/examples/i18n/ro/features/suma.feature +0 -11
- data/features/announce.feature +0 -164
- data/features/around_hooks.feature +0 -232
- data/features/bug_371.feature +0 -32
- data/features/bug_464.feature +0 -16
- data/features/bug_475.feature +0 -42
- data/features/bug_585_tab_indentation.feature +0 -22
- data/features/bug_600.feature +0 -67
- data/features/call_steps_from_stepdefs.feature +0 -154
- data/features/cucumber_cli.feature +0 -591
- data/features/cucumber_cli_outlines.feature +0 -117
- data/features/default_snippets.feature +0 -42
- data/features/diffing.feature +0 -25
- data/features/drb_server_integration.feature +0 -174
- data/features/exception_in_after_block.feature +0 -127
- data/features/exception_in_after_step_block.feature +0 -104
- data/features/exception_in_before_block.feature +0 -98
- data/features/exclude_files.feature +0 -20
- data/features/expand.feature +0 -60
- data/features/html_formatter.feature +0 -8
- data/features/html_formatter/a.html +0 -582
- data/features/junit_formatter.feature +0 -88
- data/features/language_from_header.feature +0 -30
- data/features/language_help.feature +0 -78
- data/features/listener_debugger_formatter.feature +0 -42
- data/features/multiline_names.feature +0 -44
- data/features/negative_tagged_hooks.feature +0 -60
- data/features/post_configuration_hook.feature +0 -37
- data/features/profiles.feature +0 -126
- data/features/rake_task.feature +0 -152
- data/features/report_called_undefined_steps.feature +0 -34
- data/features/rerun_formatter.feature +0 -45
- data/features/simplest.feature +0 -11
- data/features/snippet.feature +0 -23
- data/features/snippets_when_using_star_keyword.feature +0 -36
- data/features/step_definitions/extra_steps.rb +0 -2
- data/features/step_definitions/simplest_steps.rb +0 -3
- data/features/step_definitions/wire_steps.rb +0 -32
- data/features/support/env.rb.simplest +0 -7
- data/features/support/fake_wire_server.rb +0 -77
- data/features/table_diffing.feature +0 -45
- data/features/table_mapping.feature +0 -34
- data/features/tag_logic.feature +0 -258
- data/features/transform.feature +0 -245
- data/features/unicode_table.feature +0 -35
- data/features/usage_and_stepdefs_formatter.feature +0 -169
- data/features/wire_protocol.feature +0 -332
- data/features/wire_protocol_table_diffing.feature +0 -119
- data/features/wire_protocol_tags.feature +0 -87
- data/features/wire_protocol_timeouts.feature +0 -63
- data/features/work_in_progress.feature +0 -156
- data/fixtures/json/features/pystring.feature +0 -8
- data/fixtures/self_test/features/background/background_tagged_before_on_outline.feature +0 -12
- data/fixtures/self_test/features/background/background_with_name.feature +0 -7
- data/fixtures/self_test/features/background/failing_background.feature +0 -12
- data/fixtures/self_test/features/background/failing_background_after_success.feature +0 -11
- data/fixtures/self_test/features/background/multiline_args_background.feature +0 -32
- data/fixtures/self_test/features/background/passing_background.feature +0 -10
- data/fixtures/self_test/features/background/pending_background.feature +0 -10
- data/fixtures/self_test/features/background/scenario_outline_failing_background.feature +0 -16
- data/fixtures/self_test/features/background/scenario_outline_passing_background.feature +0 -16
- data/gem_tasks/features.rake +0 -14
- data/gem_tasks/sdoc.rake +0 -12
- data/lib/cucumber/ast/py_string.rb +0 -80
- data/lib/cucumber/formatter/color_io.rb +0 -23
- data/lib/cucumber/formatter/tag_cloud.rb +0 -35
- data/spec/cucumber/ast/py_string_spec.rb +0 -40
- data/spec/cucumber/formatter/color_io_spec.rb +0 -29
- data/spec/cucumber/step_mother_spec.rb +0 -302
data/lib/cucumber/rake/task.rb
CHANGED
|
@@ -1,4 +1,12 @@
|
|
|
1
1
|
require 'cucumber/platform'
|
|
2
|
+
require 'gherkin/formatter/ansi_escapes'
|
|
3
|
+
|
|
4
|
+
begin
|
|
5
|
+
# Support Rake > 0.8.7
|
|
6
|
+
require 'rake/dsl_definition'
|
|
7
|
+
include Rake::DSL
|
|
8
|
+
rescue LoadError
|
|
9
|
+
end
|
|
2
10
|
|
|
3
11
|
module Cucumber
|
|
4
12
|
module Rake
|
|
@@ -8,7 +16,7 @@ module Cucumber
|
|
|
8
16
|
#
|
|
9
17
|
# Cucumber::Rake::Task.new
|
|
10
18
|
#
|
|
11
|
-
# This will define a task named <tt>cucumber</tt> described as 'Run Cucumber features'.
|
|
19
|
+
# This will define a task named <tt>cucumber</tt> described as 'Run Cucumber features'.
|
|
12
20
|
# It will use steps from 'features/**/*.rb' and features in 'features/**/*.feature'.
|
|
13
21
|
#
|
|
14
22
|
# To further configure the task, you can pass a block:
|
|
@@ -22,68 +30,96 @@ module Cucumber
|
|
|
22
30
|
# Cucumber::Rake::Task.new do |t|
|
|
23
31
|
# t.rcov = true
|
|
24
32
|
# end
|
|
25
|
-
#
|
|
33
|
+
#
|
|
26
34
|
# See the attributes for additional configuration possibilities.
|
|
27
35
|
class Task
|
|
36
|
+
include Gherkin::Formatter::AnsiEscapes
|
|
37
|
+
|
|
28
38
|
class InProcessCucumberRunner #:nodoc:
|
|
29
39
|
attr_reader :args
|
|
30
|
-
|
|
40
|
+
|
|
31
41
|
def initialize(libs, cucumber_opts, feature_files)
|
|
32
42
|
raise "libs must be an Array when running in-process" unless Array === libs
|
|
33
43
|
libs.reverse.each{|lib| $LOAD_PATH.unshift(lib)}
|
|
34
44
|
@args = (
|
|
35
|
-
cucumber_opts +
|
|
45
|
+
cucumber_opts +
|
|
36
46
|
feature_files
|
|
37
47
|
).flatten.compact
|
|
38
48
|
end
|
|
39
|
-
|
|
49
|
+
|
|
40
50
|
def run
|
|
41
51
|
require 'cucumber/cli/main'
|
|
42
52
|
failure = Cucumber::Cli::Main.execute(args)
|
|
43
53
|
raise "Cucumber failed" if failure
|
|
44
54
|
end
|
|
45
55
|
end
|
|
46
|
-
|
|
56
|
+
|
|
47
57
|
class ForkedCucumberRunner #:nodoc:
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
@
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
feature_files
|
|
56
|
-
).flatten
|
|
58
|
+
|
|
59
|
+
def initialize(libs, cucumber_bin, cucumber_opts, bundler, feature_files)
|
|
60
|
+
@libs = libs
|
|
61
|
+
@cucumber_bin = cucumber_bin
|
|
62
|
+
@cucumber_opts = cucumber_opts
|
|
63
|
+
@bundler = bundler
|
|
64
|
+
@feature_files = feature_files
|
|
57
65
|
end
|
|
58
66
|
|
|
59
67
|
def load_path(libs)
|
|
60
|
-
['"%s"' % libs.join(File::PATH_SEPARATOR)]
|
|
68
|
+
['"%s"' % @libs.join(File::PATH_SEPARATOR)]
|
|
61
69
|
end
|
|
62
70
|
|
|
63
71
|
def quoted_binary(cucumber_bin)
|
|
64
72
|
['"%s"' % cucumber_bin]
|
|
65
73
|
end
|
|
66
74
|
|
|
67
|
-
def
|
|
68
|
-
File.exist?("./Gemfile") ?
|
|
75
|
+
def use_bundler
|
|
76
|
+
@bundler.nil? ? File.exist?("./Gemfile") && gem_available?("bundler") : @bundler
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
def gem_available?(gemname)
|
|
80
|
+
gem_available_new_rubygems?(gemname) || gem_available_old_rubygems?(gemname)
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
def gem_available_old_rubygems?(gemname)
|
|
84
|
+
Gem.available?(gemname)
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
def gem_available_new_rubygems?(gemname)
|
|
88
|
+
Gem::Specification.respond_to?(:find_all_by_name) && Gem::Specification.find_all_by_name(gemname).any?
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
def cmd
|
|
92
|
+
if use_bundler
|
|
93
|
+
[ Cucumber::RUBY_BINARY, '-S', 'bundle', 'exec', 'cucumber', @cucumber_opts,
|
|
94
|
+
@feature_files ].flatten
|
|
95
|
+
else
|
|
96
|
+
[ Cucumber::RUBY_BINARY, '-I', load_path(@libs), quoted_binary(@cucumber_bin),
|
|
97
|
+
@cucumber_opts, @feature_files ].flatten
|
|
98
|
+
end
|
|
69
99
|
end
|
|
70
100
|
|
|
71
101
|
def run
|
|
72
|
-
sh(
|
|
102
|
+
sh(cmd.join(" "))
|
|
73
103
|
end
|
|
74
104
|
end
|
|
75
105
|
|
|
76
106
|
class RCovCucumberRunner < ForkedCucumberRunner #:nodoc:
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
107
|
+
|
|
108
|
+
def initialize(libs, cucumber_bin, cucumber_opts, bundler, feature_files, rcov_opts)
|
|
109
|
+
super( libs, cucumber_bin, cucumber_opts, bundler, feature_files )
|
|
110
|
+
@rcov_opts = rcov_opts
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
def cmd
|
|
114
|
+
if use_bundler
|
|
115
|
+
[Cucumber::RUBY_BINARY, '-S', 'bundle', 'exec', 'rcov', @rcov_opts,
|
|
116
|
+
quoted_binary(@cucumber_bin), '--', @cucumber_opts, @feature_files].flatten
|
|
117
|
+
else
|
|
118
|
+
[Cucumber::RUBY_BINARY, '-I', load_path(@libs), '-S', 'rcov', @rcov_opts,
|
|
119
|
+
quoted_binary(@cucumber_bin), '--', @cucumber_opts, @feature_files].flatten
|
|
120
|
+
end
|
|
86
121
|
end
|
|
122
|
+
|
|
87
123
|
end
|
|
88
124
|
|
|
89
125
|
LIB = File.expand_path(File.dirname(__FILE__) + '/../..') #:nodoc:
|
|
@@ -104,6 +140,12 @@ module Cucumber
|
|
|
104
140
|
# Run cucumber with RCov? Defaults to false. If you set this to
|
|
105
141
|
# true, +fork+ is implicit.
|
|
106
142
|
attr_accessor :rcov
|
|
143
|
+
def rcov=(flag)
|
|
144
|
+
if(flag && Cucumber::RUBY_1_9)
|
|
145
|
+
raise failed + "RCov only works on Ruby 1.8.x. You may want to use SimpleCov: https://github.com/colszowka/simplecov" + reset
|
|
146
|
+
end
|
|
147
|
+
@rcov = flag
|
|
148
|
+
end
|
|
107
149
|
|
|
108
150
|
# Extra options to pass to rcov.
|
|
109
151
|
# It's recommended to pass an Array, but if it's a String it will be #split by ' '.
|
|
@@ -117,10 +159,17 @@ module Cucumber
|
|
|
117
159
|
# your load path and gems.
|
|
118
160
|
attr_accessor :fork
|
|
119
161
|
|
|
120
|
-
# Define what profile to be used. When used with cucumber_opts it is simply appended
|
|
162
|
+
# Define what profile to be used. When used with cucumber_opts it is simply appended
|
|
121
163
|
# to it. Will be ignored when CUCUMBER_OPTS is used.
|
|
122
164
|
attr_accessor :profile
|
|
123
165
|
|
|
166
|
+
# Whether or not to run with bundler (bundle exec). Setting this to false may speed
|
|
167
|
+
# up the execution. The default value is true if Bundler is installed and you have
|
|
168
|
+
# a Gemfile, false otherwise.
|
|
169
|
+
#
|
|
170
|
+
# Note that this attribute has no effect if you don't run in forked mode.
|
|
171
|
+
attr_accessor :bundler
|
|
172
|
+
|
|
124
173
|
# Define Cucumber Rake task
|
|
125
174
|
def initialize(task_name = "cucumber", desc = "Run Cucumber features")
|
|
126
175
|
@task_name, @desc = task_name, desc
|
|
@@ -146,9 +195,9 @@ module Cucumber
|
|
|
146
195
|
def runner(task_args = nil) #:nodoc:
|
|
147
196
|
cucumber_opts = [(ENV['CUCUMBER_OPTS'] ? ENV['CUCUMBER_OPTS'].split(/\s+/) : nil) || cucumber_opts_with_profile]
|
|
148
197
|
if(@rcov)
|
|
149
|
-
RCovCucumberRunner.new(libs, binary, cucumber_opts, feature_files, rcov_opts)
|
|
198
|
+
RCovCucumberRunner.new(libs, binary, cucumber_opts, bundler, feature_files, rcov_opts)
|
|
150
199
|
elsif(@fork)
|
|
151
|
-
ForkedCucumberRunner.new(libs, binary, cucumber_opts, feature_files)
|
|
200
|
+
ForkedCucumberRunner.new(libs, binary, cucumber_opts, bundler, feature_files)
|
|
152
201
|
else
|
|
153
202
|
InProcessCucumberRunner.new(libs, cucumber_opts, feature_files)
|
|
154
203
|
end
|
|
@@ -88,6 +88,7 @@ module Cucumber
|
|
|
88
88
|
|
|
89
89
|
# Registers a proc that will run after Cucumber is configured. You can register as
|
|
90
90
|
# as you want (typically from ruby scripts under <tt>support/hooks.rb</tt>).
|
|
91
|
+
# TODO: Deprecate this
|
|
91
92
|
def AfterConfiguration(&proc)
|
|
92
93
|
RbDsl.register_rb_hook('after_configuration', [], proc)
|
|
93
94
|
end
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
require 'cucumber/core_ext/instance_exec'
|
|
1
2
|
require 'cucumber/rb_support/rb_dsl'
|
|
2
3
|
require 'cucumber/rb_support/rb_world'
|
|
3
4
|
require 'cucumber/rb_support/rb_step_definition'
|
|
@@ -21,7 +22,7 @@ module Cucumber
|
|
|
21
22
|
message << first_proc.backtrace_line('World') << "\n"
|
|
22
23
|
message << second_proc.backtrace_line('World') << "\n\n"
|
|
23
24
|
message << "Use Ruby modules instead to extend your worlds. See the Cucumber::RbSupport::RbDsl#World RDoc\n"
|
|
24
|
-
message << "or http://wiki.github.com/
|
|
25
|
+
message << "or http://wiki.github.com/cucumber/cucumber/a-whole-new-world.\n\n"
|
|
25
26
|
super(message)
|
|
26
27
|
end
|
|
27
28
|
end
|
|
@@ -29,7 +30,8 @@ module Cucumber
|
|
|
29
30
|
# The Ruby implementation of the programming language API.
|
|
30
31
|
class RbLanguage
|
|
31
32
|
include LanguageSupport::LanguageMethods
|
|
32
|
-
attr_reader :current_world
|
|
33
|
+
attr_reader :current_world,
|
|
34
|
+
:step_definitions
|
|
33
35
|
|
|
34
36
|
Gherkin::I18n.code_keywords.each do |adverb|
|
|
35
37
|
RbDsl.alias_adverb(adverb)
|
|
@@ -65,7 +67,7 @@ module Cucumber
|
|
|
65
67
|
|
|
66
68
|
# Gets called for each file under features (or whatever is overridden
|
|
67
69
|
# with --require).
|
|
68
|
-
def step_definitions_for(rb_file)
|
|
70
|
+
def step_definitions_for(rb_file) # Looks Unused - Delete?
|
|
69
71
|
begin
|
|
70
72
|
require rb_file # This will cause self.add_step_definition and self.add_hook to be called from RbDsl
|
|
71
73
|
step_definitions
|
|
@@ -76,7 +78,7 @@ module Cucumber
|
|
|
76
78
|
@step_definitions = nil
|
|
77
79
|
end
|
|
78
80
|
end
|
|
79
|
-
|
|
81
|
+
|
|
80
82
|
def step_matches(name_to_match, name_to_format)
|
|
81
83
|
@step_definitions.map do |step_definition|
|
|
82
84
|
if(arguments = step_definition.arguments_from(name_to_match))
|
|
@@ -89,7 +91,7 @@ module Cucumber
|
|
|
89
91
|
|
|
90
92
|
ARGUMENT_PATTERNS = ['"([^"]*)"', '(\d+)']
|
|
91
93
|
|
|
92
|
-
def snippet_text(
|
|
94
|
+
def snippet_text(code_keyword, step_name, multiline_arg_class)
|
|
93
95
|
snippet_pattern = Regexp.escape(step_name).gsub('\ ', ' ').gsub('/', '\/')
|
|
94
96
|
arg_count = 0
|
|
95
97
|
ARGUMENT_PATTERNS.each do |pattern|
|
|
@@ -105,7 +107,7 @@ module Cucumber
|
|
|
105
107
|
multiline_class_comment = "# #{multiline_arg_class.default_arg_name} is a #{multiline_arg_class.to_s}\n "
|
|
106
108
|
end
|
|
107
109
|
|
|
108
|
-
"#{
|
|
110
|
+
"#{code_keyword} /^#{snippet_pattern}$/ do#{block_arg_string}\n #{multiline_class_comment}pending # express the regexp above with the code you wish you had\nend"
|
|
109
111
|
end
|
|
110
112
|
|
|
111
113
|
def begin_rb_scenario(scenario)
|
|
@@ -138,9 +140,9 @@ module Cucumber
|
|
|
138
140
|
end
|
|
139
141
|
|
|
140
142
|
def load_code_file(code_file)
|
|
141
|
-
|
|
143
|
+
load File.expand_path(code_file) # This will cause self.add_step_definition, self.add_hook, and self.add_transform to be called from RbDsl
|
|
142
144
|
end
|
|
143
|
-
|
|
145
|
+
|
|
144
146
|
protected
|
|
145
147
|
|
|
146
148
|
def begin_scenario(scenario)
|
|
@@ -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
|
|
@@ -32,6 +32,23 @@ module Cucumber
|
|
|
32
32
|
@rb_language.current_world.cucumber_instance_exec(true, @regexp.inspect, *args, &@proc)
|
|
33
33
|
end
|
|
34
34
|
end
|
|
35
|
+
|
|
36
|
+
def to_s
|
|
37
|
+
strip_captures(strip_anchors(@regexp.source))
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
private
|
|
41
|
+
|
|
42
|
+
def strip_captures(regexp_source)
|
|
43
|
+
regexp_source.
|
|
44
|
+
gsub(/(\()/, '').
|
|
45
|
+
gsub(/(\))/, '')
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def strip_anchors(regexp_source)
|
|
49
|
+
regexp_source.
|
|
50
|
+
gsub(/(^\^|\$$)/, '')
|
|
51
|
+
end
|
|
35
52
|
end
|
|
36
53
|
end
|
|
37
54
|
end
|
|
@@ -1,7 +1,11 @@
|
|
|
1
|
+
require 'gherkin/formatter/ansi_escapes'
|
|
2
|
+
|
|
1
3
|
module Cucumber
|
|
2
4
|
module RbSupport
|
|
3
5
|
# All steps are run in the context of an object that extends this module.
|
|
4
6
|
module RbWorld
|
|
7
|
+
include Gherkin::Formatter::AnsiEscapes
|
|
8
|
+
|
|
5
9
|
class << self
|
|
6
10
|
def alias_adverb(adverb)
|
|
7
11
|
alias_method adverb, :__cucumber_invoke
|
|
@@ -32,14 +36,19 @@ module Cucumber
|
|
|
32
36
|
@__cucumber_step_mother.table(text_or_table, file, line_offset)
|
|
33
37
|
end
|
|
34
38
|
|
|
35
|
-
# See StepMother#
|
|
36
|
-
def
|
|
37
|
-
@__cucumber_step_mother.
|
|
39
|
+
# See StepMother#doc_string
|
|
40
|
+
def doc_string(string_with_triple_quotes, file=nil, line_offset=0)
|
|
41
|
+
@__cucumber_step_mother.doc_string(string_with_triple_quotes, file, line_offset)
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def announce(*messages)
|
|
45
|
+
STDERR.puts failed + "WARNING: #announce is deprecated. Use #puts instead:" + caller[0] + reset
|
|
46
|
+
puts(*messages)
|
|
38
47
|
end
|
|
39
48
|
|
|
40
|
-
# See StepMother#
|
|
41
|
-
def
|
|
42
|
-
@__cucumber_step_mother.
|
|
49
|
+
# See StepMother#puts
|
|
50
|
+
def puts(*messages)
|
|
51
|
+
@__cucumber_step_mother.puts(*messages)
|
|
43
52
|
end
|
|
44
53
|
|
|
45
54
|
# See StepMother#ask
|
|
@@ -48,17 +57,8 @@ module Cucumber
|
|
|
48
57
|
end
|
|
49
58
|
|
|
50
59
|
# See StepMother#embed
|
|
51
|
-
def embed(file, mime_type)
|
|
52
|
-
@__cucumber_step_mother.embed(file, mime_type)
|
|
53
|
-
end
|
|
54
|
-
|
|
55
|
-
# Prints out the world class, followed by all included modules.
|
|
56
|
-
def announce_world
|
|
57
|
-
announce "WORLD:\n #{self.class}"
|
|
58
|
-
world = self
|
|
59
|
-
(class << self; self; end).instance_eval do
|
|
60
|
-
world.announce " #{included_modules.join("\n ")}"
|
|
61
|
-
end
|
|
60
|
+
def embed(file, mime_type, label='Screenshot')
|
|
61
|
+
@__cucumber_step_mother.embed(file, mime_type, label)
|
|
62
62
|
end
|
|
63
63
|
|
|
64
64
|
# Mark the matched step as pending.
|
|
@@ -88,7 +88,15 @@ module Cucumber
|
|
|
88
88
|
# such errors in World we define it to just return a simple String.
|
|
89
89
|
#
|
|
90
90
|
def inspect #:nodoc:
|
|
91
|
-
|
|
91
|
+
modules = [self.class]
|
|
92
|
+
(class << self; self; end).instance_eval do
|
|
93
|
+
modules += included_modules
|
|
94
|
+
end
|
|
95
|
+
sprintf("#<%s:0x%x>", modules.join('+'), self.object_id)
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
def to_s
|
|
99
|
+
inspect
|
|
92
100
|
end
|
|
93
101
|
end
|
|
94
102
|
end
|
|
@@ -4,13 +4,13 @@ RSpec.configuration.configure_mock_framework
|
|
|
4
4
|
World(RSpec::Core::MockFrameworkAdapter)
|
|
5
5
|
|
|
6
6
|
Before do
|
|
7
|
-
|
|
7
|
+
RSpec::Mocks::setup(self)
|
|
8
8
|
end
|
|
9
9
|
|
|
10
10
|
After do
|
|
11
11
|
begin
|
|
12
|
-
|
|
12
|
+
RSpec::Mocks::verify
|
|
13
13
|
ensure
|
|
14
|
-
|
|
14
|
+
RSpec::Mocks::teardown
|
|
15
15
|
end
|
|
16
16
|
end
|
data/lib/cucumber/step_match.rb
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
module Cucumber
|
|
2
2
|
class StepMatch #:nodoc:
|
|
3
|
-
attr_reader :step_definition
|
|
3
|
+
attr_reader :step_definition, :step_arguments
|
|
4
4
|
|
|
5
5
|
# Creates a new StepMatch. The +name_to_report+ argument is what's reported, unless it's is,
|
|
6
6
|
# in which case +name_to_report+ is used instead.
|
|
@@ -20,7 +20,7 @@ module Cucumber
|
|
|
20
20
|
end
|
|
21
21
|
|
|
22
22
|
def invoke(multiline_arg)
|
|
23
|
-
multiline_arg = Ast::
|
|
23
|
+
multiline_arg = Ast::DocString.new(multiline_arg) if String === multiline_arg
|
|
24
24
|
all_args = args
|
|
25
25
|
all_args << multiline_arg.to_step_definition_arg if multiline_arg
|
|
26
26
|
@step_definition.invoke(all_args)
|
|
@@ -107,5 +107,9 @@ module Cucumber
|
|
|
107
107
|
def text_length
|
|
108
108
|
@step.text_length
|
|
109
109
|
end
|
|
110
|
+
|
|
111
|
+
def step_arguments
|
|
112
|
+
[]
|
|
113
|
+
end
|
|
110
114
|
end
|
|
111
115
|
end
|
data/lib/cucumber/step_mother.rb
CHANGED
|
@@ -1,431 +1,10 @@
|
|
|
1
|
-
require 'cucumber/
|
|
2
|
-
require 'cucumber/core_ext/instance_exec'
|
|
3
|
-
require 'cucumber/language_support/language_methods'
|
|
4
|
-
require 'cucumber/formatter/duration'
|
|
5
|
-
require 'cucumber/cli/options'
|
|
6
|
-
require 'timeout'
|
|
1
|
+
require 'cucumber/runtime'
|
|
7
2
|
|
|
8
3
|
module Cucumber
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
def initialize(step_name)
|
|
14
|
-
super %{Undefined step: "#{step_name}"}
|
|
15
|
-
@step_name = step_name
|
|
16
|
-
end
|
|
17
|
-
|
|
18
|
-
def nested!
|
|
19
|
-
@nested = true
|
|
20
|
-
end
|
|
21
|
-
|
|
22
|
-
def nested?
|
|
23
|
-
@nested
|
|
24
|
-
end
|
|
25
|
-
end
|
|
26
|
-
|
|
27
|
-
# Raised when a StepDefinition's block invokes World#pending
|
|
28
|
-
class Pending < StandardError
|
|
29
|
-
end
|
|
30
|
-
|
|
31
|
-
# Raised when a step matches 2 or more StepDefinitions
|
|
32
|
-
class Ambiguous < StandardError
|
|
33
|
-
def initialize(step_name, step_definitions, used_guess)
|
|
34
|
-
message = "Ambiguous match of \"#{step_name}\":\n\n"
|
|
35
|
-
message << step_definitions.map{|sd| sd.backtrace_line}.join("\n")
|
|
36
|
-
message << "\n\n"
|
|
37
|
-
message << "You can run again with --guess to make Cucumber be more smart about it\n" unless used_guess
|
|
38
|
-
super(message)
|
|
39
|
-
end
|
|
40
|
-
end
|
|
41
|
-
|
|
42
|
-
class TagExcess < StandardError
|
|
43
|
-
def initialize(messages)
|
|
44
|
-
super(messages.join("\n"))
|
|
45
|
-
end
|
|
46
|
-
end
|
|
47
|
-
|
|
48
|
-
# This is the meaty part of Cucumber that ties everything together.
|
|
49
|
-
class StepMother
|
|
50
|
-
include Constantize
|
|
51
|
-
include Formatter::Duration
|
|
52
|
-
attr_writer :options, :visitor, :log
|
|
53
|
-
|
|
54
|
-
def initialize
|
|
55
|
-
@unsupported_programming_languages = []
|
|
56
|
-
@programming_languages = []
|
|
57
|
-
@language_map = {}
|
|
58
|
-
@current_scenario = nil
|
|
59
|
-
end
|
|
60
|
-
|
|
61
|
-
def load_plain_text_features(feature_files)
|
|
62
|
-
features = Ast::Features.new
|
|
63
|
-
|
|
64
|
-
tag_counts = {}
|
|
65
|
-
start = Time.new
|
|
66
|
-
log.debug("Features:\n")
|
|
67
|
-
feature_files.each do |f|
|
|
68
|
-
feature_file = FeatureFile.new(f)
|
|
69
|
-
feature = feature_file.parse(options, tag_counts)
|
|
70
|
-
if feature
|
|
71
|
-
features.add_feature(feature)
|
|
72
|
-
log.debug(" * #{f}\n")
|
|
73
|
-
end
|
|
74
|
-
end
|
|
75
|
-
duration = Time.now - start
|
|
76
|
-
log.debug("Parsing feature files took #{format_duration(duration)}\n\n")
|
|
77
|
-
|
|
78
|
-
check_tag_limits(tag_counts)
|
|
79
|
-
|
|
80
|
-
features
|
|
81
|
-
end
|
|
82
|
-
|
|
83
|
-
def check_tag_limits(tag_counts)
|
|
84
|
-
error_messages = []
|
|
85
|
-
options[:tag_expression].limits.each do |tag_name, tag_limit|
|
|
86
|
-
tag_locations = (tag_counts[tag_name] || [])
|
|
87
|
-
tag_count = tag_locations.length
|
|
88
|
-
if tag_count > tag_limit
|
|
89
|
-
error = "#{tag_name} occurred #{tag_count} times, but the limit was set to #{tag_limit}\n " +
|
|
90
|
-
tag_locations.join("\n ")
|
|
91
|
-
error_messages << error
|
|
92
|
-
end
|
|
93
|
-
end
|
|
94
|
-
raise TagExcess.new(error_messages) if error_messages.any?
|
|
95
|
-
end
|
|
96
|
-
|
|
97
|
-
def load_code_files(step_def_files)
|
|
98
|
-
log.debug("Code:\n")
|
|
99
|
-
step_def_files.each do |step_def_file|
|
|
100
|
-
load_code_file(step_def_file)
|
|
101
|
-
end
|
|
102
|
-
log.debug("\n")
|
|
103
|
-
end
|
|
104
|
-
|
|
105
|
-
def load_code_file(step_def_file)
|
|
106
|
-
if programming_language = programming_language_for(step_def_file)
|
|
107
|
-
log.debug(" * #{step_def_file}\n")
|
|
108
|
-
programming_language.load_code_file(step_def_file)
|
|
109
|
-
else
|
|
110
|
-
log.debug(" * #{step_def_file} [NOT SUPPORTED]\n")
|
|
111
|
-
end
|
|
112
|
-
end
|
|
113
|
-
|
|
114
|
-
# Loads and registers programming language implementation.
|
|
115
|
-
# Instances are cached, so calling with the same argument
|
|
116
|
-
# twice will return the same instance.
|
|
117
|
-
#
|
|
118
|
-
def load_programming_language(ext)
|
|
119
|
-
return @language_map[ext] if @language_map[ext]
|
|
120
|
-
programming_language_class = constantize("Cucumber::#{ext.capitalize}Support::#{ext.capitalize}Language")
|
|
121
|
-
programming_language = programming_language_class.new(self)
|
|
122
|
-
@programming_languages << programming_language
|
|
123
|
-
@language_map[ext] = programming_language
|
|
124
|
-
programming_language
|
|
125
|
-
end
|
|
126
|
-
|
|
127
|
-
# Returns the options passed on the command line.
|
|
128
|
-
def options
|
|
129
|
-
@options ||= Cli::Options.new
|
|
130
|
-
end
|
|
131
|
-
|
|
132
|
-
def step_visited(step) #:nodoc:
|
|
133
|
-
steps << step unless steps.index(step)
|
|
134
|
-
end
|
|
135
|
-
|
|
136
|
-
def steps(status = nil) #:nodoc:
|
|
137
|
-
@steps ||= []
|
|
138
|
-
if(status)
|
|
139
|
-
@steps.select{|step| step.status == status}
|
|
140
|
-
else
|
|
141
|
-
@steps
|
|
142
|
-
end
|
|
143
|
-
end
|
|
144
|
-
|
|
145
|
-
# Output +announcement+ alongside the formatted output.
|
|
146
|
-
# This is an alternative to using Kernel#puts - it will display
|
|
147
|
-
# nicer, and in all outputs (in case you use several formatters)
|
|
148
|
-
#
|
|
149
|
-
def announce(msg)
|
|
150
|
-
msg.respond_to?(:join) ? @visitor.announce(msg.join("\n")) : @visitor.announce(msg.to_s)
|
|
151
|
-
end
|
|
152
|
-
|
|
153
|
-
# Suspends execution and prompts +question+ to the console (STDOUT).
|
|
154
|
-
# An operator (manual tester) can then enter a line of text and hit
|
|
155
|
-
# <ENTER>. The entered text is returned, and both +question+ and
|
|
156
|
-
# the result is added to the output using #announce.
|
|
157
|
-
#
|
|
158
|
-
# If you want a beep to happen (to grab the manual tester's attention),
|
|
159
|
-
# just prepend ASCII character 7 to the question:
|
|
160
|
-
#
|
|
161
|
-
# ask("#{7.chr}How many cukes are in the external system?")
|
|
162
|
-
#
|
|
163
|
-
# If that doesn't issue a beep, you can shell out to something else
|
|
164
|
-
# that makes a sound before invoking #ask.
|
|
165
|
-
#
|
|
166
|
-
def ask(question, timeout_seconds)
|
|
167
|
-
STDOUT.puts(question)
|
|
168
|
-
STDOUT.flush
|
|
169
|
-
announce(question)
|
|
170
|
-
|
|
171
|
-
if(Cucumber::JRUBY)
|
|
172
|
-
answer = jruby_gets(timeout_seconds)
|
|
173
|
-
else
|
|
174
|
-
answer = mri_gets(timeout_seconds)
|
|
175
|
-
end
|
|
176
|
-
|
|
177
|
-
if(answer)
|
|
178
|
-
announce(answer)
|
|
179
|
-
answer
|
|
180
|
-
else
|
|
181
|
-
raise("Waited for input for #{timeout_seconds} seconds, then timed out.")
|
|
182
|
-
end
|
|
183
|
-
end
|
|
184
|
-
|
|
185
|
-
# Embed +file+ of MIME type +mime_type+ into the output. This may or may
|
|
186
|
-
# not be ignored, depending on what kind of formatter(s) are active.
|
|
187
|
-
#
|
|
188
|
-
def embed(file, mime_type)
|
|
189
|
-
@visitor.embed(file, mime_type)
|
|
190
|
-
end
|
|
191
|
-
|
|
192
|
-
def scenarios(status = nil) #:nodoc:
|
|
193
|
-
@scenarios ||= []
|
|
194
|
-
if(status)
|
|
195
|
-
@scenarios.select{|scenario| scenario.status == status}
|
|
196
|
-
else
|
|
197
|
-
@scenarios
|
|
198
|
-
end
|
|
199
|
-
end
|
|
200
|
-
|
|
201
|
-
def invoke(step_name, multiline_argument=nil)
|
|
202
|
-
begin
|
|
203
|
-
step_match(step_name).invoke(multiline_argument)
|
|
204
|
-
rescue Exception => e
|
|
205
|
-
e.nested! if Undefined === e
|
|
206
|
-
raise e
|
|
207
|
-
end
|
|
208
|
-
end
|
|
209
|
-
|
|
210
|
-
# Invokes a series of steps +steps_text+. Example:
|
|
211
|
-
#
|
|
212
|
-
# invoke(%Q{
|
|
213
|
-
# Given I have 8 cukes in my belly
|
|
214
|
-
# Then I should not be thirsty
|
|
215
|
-
# })
|
|
216
|
-
def invoke_steps(steps_text, i18n, file_colon_line)
|
|
217
|
-
file, line = file_colon_line.split(':')
|
|
218
|
-
parser = Gherkin::Parser::Parser.new(StepInvoker.new(self), true, 'steps')
|
|
219
|
-
parser.parse(steps_text, file, line.to_i)
|
|
220
|
-
end
|
|
221
|
-
|
|
222
|
-
class StepInvoker
|
|
223
|
-
def initialize(step_mother)
|
|
224
|
-
@step_mother = step_mother
|
|
225
|
-
end
|
|
226
|
-
|
|
227
|
-
def step(statement, multiline_arg, result)
|
|
228
|
-
cucumber_multiline_arg = case(multiline_arg)
|
|
229
|
-
when Gherkin::Formatter::Model::PyString
|
|
230
|
-
multiline_arg.value
|
|
231
|
-
when Array
|
|
232
|
-
Ast::Table.new(multiline_arg.map{|row| row.cells})
|
|
233
|
-
else
|
|
234
|
-
nil
|
|
235
|
-
end
|
|
236
|
-
@step_mother.invoke(*[statement.name, cucumber_multiline_arg].compact)
|
|
237
|
-
end
|
|
238
|
-
|
|
239
|
-
def eof
|
|
240
|
-
end
|
|
241
|
-
end
|
|
242
|
-
|
|
243
|
-
# Returns a Cucumber::Ast::Table for +text_or_table+, which can either
|
|
244
|
-
# be a String:
|
|
245
|
-
#
|
|
246
|
-
# table(%{
|
|
247
|
-
# | account | description | amount |
|
|
248
|
-
# | INT-100 | Taxi | 114 |
|
|
249
|
-
# | CUC-101 | Peeler | 22 |
|
|
250
|
-
# })
|
|
251
|
-
#
|
|
252
|
-
# or a 2D Array:
|
|
253
|
-
#
|
|
254
|
-
# table([
|
|
255
|
-
# %w{ account description amount },
|
|
256
|
-
# %w{ INT-100 Taxi 114 },
|
|
257
|
-
# %w{ CUC-101 Peeler 22 }
|
|
258
|
-
# ])
|
|
259
|
-
#
|
|
260
|
-
def table(text_or_table, file=nil, line_offset=0)
|
|
261
|
-
if Array === text_or_table
|
|
262
|
-
Ast::Table.new(text_or_table)
|
|
263
|
-
else
|
|
264
|
-
Ast::Table.parse(text_or_table, file, line_offset)
|
|
265
|
-
end
|
|
266
|
-
end
|
|
267
|
-
|
|
268
|
-
# Returns a regular String for +string_with_triple_quotes+. Example:
|
|
269
|
-
#
|
|
270
|
-
# """
|
|
271
|
-
# hello
|
|
272
|
-
# world
|
|
273
|
-
# """
|
|
274
|
-
#
|
|
275
|
-
# Is retured as: " hello\nworld"
|
|
276
|
-
#
|
|
277
|
-
def py_string(string_with_triple_quotes, file=nil, line_offset=0)
|
|
278
|
-
Ast::PyString.parse(string_with_triple_quotes)
|
|
279
|
-
end
|
|
280
|
-
|
|
281
|
-
def step_match(step_name, name_to_report=nil) #:nodoc:
|
|
282
|
-
matches = @programming_languages.map do |programming_language|
|
|
283
|
-
programming_language.step_matches(step_name, name_to_report).to_a
|
|
284
|
-
end.flatten
|
|
285
|
-
raise Undefined.new(step_name) if matches.empty?
|
|
286
|
-
matches = best_matches(step_name, matches) if matches.size > 1 && options[:guess]
|
|
287
|
-
raise Ambiguous.new(step_name, matches, options[:guess]) if matches.size > 1
|
|
288
|
-
matches[0]
|
|
289
|
-
end
|
|
290
|
-
|
|
291
|
-
def best_matches(step_name, step_matches) #:nodoc:
|
|
292
|
-
no_groups = step_matches.select {|step_match| step_match.args.length == 0}
|
|
293
|
-
max_arg_length = step_matches.map {|step_match| step_match.args.length }.max
|
|
294
|
-
top_groups = step_matches.select {|step_match| step_match.args.length == max_arg_length }
|
|
295
|
-
|
|
296
|
-
if no_groups.any?
|
|
297
|
-
longest_regexp_length = no_groups.map {|step_match| step_match.text_length }.max
|
|
298
|
-
no_groups.select {|step_match| step_match.text_length == longest_regexp_length }
|
|
299
|
-
elsif top_groups.any?
|
|
300
|
-
shortest_capture_length = top_groups.map {|step_match| step_match.args.inject(0) {|sum, c| sum + c.to_s.length } }.min
|
|
301
|
-
top_groups.select {|step_match| step_match.args.inject(0) {|sum, c| sum + c.to_s.length } == shortest_capture_length }
|
|
302
|
-
else
|
|
303
|
-
top_groups
|
|
304
|
-
end
|
|
305
|
-
end
|
|
306
|
-
|
|
307
|
-
def unmatched_step_definitions
|
|
308
|
-
@programming_languages.map do |programming_language|
|
|
309
|
-
programming_language.unmatched_step_definitions
|
|
310
|
-
end.flatten
|
|
311
|
-
end
|
|
312
|
-
|
|
313
|
-
def snippet_text(step_keyword, step_name, multiline_arg_class) #:nodoc:
|
|
314
|
-
load_programming_language('rb') if unknown_programming_language?
|
|
315
|
-
@programming_languages.map do |programming_language|
|
|
316
|
-
programming_language.snippet_text(step_keyword, step_name, multiline_arg_class)
|
|
317
|
-
end.join("\n")
|
|
318
|
-
end
|
|
319
|
-
|
|
320
|
-
def unknown_programming_language?
|
|
321
|
-
@programming_languages.empty?
|
|
322
|
-
end
|
|
323
|
-
|
|
324
|
-
def with_hooks(scenario, skip_hooks=false)
|
|
325
|
-
around(scenario, skip_hooks) do
|
|
326
|
-
before_and_after(scenario, skip_hooks) do
|
|
327
|
-
yield scenario
|
|
328
|
-
end
|
|
329
|
-
end
|
|
330
|
-
end
|
|
331
|
-
|
|
332
|
-
def around(scenario, skip_hooks=false, &block) #:nodoc:
|
|
333
|
-
unless skip_hooks
|
|
334
|
-
@programming_languages.reverse.inject(block) do |blk, programming_language|
|
|
335
|
-
proc do
|
|
336
|
-
programming_language.around(scenario) do
|
|
337
|
-
blk.call(scenario)
|
|
338
|
-
end
|
|
339
|
-
end
|
|
340
|
-
end.call
|
|
341
|
-
else
|
|
342
|
-
yield
|
|
343
|
-
end
|
|
344
|
-
end
|
|
345
|
-
|
|
346
|
-
def before_and_after(scenario, skip_hooks=false) #:nodoc:
|
|
347
|
-
before(scenario) unless skip_hooks
|
|
348
|
-
yield scenario
|
|
349
|
-
after(scenario) unless skip_hooks
|
|
350
|
-
scenario_visited(scenario)
|
|
351
|
-
end
|
|
352
|
-
|
|
353
|
-
def before(scenario) #:nodoc:
|
|
354
|
-
return if options[:dry_run] || @current_scenario
|
|
355
|
-
@current_scenario = scenario
|
|
356
|
-
@programming_languages.each do |programming_language|
|
|
357
|
-
programming_language.before(scenario)
|
|
358
|
-
end
|
|
359
|
-
end
|
|
360
|
-
|
|
361
|
-
def after(scenario) #:nodoc:
|
|
362
|
-
@current_scenario = nil
|
|
363
|
-
return if options[:dry_run]
|
|
364
|
-
@programming_languages.each do |programming_language|
|
|
365
|
-
programming_language.after(scenario)
|
|
366
|
-
end
|
|
367
|
-
end
|
|
368
|
-
|
|
369
|
-
def after_step #:nodoc:
|
|
370
|
-
return if options[:dry_run]
|
|
371
|
-
@programming_languages.each do |programming_language|
|
|
372
|
-
programming_language.execute_after_step(@current_scenario)
|
|
373
|
-
end
|
|
374
|
-
end
|
|
375
|
-
|
|
376
|
-
def after_configuration(configuration) #:nodoc
|
|
377
|
-
@programming_languages.each do |programming_language|
|
|
378
|
-
programming_language.after_configuration(configuration)
|
|
379
|
-
end
|
|
380
|
-
end
|
|
381
|
-
|
|
382
|
-
private
|
|
383
|
-
|
|
384
|
-
def programming_language_for(step_def_file) #:nodoc:
|
|
385
|
-
if ext = File.extname(step_def_file)[1..-1]
|
|
386
|
-
return nil if @unsupported_programming_languages.index(ext)
|
|
387
|
-
begin
|
|
388
|
-
load_programming_language(ext)
|
|
389
|
-
rescue LoadError => e
|
|
390
|
-
log.debug("Failed to load '#{ext}' programming language for file #{step_def_file}: #{e.message}\n")
|
|
391
|
-
@unsupported_programming_languages << ext
|
|
392
|
-
nil
|
|
393
|
-
end
|
|
394
|
-
else
|
|
395
|
-
nil
|
|
396
|
-
end
|
|
397
|
-
end
|
|
398
|
-
|
|
399
|
-
def max_step_definition_length #:nodoc:
|
|
400
|
-
@max_step_definition_length ||= step_definitions.map{|step_definition| step_definition.text_length}.max
|
|
401
|
-
end
|
|
402
|
-
|
|
403
|
-
def scenario_visited(scenario) #:nodoc:
|
|
404
|
-
scenarios << scenario unless scenarios.index(scenario)
|
|
405
|
-
end
|
|
406
|
-
|
|
407
|
-
def log
|
|
408
|
-
@log ||= Logger.new(STDOUT)
|
|
409
|
-
end
|
|
410
|
-
|
|
411
|
-
def mri_gets(timeout_seconds)
|
|
412
|
-
begin
|
|
413
|
-
Timeout.timeout(timeout_seconds) do
|
|
414
|
-
STDIN.gets
|
|
415
|
-
end
|
|
416
|
-
rescue Timeout::Error => e
|
|
417
|
-
nil
|
|
418
|
-
end
|
|
419
|
-
end
|
|
420
|
-
|
|
421
|
-
def jruby_gets(timeout_seconds)
|
|
422
|
-
answer = nil
|
|
423
|
-
t = java.lang.Thread.new do
|
|
424
|
-
answer = STDIN.gets
|
|
425
|
-
end
|
|
426
|
-
t.start
|
|
427
|
-
t.join(timeout_seconds * 1000)
|
|
428
|
-
answer
|
|
4
|
+
class StepMother < Runtime
|
|
5
|
+
def initialize(*args)
|
|
6
|
+
warn("StepMother has been deprecated and will be gently put to sleep at the next major release. Please use Runtime instead. #{caller[0]}")
|
|
7
|
+
super
|
|
429
8
|
end
|
|
430
9
|
end
|
|
431
|
-
end
|
|
10
|
+
end
|