cucumber 0.3.95 → 0.3.96

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.
Files changed (55) hide show
  1. data/History.txt +21 -0
  2. data/Manifest.txt +9 -3
  3. data/examples/sinatra/features/support/env.rb +1 -3
  4. data/features/cucumber_cli.feature +1 -0
  5. data/features/drb_server_integration.feature +56 -3
  6. data/features/junit_formatter.feature +23 -12
  7. data/features/step_definitions/cucumber_steps.rb +13 -2
  8. data/features/support/env.rb +19 -3
  9. data/lib/cucumber/ast/feature_element.rb +1 -1
  10. data/lib/cucumber/ast/step.rb +1 -1
  11. data/lib/cucumber/ast/step_invocation.rb +3 -2
  12. data/lib/cucumber/cli/configuration.rb +9 -25
  13. data/lib/cucumber/cli/drb_client.rb +7 -3
  14. data/lib/cucumber/cli/language_help_formatter.rb +4 -4
  15. data/lib/cucumber/cli/main.rb +26 -46
  16. data/lib/cucumber/cli/options.rb +3 -0
  17. data/lib/cucumber/constantize.rb +28 -0
  18. data/lib/cucumber/feature_file.rb +3 -3
  19. data/lib/cucumber/formatter/junit.rb +13 -9
  20. data/lib/cucumber/formatter/pretty.rb +2 -2
  21. data/lib/cucumber/language_support/hook_methods.rb +9 -0
  22. data/lib/cucumber/language_support/language_methods.rb +47 -0
  23. data/lib/cucumber/language_support/step_definition_methods.rb +44 -0
  24. data/lib/cucumber/parser/natural_language.rb +72 -0
  25. data/lib/cucumber/rb_support/rb_dsl.rb +73 -0
  26. data/lib/cucumber/rb_support/rb_hook.rb +19 -0
  27. data/lib/cucumber/rb_support/rb_language.rb +129 -0
  28. data/lib/cucumber/rb_support/rb_step_definition.rb +56 -0
  29. data/lib/cucumber/step_match.rb +2 -2
  30. data/lib/cucumber/step_mother.rb +87 -206
  31. data/lib/cucumber/version.rb +1 -1
  32. data/lib/cucumber/webrat/element_locator.rb +7 -7
  33. data/lib/cucumber/world.rb +28 -8
  34. data/rails_generators/cucumber/templates/cucumber_environment.rb +2 -2
  35. data/rails_generators/cucumber/templates/spork_env.rb +0 -2
  36. data/rails_generators/cucumber/templates/webrat_steps.rb +17 -0
  37. data/spec/cucumber/ast/background_spec.rb +8 -5
  38. data/spec/cucumber/ast/feature_factory.rb +4 -5
  39. data/spec/cucumber/ast/feature_spec.rb +7 -1
  40. data/spec/cucumber/ast/scenario_outline_spec.rb +10 -6
  41. data/spec/cucumber/ast/scenario_spec.rb +8 -3
  42. data/spec/cucumber/ast/step_collection_spec.rb +2 -2
  43. data/spec/cucumber/cli/configuration_spec.rb +15 -0
  44. data/spec/cucumber/cli/drb_client_spec.rb +35 -1
  45. data/spec/cucumber/cli/main_spec.rb +5 -4
  46. data/spec/cucumber/cli/options_spec.rb +6 -0
  47. data/spec/cucumber/parser/feature_parser_spec.rb +6 -5
  48. data/spec/cucumber/parser/table_parser_spec.rb +1 -1
  49. data/spec/cucumber/step_definition_spec.rb +26 -25
  50. data/spec/cucumber/step_mother_spec.rb +46 -41
  51. data/spec/cucumber/world/pending_spec.rb +4 -5
  52. metadata +11 -5
  53. data/lib/cucumber/cli/rb_step_def_loader.rb +0 -14
  54. data/lib/cucumber/parser/i18n/language.rb +0 -87
  55. data/lib/cucumber/step_definition.rb +0 -122
