aslakhellesoy-cucumber 0.3.95 → 0.3.96

Sign up to get free protection for your applications and to get access to all the features.
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
@@ -218,6 +218,9 @@ module Cucumber
218
218
  opts.on(DRB_FLAG, "Run features against a DRb server. (i.e. with the spork gem)") do
219
219
  @options[:drb] = true
220
220
  end
221
+ opts.on("--port PORT", "Specify DRb port. Ignored without --drb") do |port|
222
+ @options[:drb_port] = port
223
+ end
221
224
  opts.on_tail("--version", "Show version.") do
222
225
  @out_stream.puts VERSION::STRING
223
226
  Kernel.exit
@@ -0,0 +1,28 @@
1
+ module Cucumber
2
+ module Constantize
3
+ def constantize(camel_cased_word)
4
+ begin
5
+ names = camel_cased_word.split('::')
6
+ names.shift if names.empty? || names.first.empty?
7
+
8
+ constant = Object
9
+ names.each do |name|
10
+ constant = constant.const_defined?(name) ? constant.const_get(name) : constant.const_missing(name)
11
+ end
12
+ constant
13
+ rescue NameError
14
+ require underscore(camel_cased_word)
15
+ retry
16
+ end
17
+ end
18
+
19
+ # Snagged from active_support
20
+ def underscore(camel_cased_word)
21
+ camel_cased_word.to_s.gsub(/::/, '/').
22
+ gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2').
23
+ gsub(/([a-z\d])([A-Z])/,'\1_\2').
24
+ tr("-", "_").
25
+ downcase
26
+ end
27
+ end
28
+ end
@@ -1,4 +1,4 @@
1
- require 'cucumber/parser/i18n/language'
1
+ require 'cucumber/parser/natural_language'
2
2
  require 'cucumber/filter'
3
3
 
4
4
  module Cucumber
@@ -20,9 +20,9 @@ module Cucumber
20
20
  # Parses a file and returns a Cucumber::Ast
21
21
  # If +options+ contains tags, the result will
22
22
  # be filtered.
23
- def parse(options={})
23
+ def parse(step_mother, options)
24
24
  filter = Filter.new(@lines, options)
25
- language = Parser::I18n::Language[lang || options[:lang] || 'en']
25
+ language = Parser::NaturalLanguage.get(step_mother, (lang || options[:lang] || 'en'))
26
26
  language.parse(source, @path, filter)
27
27
  end
28
28
 
@@ -45,8 +45,8 @@ module Cucumber
45
45
  end
46
46
 
47
47
  def visit_scenario_name(keyword, name, file_colon_line, source_indent)
48
- scenario_name = name.strip
49
- scenario_name = "Unnamed scenario" if name == ""
48
+ scenario_name = name.strip.delete(".\r\n")
49
+ scenario_name = "Unnamed scenario" if name.blank?
50
50
  @scenario = scenario_name
51
51
  @outline = keyword.include?('Scenario Outline')
52
52
  @output = "Scenario#{ " outline" if @outline}: #{@scenario}\n\n"
@@ -96,16 +96,20 @@ module Cucumber
96
96
  @time += duration
97
97
  classname = "#{@feature_name}.#{@scenario}"
98
98
  name = "#{@scenario}#{suffix}"
99
- @builder.testcase(:classname => classname, :name => name, :time => "%.6f" % duration) do
100
- if status != :passed
101
- @builder.failure(:message => "#{status.to_s} #{name}", :type => status.to_s) do
102
- @builder.text! @output
103
- @builder.text!(format_exception(exception)) if exception
99
+ failed = (status == :failed || (status == :pending && @options[:strict]))
100
+ #puts "FAILED:!!#{failed}"
101
+ if status == :passed || failed
102
+ @builder.testcase(:classname => classname, :name => name, :time => "%.6f" % duration) do
103
+ if failed
104
+ @builder.failure(:message => "#{status.to_s} #{name}", :type => status.to_s) do
105
+ @builder.text! @output
106
+ @builder.text!(format_exception(exception)) if exception
107
+ end
108
+ @failures += 1
104
109
  end
105
- @failures += 1
106
110
  end
111
+ @tests += 1
107
112
  end
108
- @tests += 1
109
113
  end
110
114
 
111
115
  def format_exception(exception)
@@ -97,9 +97,9 @@ module Cucumber
97
97
  end
98
98
 
99
99
  def visit_examples_name(keyword, name)
100
- names = name.empty? ? [name] : name.split("\n")
100
+ names = name.strip.empty? ? [name.strip] : name.split("\n")
101
101
  @io.puts("\n #{keyword} #{names[0]}")
102
- names[1..-1].each {|s| @io.puts " #{s}" }
102
+ names[1..-1].each {|s| @io.puts " #{s}" } unless names.empty?
103
103
  @io.flush
104
104
  @indent = 6
105
105
  @scenario_indent = 6