@@ -0,0 +1,73 @@
1
+ require 'cucumber/rb_support/rb_hook'
2
+
3
+ module Cucumber
4
+ module RbSupport
5
+ # This module defines the methods you can use to define pure Ruby
6
+ # Step Definitions and Hooks. This module is mixed into the toplevel
7
+ # object.
8
+ module RbDsl
9
+ class << self
10
+ attr_accessor :step_mother, :rb_language
11
+
12
+ def alias_adverb(adverb)
13
+ alias_method adverb, :register_rb_step_definition
14
+ end
15
+ end
16
+
17
+ # Registers any number of +world_modules+ (Ruby Modules) and/or a Proc.
18
+ # The +proc+ will be executed once before each scenario to create an
19
+ # Object that the scenario's steps will run within. Any +world_modules+
20
+ # will be mixed into this Object (via Object#extend).
21
+ #
22
+ # This method is typically called from one or more Ruby scripts under
23
+ # <tt>features/support</tt>. You can call this method as many times as you
24
+ # like (to register more modules), but if you try to register more than
25
+ # one Proc you will get an error.
26
+ #
27
+ # Cucumber will not yield anything to the +proc+. Examples:
28
+ #
29
+ # World do
30
+ # MyClass.new
31
+ # end
32
+ #
33
+ # World(MyModule)
34
+ #
35
+ def World(*world_modules, &proc)
36
+ RbDsl.rb_language.build_world_factory(*world_modules, &proc)
37
+ end
38
+
39
+ # Registers a Before proc. You can call this method as many times as you
40
+ # want (typically from ruby scripts under <tt>support</tt>).
41
+ def Before(*tag_names, &proc)
42
+ RbDsl.step_mother.register_hook(:before, RbHook.new(RbDsl.rb_language, tag_names, proc))
43
+ end
44
+
45
+ def After(*tag_names, &proc)
46
+ RbDsl.step_mother.register_hook(:after, RbHook.new(RbDsl.rb_language, tag_names, proc))
47
+ end
48
+
49
+ def AfterStep(*tag_names, &proc)
50
+ RbDsl.step_mother.register_hook(:after_step, RbHook.new(RbDsl.rb_language, tag_names, proc))
51
+ end
52
+
53
+ # Registers a new Ruby StepDefinition.
54
+ # This method is aliased
55
+ # to <tt>Given</tt>, <tt>When</tt> and <tt>Then</tt>, and
56
+ # also to the i18n translations whenever a feature of a
57
+ # new language is loaded.
58
+ #
59
+ # See Cucumber#alias_steps for details on how to
60
+ # create your own aliases.
61
+ #
62
+ # The +&proc+ gets executed in the context of a <tt>world</tt>
63
+ # object, which is defined by #World. A new <tt>world</tt>
64
+ # object is created for each scenario and is shared across
65
+ # step definitions within that scenario.
66
+ def register_rb_step_definition(regexp, &proc)
67
+ RbDsl.step_mother.register_step_definition(RbStepDefinition.new(RbDsl.rb_language, regexp, &proc))
68
+ end
69
+ end
70
+ end
71
+ end
72
+
73
+ extend(Cucumber::RbSupport::RbDsl)
@@ -0,0 +1,19 @@
1
+ module Cucumber
2
+ module RbSupport
3
+ class RbHook
4
+ include LanguageSupport::HookMethods
5
+
6
+ attr_reader :tag_names
7
+
8
+ def initialize(rb_language, tag_names, proc)
9
+ @rb_language = rb_language
10
+ @tag_names = tag_names
11
+ @proc = proc
12
+ end
13
+
14
+ def invoke(location, scenario)
15
+ @rb_language.current_world.cucumber_instance_exec(false, location, scenario, &@proc)
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,129 @@
1
+ require 'cucumber/rb_support/rb_dsl'
2
+ require 'cucumber/rb_support/rb_step_definition'
3
+
4
+ module Cucumber
5
+ module RbSupport
6
+ class NilWorld < StandardError
7
+ def initialize
8
+ super("World procs should never return nil")
9
+ end
10
+ end
11
+
12
+ class MultipleWorld < StandardError
13
+ def initialize(first_proc, second_proc)
14
+ message = "You can only pass a proc to #World once, but it's happening\n"
15
+ message << "in 2 places:\n\n"
16
+ message << first_proc.backtrace_line('World') << "\n"
17
+ message << second_proc.backtrace_line('World') << "\n\n"
18
+ message << "Use Ruby modules instead to extend your worlds. See the Cucumber::StepMother#World RDoc\n"
19
+ message << "or http://wiki.github.com/aslakhellesoy/cucumber/a-whole-new-world.\n\n"
20
+ super(message)
21
+ end
22
+ end
23
+
24
+ class RbLanguage
25
+ include LanguageSupport::LanguageMethods
26
+ attr_reader :current_world, :step_mother
27
+
28
+ def initialize(step_mother)
29
+ @step_mother = step_mother
30
+ RbDsl.step_mother = step_mother
31
+ RbDsl.rb_language = self
32
+ end
33
+
34
+ def load_step_def_file(step_def_file)
35
+ begin
36
+ require step_def_file
37
+ rescue LoadError => e
38
+ e.message << "\nFailed to load #{step_def_file}"
39
+ raise e
40
+ end
41
+ end
42
+
43
+ def build_world_factory(*world_modules, &proc)
44
+ if(proc)
45
+ raise MultipleWorld.new(@world_proc, proc) if @world_proc
46
+ @world_proc = proc
47
+ end
48
+ @world_modules ||= []
49
+ @world_modules += world_modules
50
+ end
51
+
52
+ def begin_scenario
53
+ create_world
54
+ extend_world
55
+ connect_world(@step_mother)
56
+ end
57
+
58
+ def end_scenario
59
+ @current_world = nil
60
+ end
61
+
62
+ def snippet_text(step_keyword, step_name, multiline_arg_class = nil)
63
+ escaped = Regexp.escape(step_name).gsub('\ ', ' ').gsub('/', '\/')
64
+ escaped = escaped.gsub(PARAM_PATTERN, ESCAPED_PARAM_PATTERN)
65
+
66
+ n = 0
67
+ block_args = escaped.scan(ESCAPED_PARAM_PATTERN).map do |a|
68
+ n += 1
69
+ "arg#{n}"
70
+ end
71
+ block_args << multiline_arg_class.default_arg_name unless multiline_arg_class.nil?
72
+ block_arg_string = block_args.empty? ? "" : " |#{block_args.join(", ")}|"
73
+ multiline_class_comment = ""
74
+ if(multiline_arg_class == Ast::Table)
75
+ multiline_class_comment = "# #{multiline_arg_class.default_arg_name} is a #{multiline_arg_class.to_s}\n "
76
+ end
77
+
78
+ "#{step_keyword} /^#{escaped}$/ do#{block_arg_string}\n #{multiline_class_comment}pending\nend"
79
+ end
80
+
81
+ def alias_adverbs(adverbs)
82
+ adverbs.each do |adverb|
83
+ RbDsl.alias_adverb(adverb)
84
+ World.alias_adverb(adverb)
85
+ end
86
+ end
87
+
88
+ private
89
+
90
+ PARAM_PATTERN = /"([^\"]*)"/
91
+ ESCAPED_PARAM_PATTERN = '"([^\\"]*)"'
92
+
93
+ def create_world
94
+ if(@world_proc)
95
+ @current_world = @world_proc.call
96
+ check_nil(@current_world, @world_proc)
97
+ else
98
+ @current_world = Object.new
99
+ end
100
+ end
101
+
102
+ def extend_world
103
+ @current_world.extend(World)
104
+ @current_world.extend(::Spec::Matchers) if defined?(::Spec::Matchers)
105
+ (@world_modules || []).each do |mod|
106
+ @current_world.extend(mod)
107
+ end
108
+ end
109
+
110
+ def connect_world(step_mother)
111
+ @current_world.__cucumber_step_mother = step_mother
112
+ end
113
+
114
+ def check_nil(o, proc)
115
+ if o.nil?
116
+ begin
117
+ raise NilWorld.new
118
+ rescue NilWorld => e
119
+ e.backtrace.clear
120
+ e.backtrace.push(proc.backtrace_line("World"))
121
+ raise e
122
+ end
123
+ else
124
+ o
125
+ end
126
+ end
127
+ end
128
+ end
129
+ end
@@ -0,0 +1,56 @@
1
+ require 'cucumber/step_match'
2
+ require 'cucumber/core_ext/string'
3
+ require 'cucumber/core_ext/proc'
4
+
5
+ module Cucumber
6
+ # A Step Definition holds a Regexp and a Proc, and is created
7
+ # by calling <tt>Given</tt>, <tt>When</tt> or <tt>Then</tt>
8
+ # in the <tt>step_definitions</tt> ruby files - for example:
9
+ #
10
+ # Given /I have (\d+) cucumbers in my belly/ do
11
+ # # some code here
12
+ # end
13
+ #
14
+ class RbStepDefinition
15
+ include LanguageSupport::StepDefinitionMethods
16
+
17
+ class MissingProc < StandardError
18
+ def message
19
+ "Step definitions must always have a proc"
20
+ end
21
+ end
22
+
23
+ attr_reader :proc
24
+
25
+ def initialize(rb_language, pattern, &proc)
26
+ raise MissingProc if proc.nil?
27
+ if String === pattern
28
+ p = pattern.gsub(/\$\w+/, '(.*)') # Replace $var with (.*)
29
+ pattern = Regexp.new("^#{p}$")
30
+ end
31
+ @rb_language, @regexp, @proc = rb_language, pattern, proc
32
+ end
33
+
34
+ def regexp
35
+ @regexp
36
+ end
37
+
38
+ def invoke(args)
39
+ args = args.map{|arg| Ast::PyString === arg ? arg.to_s : arg}
40
+ begin
41
+ @rb_language.current_world.cucumber_instance_exec(true, regexp.inspect, *args, &@proc)
42
+ rescue Cucumber::ArityMismatchError => e
43
+ e.backtrace.unshift(self.backtrace_line)
44
+ raise e
45
+ end
46
+ end
47
+
48
+ def file_colon_line
49
+ @proc.file_colon_line
50
+ end
51
+
52
+ def file
53
+ @file ||= file_colon_line.split(':')[0]
54
+ end
55
+ end
56
+ end
@@ -10,10 +10,10 @@ module Cucumber
10
10
  @formatted_step_name
11
11
  end
12
12
 
13
- def invoke(world, multiline_arg)
13
+ def invoke(multiline_arg)
14
14
  all_args = @args.dup
15
15
  all_args << multiline_arg if multiline_arg
16
- @step_definition.invoke(world, all_args)
16
+ @step_definition.invoke(all_args)
17
17
  end
18
18
 
19
19
  def format_args(format = lambda{|a| a})
@@ -1,6 +1,10 @@
1
- require 'cucumber/step_definition'
1
+ require 'cucumber/constantize'
2
2
  require 'cucumber/world'
3
3
  require 'cucumber/core_ext/instance_exec'
4
+ require 'cucumber/parser/natural_language'
5
+ require 'cucumber/language_support/hook_methods'
6
+ require 'cucumber/language_support/language_methods'
7
+ require 'cucumber/language_support/step_definition_methods'
4
8
 
5
9
  module Cucumber
6
10
  class Undefined < StandardError
@@ -45,61 +49,56 @@ module Cucumber
45
49
  end
46
50
  end
47
51
 
48
- class NilWorld < StandardError
49
- def initialize
50
- super("World procs should never return nil")
51
- end
52
- end
53
-
54
- class MultipleWorld < StandardError
55
- def initialize(first_proc, second_proc)
56
- message = "You can only pass a proc to #World once, but it's happening\n"
57
- message << "in 2 places:\n\n"
58
- message << first_proc.backtrace_line('World') << "\n"
59
- message << second_proc.backtrace_line('World') << "\n\n"
60
- message << "Use Ruby modules instead to extend your worlds. See the Cucumber::StepMother#World RDoc\n"
61
- message << "or http://wiki.github.com/aslakhellesoy/cucumber/a-whole-new-world.\n\n"
62
- super(message)
63
- end
64
- end
65
-
66
52
  # This is the main interface for registering step definitions, which is done