@@ -0,0 +1,9 @@
1
+ module Cucumber
2
+ module LanguageSupport
3
+ module HookMethods
4
+ def matches_tag_names?(other_tag_names)
5
+ tag_names.empty? || (tag_names.map{|tag| Ast::Tags.strip_prefix(tag)} & other_tag_names).any?
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,47 @@
1
+ module Cucumber
2
+ module LanguageSupport
3
+ module LanguageMethods
4
+ def before(scenario)
5
+ step_mother.begin_scenario
6
+ execute_before(scenario)
7
+ end
8
+
9
+ def after(scenario)
10
+ execute_after(scenario)
11
+ step_mother.end_scenario
12
+ end
13
+
14
+ def execute_before(scenario)
15
+ step_mother.hooks_for(:before, scenario).each do |hook|
16
+ invoke(hook, 'Before', scenario, true)
17
+ end
18
+ end
19
+
20
+ def execute_after(scenario)
21
+ step_mother.hooks_for(:after, scenario).each do |hook|
22
+ invoke(hook, 'After', scenario, true)
23
+ end
24
+ end
25
+
26
+ def execute_after_step(scenario)
27
+ step_mother.hooks_for(:after_step, scenario).each do |hook|
28
+ invoke(hook, 'AfterStep', scenario, false)
29
+ end
30
+ end
31
+
32
+ private
33
+
34
+ def invoke(hook, location, scenario, exception_fails_scenario)
35
+ begin
36
+ hook.invoke(location, scenario)
37
+ rescue Exception => exception
38
+ if exception_fails_scenario
39
+ scenario.fail!(exception)
40
+ else
41
+ raise
42
+ end
43
+ end
44
+ end
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,44 @@
1
+ module Cucumber
2
+ module LanguageSupport
3
+ module StepDefinitionMethods
4
+ def step_match(name_to_match, name_to_report)
5
+ if(match = regexp.match(name_to_match))
6
+ StepMatch.new(self, name_to_match, name_to_report, match.captures)
7
+ else
8
+ nil
9
+ end
10
+ end
11
+
12
+ # Formats the matched arguments of the associated Step. This method
13
+ # is usually called from visitors, which render output.
14
+ #
15
+ # The +format+ can either be a String or a Proc.
16
+ #
17
+ # If it is a String it should be a format string according to
18
+ # <tt>Kernel#sprinf</tt>, for example:
19
+ #
20
+ # '<span class="param">%s</span></tt>'
21
+ #
22
+ # If it is a Proc, it should take one argument and return the formatted
23
+ # argument, for example:
24
+ #
25
+ # lambda { |param| "[#{param}]" }
26
+ #
27
+ def format_args(step_name, format)
28
+ step_name.gzub(regexp, format)
29
+ end
30
+
31
+ def same_regexp?(regexp)
32
+ self.regexp == regexp
33
+ end
34
+
35
+ def backtrace_line
36
+ "#{file_colon_line}:in `#{regexp.inspect}'"
37
+ end
38
+
39
+ def text_length
40
+ regexp.inspect.jlength
41
+ end
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,72 @@
1
+ module Cucumber
2
+ module Parser
3
+ class NaturalLanguage
4
+ KEYWORD_KEYS = %w{name native encoding feature background scenario scenario_outline examples given when then but}
5
+
6
+ class << self
7
+ def get(step_mother, lang)
8
+ languages[lang] ||= new(step_mother, lang)
9
+ end
10
+
11
+ def languages
12
+ @languages ||= {}
13
+ end
14
+ end
15
+
16
+ def initialize(step_mother, lang)
17
+ @keywords = Cucumber::LANGUAGES[lang]
18
+ raise "Language not supported: #{lang.inspect}" if @keywords.nil?
19
+ @keywords['grammar_name'] = @keywords['name'].gsub(/\s/, '')
20
+ register_adverbs(step_mother) if step_mother
21
+ end
22
+
23
+ def register_adverbs(step_mother)
24
+ adverbs = %w{given when then and but}.map{|keyword| @keywords[keyword].split('|').map{|w| w.gsub(/\s/, '')}}.flatten
25
+ step_mother.register_adverbs(adverbs)
26
+ end
27
+
28
+ def parser
29
+ return @parser if @parser
30
+ i18n_tt = File.expand_path(File.dirname(__FILE__) + '/i18n.tt')
31
+ template = File.open(i18n_tt, Cucumber.file_mode('r')).read
32
+ erb = ERB.new(template)
33
+ grammar = erb.result(binding)
34
+ Treetop.load_from_string(grammar)
35
+ @parser = Parser::I18n.const_get("#{@keywords['grammar_name']}Parser").new
36
+ def @parser.inspect
37
+ "#<#{self.class.name}>"
38
+ end
39
+ @parser
40
+ end
41
+
42
+ def parse(source, path, filter)
43
+ feature = parser.parse_or_fail(source, path, filter)
44
+ feature.language = self if feature
45
+ feature
46
+ end
47
+
48
+ def keywords(key, raw=false)
49
+ return @keywords[key] if raw
50
+ return nil unless @keywords[key]
51
+ values = @keywords[key].split('|')
52
+ values.map{|value| "'#{value}'"}.join(" / ")
53
+ end
54
+
55
+ def incomplete?
56
+ KEYWORD_KEYS.detect{|key| @keywords[key].nil?}
57
+ end
58
+
59
+ def scenario_keyword
60
+ @keywords['scenario'].split('|')[0] + ':'
61
+ end
62
+
63
+ def but_keywords
64
+ @keywords['but'].split('|')
65
+ end
66
+
67
+ def and_keywords
68
+ @keywords['and'].split('|')
69
+ end
70
+ end
71
+ end
72
+ end
@@ -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})