67
53
  # from <tt>*_steps.rb</tt> files. This module is included right at the top-level
68
54
  # so #register_step_definition (and more interestingly - its aliases) are
69
55
  # available from the top-level.
70
- module StepMother
71
- class Hook
72
- def initialize(tag_names, proc)
73
- @tag_names = tag_names.map{|tag| Ast::Tags.strip_prefix(tag)}
74
- @proc = proc
75
- end
56
+ class StepMother
57
+ include Constantize
58
+
59
+ attr_writer :options, :visitor
76
60
 
77
- def matches_tag_names?(tag_names)
78
- @tag_names.empty? || (@tag_names & tag_names).any?
79
- end
61
+ def initialize
62
+ @programming_languages = []
63
+ @language_map = {}
64
+ load_natural_language('en')
65
+ end
80
66
 
81
- def execute_in(world, scenario, location, exception_fails_scenario = true)
82
- begin
83
- world.cucumber_instance_exec(false, location, scenario, &@proc)
84
- rescue Exception => exception
85
- if exception_fails_scenario
86
- scenario.fail!(exception)
87
- else
88
- raise
89
- end
90
- end
91
- end
67
+ # Loads and registers programming language implementation.
68
+ # Instances are cached, so calling with the same argument
69
+ # twice will return the same instance.
70
+ #
71
+ # Raises an exception if the language can't be loaded.
72
+ #
73
+ def load_programming_language(ext)
74
+ return @language_map[ext] if @language_map[ext]
75
+ programming_language_class = constantize("Cucumber::#{ext.capitalize}Support::#{ext.capitalize}Language")
76
+ programming_language = programming_language_class.new(self)
77
+ programming_language.alias_adverbs(@adverbs || [])
78
+ @programming_languages << programming_language
79
+ @language_map[ext] = programming_language
80
+ programming_language
81
+ end
82
+
83
+ # Loads a natural language. This has the effect of aliasing
84
+ # Step Definition keywords for all of the registered programming
85
+ # languages (if they support aliasing). See #load_programming_language
86
+ #
87
+ def load_natural_language(lang)
88
+ Parser::NaturalLanguage.get(self, lang)
92
89
  end
93
90
 
94
- class << self
95
- def alias_adverb(adverb)
96
- adverb = adverb.gsub(/\s/, '')
97
- alias_method adverb, :register_step_definition
91
+ # Registers a StepDefinition. This can be a Ruby StepDefintion,
92
+ # or any other kind of object that implements the StepDefintion
93
+ # contract (API).
94
+ def register_step_definition(step_definition)
95
+ step_definitions.each do |already|
96
+ raise Redundant.new(already, step_definition) if already.same_regexp?(step_definition.regexp)
98
97
  end
98
+ step_definitions << step_definition
99
+ step_definition
99
100
  end
100
101
 
101
- attr_writer :snippet_generator, :options, :visitor
102
-
103
102
  def options
104
103
  @options ||= {}
105
104
  end
@@ -117,6 +116,10 @@ module Cucumber
117
116
  end
118
117
  end
119
118
 
119
+ def announce(msg)
120
+ @visitor.announce(msg)
121
+ end
122
+
120
123
  def scenarios(status = nil)
121
124
  @scenarios ||= []
122
125
  if(status)
@@ -126,44 +129,8 @@ module Cucumber
126
129
  end
127
130
  end
128
131
 
129
- # Registers a new StepDefinition. This method is aliased
130
- # to <tt>Given</tt>, <tt>When</tt> and <tt>Then</tt>, and
131
- # also to the i18n translations whenever a feature of a
132
- # new language is loaded.
133
- #
134
- # See Cucumber#alias_steps for details on how to
135
- # create your own aliases.
136
- #
137
- # The +&proc+ gets executed in the context of a <tt>world</tt>
138
- # object, which is defined by #World. A new <tt>world</tt>
139
- # object is created for each scenario and is shared across
140
- # step definitions within that scenario.
141
- def register_step_definition(regexp, &proc)
142
- step_definition = StepDefinition.new(regexp, &proc)
143
- step_definitions.each do |already|
144
- raise Redundant.new(already, step_definition) if already.match(regexp)
145
- end
146
- step_definitions << step_definition
147
- step_definition
148
- end
149
-
150
- # Registers a Before proc. You can call this method as many times as you
151
- # want (typically from ruby scripts under <tt>support</tt>).
152
- def Before(*tag_names, &proc)
153
- register_hook(:before, tag_names, proc)
154
- end
155
-
156
- def After(*tag_names, &proc)
157
- register_hook(:after, tag_names, proc)
158
- end
159
-
160
- def AfterStep(*tag_names, &proc)
161
- register_hook(:after_step, tag_names, proc)
162
- end
163
-
164
- def register_hook(phase, tags, proc)
165
- hook = Hook.new(tags, proc)
166
- hooks[phase] << hook
132
+ def register_hook(phase, hook)
133
+ hooks[phase.to_sym] << hook
167
134
  hook
168
135
  end
169
136
 
@@ -172,53 +139,7 @@ module Cucumber
172
139
  end
173
140
 
174
141
  def hooks_for(phase, scenario)
175
- hooks[phase].select{|hook| scenario.accept_hook?(hook)}
176
- end
177
-
178
- # Registers any number of +world_modules+ (Ruby Modules) and/or a Proc.
179
- # The +proc+ will be executed once before each scenario to create an
180
- # Object that the scenario's steps will run within. Any +world_modules+
181
- # will be mixed into this Object (via Object#extend).
182
- #
183
- # This method is typically called from one or more Ruby scripts under
184
- # <tt>features/support</tt>. You can call this method as many times as you
185
- # like (to register more modules), but if you try to register more than
186
- # one Proc you will get an error.
187
- #
188
- # Cucumber will not yield anything to the +proc+ (like it used to do before v0.3).
189
- #
190
- # In earlier versions of Cucumber (before 0.3) you could not register
191
- # any +world_modules+. Instead you would register several Proc objects (by
192
- # calling the method several times). The result of each +proc+ would be yielded
193
- # to the next +proc+. Example:
194
- #
195
- # World do |world| # NOT SUPPORTED FROM 0.3
196
- # MyClass.new
197
- # end
198
- #
199
- # World do |world| # NOT SUPPORTED FROM 0.3
200
- # world.extend(MyModule)
201
- # end
202
- #
203
- # From Cucumber 0.3 the recommended way to do this is:
204
- #
205
- # World do
206
- # MyClass.new
207
- # end
208
- #
209
- # World(MyModule)
210
- #
211
- def World(*world_modules, &proc)
212
- if(proc)
213
- raise MultipleWorld.new(@world_proc, proc) if @world_proc
214
- @world_proc = proc
215
- end
216
- @world_modules ||= []
217
- @world_modules += world_modules
218
- end
219
-
220
- def current_world
221
- @current_world
142
+ hooks[phase.to_sym].select{|hook| scenario.accept_hook?(hook)}
222
143
  end
223
144
 
224
145
  def step_match(step_name, formatted_step_name=nil)
@@ -257,108 +178,68 @@ module Cucumber
257
178
  end
258
179
 
259
180
  def snippet_text(step_keyword, step_name, multiline_arg_class)
260
- @snippet_generator.snippet_text(step_keyword, step_name, multiline_arg_class)
181
+ @programming_languages.map do |programming_language|
182
+ programming_language.snippet_text(step_keyword, step_name, multiline_arg_class)
183
+ end.join("\n")
261
184
  end
262
185
 
263
186
  def before_and_after(scenario, skip_hooks=false)
264
187
  before(scenario) unless skip_hooks
265
- @current_scenario = scenario
266
188
  yield scenario
267
- @current_scenario = nil
268
189
  after(scenario) unless skip_hooks
269
190
  scenario_visited(scenario)
270
191
  end
271
-
272
- def before(scenario)
273
- unless current_world
274
- new_world!
275
- execute_before(scenario)
276
- end
277
- end
278
-
279
- def after(scenario)
280
- execute_after(scenario)
281
- nil_world!
282
- end
283
-
284
- def after_step
285
- execute_after_step(@current_scenario)
286
- end
287
-
288
- private
289
192
 
290
- def max_step_definition_length
291
- @max_step_definition_length ||= step_definitions.map{|step_definition| step_definition.text_length}.max
193
+ def register_adverbs(adverbs)
194
+ @adverbs ||= []
195
+ @adverbs += adverbs
196
+ @adverbs.uniq!
197
+ @programming_languages.each do |programming_language|
198
+ programming_language.alias_adverbs(@adverbs)
199
+ end
292
200
  end
293
201
 
294
- # Creates a new world instance
295
- def new_world!
202
+ def begin_scenario
296
203
  return if options[:dry_run]
297
- create_world!
298
- extend_world
299
- connect_world
300
- @current_world
301
- end
302
-
303
- def create_world!
304
- if(@world_proc)
305
- @current_world = @world_proc.call
306
- check_nil(@current_world, @world_proc)
307
- else
308
- @current_world = Object.new
204
+ @programming_languages.each do |programming_language|
205
+ programming_language.begin_scenario
309
206
  end
310
207
  end
311
208
 
312
- def extend_world
313
- @current_world.extend(World)
314
- @current_world.extend(::Spec::Matchers) if defined?(::Spec::Matchers)
315
- (@world_modules || []).each do |mod|
316
- @current_world.extend(mod)
209
+ def end_scenario
210
+ return if options[:dry_run]
211
+ @programming_languages.each do |programming_language|
212
+ programming_language.end_scenario
317
213
  end
318
214
  end
319
-
320
- def connect_world
321
- @current_world.__cucumber_step_mother = self
322
- @current_world.__cucumber_visitor = @visitor
323
- end
324
-
325
- def check_nil(o, proc)
326
- if o.nil?
327
- begin
328
- raise NilWorld.new
329
- rescue NilWorld => e
330
- e.backtrace.clear
331
- e.backtrace.push(proc.backtrace_line("World"))
332
- raise e
333
- end
334
- else
335
- o
215
+
216
+ def before(scenario)
217
+ return if options[:dry_run] || @current_scenario
218
+ @current_scenario = scenario
219
+ @programming_languages.each do |programming_language|
220
+ programming_language.before(scenario)
336
221
  end
337
222
  end
338
-
339
- def nil_world!
340
- @current_world = nil
341
- end
342
-
343
- def execute_before(scenario)
223
+
224
+ def after(scenario)
225
+ @current_scenario = nil
344
226
  return if options[:dry_run]
345
- hooks_for(:before, scenario).each do |hook|
346
- hook.execute_in(@current_world, scenario, 'Before')
227
+ @programming_languages.each do |programming_language|
228
+ programming_language.after(scenario)
347
229
  end
348
230
  end
349
-
350
- def execute_after(scenario)
231
+
232
+ def after_step
351
233
  return if options[:dry_run]
352
- hooks_for(:after, scenario).each do |hook|
353
- hook.execute_in(@current_world, scenario, 'After')
234
+ @programming_languages.each do |programming_language|
235
+ programming_language.execute_after_step(@current_scenario)
354
236
  end
355
237
  end
238
+
239
+ private
356
240
 
357
- def execute_after_step(scenario)
358
- return if options[:dry_run]
359
- hooks_for(:after_step, scenario).each do |hook|
360
- hook.execute_in(@current_world, scenario, 'AfterStep', false)
361
- end
241
+ def max_step_definition_length
242
+ @max_step_definition_length ||= step_definitions.map{|step_definition| step_definition.text_length}.max
362
243
  end
363
244
 
364
245
  def scenario_visited(scenario)