cucumber 0.8.6 → 0.8.7

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 (180) hide show
  1. data/.rspec +1 -1
  2. data/Caliper.yml +4 -0
  3. data/History.txt +1557 -0
  4. data/LICENSE +1 -1
  5. data/README.rdoc +26 -0
  6. data/Rakefile +51 -5
  7. data/VERSION.yml +5 -0
  8. data/bin/cucumber +1 -7
  9. data/cucumber.gemspec +77 -3
  10. data/examples/i18n/ar/features/step_definitons/calculator_steps.rb +1 -1
  11. data/examples/i18n/he/features/step_definitons/calculator_steps.rb +1 -1
  12. data/examples/i18n/ro/features/step_definitons/calculator_steps.rb +7 -4
  13. data/examples/i18n/ro/features/suma.feature +11 -0
  14. data/examples/i18n/ru/features/division.feature +2 -2
  15. data/examples/i18n/tr/features/step_definitons/hesap_makinesi_adimlari.rb +3 -3
  16. data/examples/sinatra/features/support/env.rb +5 -2
  17. data/examples/v8/features/fibonacci.feature +1 -1
  18. data/examples/watir/features/step_definitions/search_steps.rb +1 -1
  19. data/features/announce.feature +164 -0
  20. data/features/around_hooks.feature +232 -0
  21. data/features/background.feature +95 -284
  22. data/features/bug_371.feature +32 -0
  23. data/features/bug_464.feature +16 -0
  24. data/features/bug_475.feature +42 -0
  25. data/features/bug_585_tab_indentation.feature +22 -0
  26. data/features/bug_600.feature +67 -0
  27. data/features/call_steps_from_stepdefs.feature +154 -0
  28. data/features/cucumber_cli.feature +591 -0
  29. data/features/cucumber_cli_outlines.feature +117 -0
  30. data/features/custom_formatter.feature +73 -3
  31. data/features/default_snippets.feature +42 -0
  32. data/features/diffing.feature +25 -0
  33. data/features/drb_server_integration.feature +174 -0
  34. data/features/exception_in_after_block.feature +127 -0
  35. data/features/exception_in_after_step_block.feature +104 -0
  36. data/features/exception_in_before_block.feature +98 -0
  37. data/features/exclude_files.feature +20 -0
  38. data/features/expand.feature +60 -0
  39. data/features/html_formatter.feature +8 -0
  40. data/features/html_formatter/a.html +582 -0
  41. data/features/json_formatter.feature +245 -160
  42. data/features/junit_formatter.feature +88 -0
  43. data/features/language_from_header.feature +30 -0
  44. data/features/language_help.feature +78 -0
  45. data/features/listener_debugger_formatter.feature +42 -0
  46. data/features/multiline_names.feature +44 -0
  47. data/features/negative_tagged_hooks.feature +60 -0
  48. data/features/post_configuration_hook.feature +37 -0
  49. data/features/profiles.feature +126 -0
  50. data/features/rake_task.feature +152 -0
  51. data/features/report_called_undefined_steps.feature +34 -0
  52. data/features/rerun_formatter.feature +45 -0
  53. data/features/simplest.feature +11 -0
  54. data/features/snippet.feature +23 -0
  55. data/features/snippets_when_using_star_keyword.feature +36 -0
  56. data/features/step_definitions/cucumber_steps.rb +153 -7
  57. data/features/step_definitions/extra_steps.rb +2 -0
  58. data/features/step_definitions/simplest_steps.rb +3 -0
  59. data/features/step_definitions/wire_steps.rb +32 -0
  60. data/features/support/env.rb +140 -18
  61. data/features/support/env.rb.simplest +7 -0
  62. data/features/support/fake_wire_server.rb +77 -0
  63. data/features/table_diffing.feature +45 -0
  64. data/features/table_mapping.feature +34 -0
  65. data/features/tag_logic.feature +258 -0
  66. data/features/transform.feature +245 -0
  67. data/features/unicode_table.feature +35 -0
  68. data/features/usage_and_stepdefs_formatter.feature +169 -0
  69. data/features/wire_protocol.feature +332 -0
  70. data/features/wire_protocol_table_diffing.feature +119 -0
  71. data/features/wire_protocol_tags.feature +87 -0
  72. data/features/wire_protocol_timeouts.feature +63 -0
  73. data/features/work_in_progress.feature +156 -0
  74. data/fixtures/json/features/pystring.feature +8 -0
  75. data/fixtures/junit/features/pending.feature +1 -3
  76. data/fixtures/self_test/features/background/background_tagged_before_on_outline.feature +12 -0
  77. data/fixtures/self_test/features/background/background_with_name.feature +7 -0
  78. data/fixtures/self_test/features/background/failing_background.feature +12 -0
  79. data/fixtures/self_test/features/background/failing_background_after_success.feature +11 -0
  80. data/fixtures/self_test/features/background/multiline_args_background.feature +32 -0
  81. data/fixtures/self_test/features/background/passing_background.feature +10 -0
  82. data/fixtures/self_test/features/background/pending_background.feature +10 -0
  83. data/fixtures/self_test/features/background/scenario_outline_failing_background.feature +16 -0
  84. data/fixtures/self_test/features/background/scenario_outline_passing_background.feature +16 -0
  85. data/fixtures/self_test/features/support/env.rb +0 -8
  86. data/fixtures/tickets/features.html +1 -1
  87. data/gem_tasks/examples.rake +1 -1
  88. data/gem_tasks/features.rake +14 -0
  89. data/gem_tasks/sdoc.rake +12 -0
  90. data/lib/cucumber.rb +0 -12
  91. data/lib/cucumber/ast.rb +1 -1
  92. data/lib/cucumber/ast/background.rb +5 -21
  93. data/lib/cucumber/ast/examples.rb +4 -12
  94. data/lib/cucumber/ast/feature.rb +5 -13
  95. data/lib/cucumber/ast/feature_element.rb +4 -9
  96. data/lib/cucumber/ast/outline_table.rb +4 -4
  97. data/lib/cucumber/ast/py_string.rb +80 -0
  98. data/lib/cucumber/ast/scenario.rb +5 -7
  99. data/lib/cucumber/ast/scenario_outline.rb +15 -23
  100. data/lib/cucumber/ast/step.rb +0 -5
  101. data/lib/cucumber/ast/step_invocation.rb +15 -21
  102. data/lib/cucumber/ast/table.rb +8 -14
  103. data/lib/cucumber/ast/tree_walker.rb +48 -10
  104. data/lib/cucumber/cli/configuration.rb +8 -33
  105. data/lib/cucumber/cli/main.rb +35 -20
  106. data/lib/cucumber/cli/options.rb +7 -8
  107. data/lib/cucumber/cli/profile_loader.rb +0 -2
  108. data/lib/cucumber/core_ext/proc.rb +1 -2
  109. data/lib/cucumber/feature_file.rb +15 -47
  110. data/lib/cucumber/formatter/ansicolor.rb +5 -3
  111. data/lib/cucumber/formatter/color_io.rb +23 -0
  112. data/lib/cucumber/formatter/console.rb +23 -27
  113. data/lib/cucumber/formatter/cucumber.css +17 -34
  114. data/lib/cucumber/formatter/cucumber.sass +182 -173
  115. data/lib/cucumber/formatter/html.rb +11 -46
  116. data/lib/cucumber/formatter/io.rb +4 -2
  117. data/lib/cucumber/formatter/json.rb +152 -15
  118. data/lib/cucumber/formatter/json_pretty.rb +6 -5
  119. data/lib/cucumber/formatter/junit.rb +22 -28
  120. data/lib/cucumber/formatter/pdf.rb +6 -6
  121. data/lib/cucumber/formatter/pretty.rb +5 -5
  122. data/lib/cucumber/formatter/rerun.rb +11 -22
  123. data/lib/cucumber/formatter/tag_cloud.rb +35 -0
  124. data/lib/cucumber/formatter/unicode.rb +20 -41
  125. data/lib/cucumber/js_support/js_dsl.js +4 -4
  126. data/lib/cucumber/js_support/js_language.rb +5 -9
  127. data/lib/cucumber/js_support/js_snippets.rb +2 -2
  128. data/lib/cucumber/language_support.rb +2 -2
  129. data/lib/cucumber/parser/gherkin_builder.rb +30 -35
  130. data/lib/cucumber/platform.rb +8 -8
  131. data/lib/cucumber/py_support/py_language.rb +2 -2
  132. data/lib/cucumber/rake/task.rb +31 -74
  133. data/lib/cucumber/rb_support/rb_dsl.rb +0 -1
  134. data/lib/cucumber/rb_support/rb_language.rb +8 -10
  135. data/lib/cucumber/rb_support/rb_step_definition.rb +0 -8
  136. data/lib/cucumber/rb_support/rb_transform.rb +0 -17
  137. data/lib/cucumber/rb_support/rb_world.rb +18 -26
  138. data/lib/cucumber/rspec/doubles.rb +3 -3
  139. data/lib/cucumber/step_match.rb +2 -6
  140. data/lib/cucumber/step_mother.rb +427 -6
  141. data/lib/cucumber/wire_support/configuration.rb +1 -4
  142. data/lib/cucumber/wire_support/wire_language.rb +10 -3
  143. data/spec/cucumber/ast/background_spec.rb +6 -68
  144. data/spec/cucumber/ast/feature_factory.rb +4 -5
  145. data/spec/cucumber/ast/feature_spec.rb +4 -4
  146. data/spec/cucumber/ast/outline_table_spec.rb +1 -1
  147. data/spec/cucumber/ast/py_string_spec.rb +40 -0
  148. data/spec/cucumber/ast/scenario_outline_spec.rb +11 -15
  149. data/spec/cucumber/ast/scenario_spec.rb +4 -4
  150. data/spec/cucumber/ast/step_spec.rb +3 -3
  151. data/spec/cucumber/ast/table_spec.rb +2 -38
  152. data/spec/cucumber/ast/tree_walker_spec.rb +2 -2
  153. data/spec/cucumber/broadcaster_spec.rb +1 -1
  154. data/spec/cucumber/cli/configuration_spec.rb +6 -32
  155. data/spec/cucumber/cli/drb_client_spec.rb +3 -2
  156. data/spec/cucumber/cli/main_spec.rb +43 -43
  157. data/spec/cucumber/cli/options_spec.rb +1 -28
  158. data/spec/cucumber/cli/profile_loader_spec.rb +1 -1
  159. data/spec/cucumber/core_ext/proc_spec.rb +1 -1
  160. data/spec/cucumber/formatter/ansicolor_spec.rb +1 -1
  161. data/spec/cucumber/formatter/color_io_spec.rb +29 -0
  162. data/spec/cucumber/formatter/duration_spec.rb +1 -1
  163. data/spec/cucumber/formatter/html_spec.rb +5 -3
  164. data/spec/cucumber/formatter/junit_spec.rb +2 -16
  165. data/spec/cucumber/formatter/progress_spec.rb +1 -1
  166. data/spec/cucumber/formatter/spec_helper.rb +12 -11
  167. data/spec/cucumber/rb_support/rb_language_spec.rb +28 -241
  168. data/spec/cucumber/rb_support/rb_step_definition_spec.rb +28 -33
  169. data/spec/cucumber/rb_support/regexp_argument_matcher_spec.rb +1 -1
  170. data/spec/cucumber/step_match_spec.rb +9 -11
  171. data/spec/cucumber/step_mother_spec.rb +302 -0
  172. data/spec/cucumber/wire_support/configuration_spec.rb +1 -1
  173. data/spec/cucumber/wire_support/connection_spec.rb +1 -1
  174. data/spec/cucumber/wire_support/wire_exception_spec.rb +1 -1
  175. data/spec/cucumber/wire_support/wire_language_spec.rb +1 -1
  176. data/spec/cucumber/wire_support/wire_packet_spec.rb +1 -1
  177. data/spec/cucumber/wire_support/wire_step_definition_spec.rb +1 -1
  178. data/spec/cucumber/world/pending_spec.rb +2 -2
  179. data/spec/spec_helper.rb +20 -13
  180. metadata +78 -4
@@ -1,12 +1,10 @@
1
- require 'cucumber/ast/feature_element'
2
- require 'cucumber/ast/names'
3
-
4
1
  module Cucumber
5
2
  module Ast
6
3
  class ScenarioOutline #:nodoc:
7
4
  include FeatureElement
8
- include Names
9
5
 
6
+ attr_reader :name
7
+
10
8
  module ExamplesArray #:nodoc:
11
9
  def accept(visitor)
12
10
  return if Cucumber.wants_to_quit
@@ -22,12 +20,12 @@ module Cucumber
22
20
  # * Examples keyword
23
21
  # * Examples section name
24
22
  # * Raw matrix
25
- def initialize(background, comment, tags, line, keyword, title, description, raw_steps, example_sections)
26
- @background, @comment, @tags, @line, @keyword, @title, @description, @raw_steps, @example_sections = background, comment, tags, line, keyword, title, description, raw_steps, example_sections
23
+ def initialize(background, comment, tags, line, keyword, name, raw_steps, example_sections)
24
+ @background, @comment, @tags, @line, @keyword, @name, @raw_steps, @example_sections = background, comment, tags, line, keyword, name, raw_steps, example_sections
27
25
  end
28
26
 
29
- def add_examples(example_section, gherkin_examples)
30
- @example_sections << [example_section, gherkin_examples]
27
+ def add_examples(example_section)
28
+ @example_sections << example_section
31
29
  end
32
30
 
33
31
  def init
@@ -35,21 +33,15 @@ module Cucumber
35
33
  attach_steps(@raw_steps)
36
34
  @steps = StepCollection.new(@raw_steps)
37
35
 
38
- @examples_array = @example_sections.map do |example_section_and_gherkin_examples|
39
- example_section = example_section_and_gherkin_examples[0]
40
- gherkin_examples = example_section_and_gherkin_examples[1]
41
-
42
- examples_comment = example_section[0]
43
- examples_line = example_section[1]
44
- examples_keyword = example_section[2]
45
- examples_title = example_section[3]
46
- examples_description = example_section[4]
47
- examples_matrix = example_section[5]
36
+ @examples_array = @example_sections.map do |example_section|
37
+ examples_comment = example_section[0]
38
+ examples_line = example_section[1]
39
+ examples_keyword = example_section[2]
40
+ examples_name = example_section[3]
41
+ examples_matrix = example_section[4]
48
42
 
49
43
  examples_table = OutlineTable.new(examples_matrix, self)
50
- ex = Examples.new(examples_comment, examples_line, examples_keyword, examples_title, examples_description, examples_table)
51
- ex.gherkin_statement(gherkin_examples)
52
- ex
44
+ Examples.new(examples_comment, examples_line, examples_keyword, examples_name, examples_table)
53
45
  end
54
46
 
55
47
  @examples_array.extend(ExamplesArray)
@@ -61,7 +53,7 @@ module Cucumber
61
53
  return if Cucumber.wants_to_quit
62
54
  visitor.visit_comment(@comment) unless @comment.empty?
63
55
  visitor.visit_tags(@tags)
64
- visitor.visit_scenario_name(@keyword, name, file_colon_line(@line), source_indent(first_line_length))
56
+ visitor.visit_scenario_name(@keyword, @name, file_colon_line(@line), source_indent(first_line_length))
65
57
  visitor.visit_steps(@steps)
66
58
 
67
59
  skip_invoke! if @background && @background.failed?
@@ -110,7 +102,7 @@ module Cucumber
110
102
 
111
103
  def to_sexp
112
104
  init
113
- sexp = [:scenario_outline, @keyword, name]
105
+ sexp = [:scenario_outline, @keyword, @name]
114
106
  comment = @comment.to_sexp
115
107
  sexp += [comment] if comment
116
108
  tags = @tags.to_sexp
@@ -14,11 +14,6 @@ module Cucumber
14
14
  @line, @keyword, @name, @multiline_arg = line, keyword, name, multiline_arg
15
15
  end
16
16
 
17
- attr_reader :gherkin_statement
18
- def gherkin_statement(statement=nil)
19
- @gherkin_statement ||= statement
20
- end
21
-
22
17
  def background?
23
18
  false
24
19
  end
@@ -1,4 +1,3 @@
1
- require 'cucumber/errors'
2
1
  require 'cucumber/step_match'
3
2
  require 'cucumber/ast/table'
4
3
  require 'gherkin/rubify'
@@ -39,7 +38,7 @@ module Cucumber
39
38
 
40
39
  def accept(visitor)
41
40
  return if Cucumber.wants_to_quit
42
- invoke(visitor.step_mother, visitor.configuration)
41
+ invoke(visitor.step_mother, visitor.options)
43
42
  visit_step_result(visitor)
44
43
  end
45
44
 
@@ -55,64 +54,63 @@ module Cucumber
55
54
  )
56
55
  end
57
56
 
58
- def invoke(step_mother, configuration)
59
- find_step_match!(step_mother, configuration)
60
- unless @skip_invoke || configuration.dry_run? || @exception || @step_collection.exception
57
+ def invoke(step_mother, options)
58
+ find_step_match!(step_mother)
59
+ unless @skip_invoke || options[:dry_run] || @exception || @step_collection.exception
61
60
  @skip_invoke = true
62
61
  begin
63
62
  @step_match.invoke(@multiline_arg)
64
63
  step_mother.after_step
65
64
  status!(:passed)
66
65
  rescue Pending => e
67
- failed(configuration, e, false)
66
+ failed(options, e, false)
68
67
  status!(:pending)
69
68
  rescue Undefined => e
70
- failed(configuration, e, false)
69
+ failed(options, e, false)
71
70
  status!(:undefined)
72
71
  rescue Cucumber::Ast::Table::Different => e
73
72
  @different_table = e.table
74
- failed(configuration, e, false)
73
+ failed(options, e, false)
75
74
  status!(:failed)
76
75
  rescue Exception => e
77
- failed(configuration, e, false)
76
+ failed(options, e, false)
78
77
  status!(:failed)
79
78
  end
80
79
  end
81
80
  end
82
81
 
83
- def find_step_match!(step_mother, configuration)
82
+ def find_step_match!(step_mother)
84
83
  return if @step_match
85
84
  begin
86
85
  @step_match = step_mother.step_match(@name)
87
86
  rescue Undefined => e
88
- failed(configuration, e, true)
87
+ failed(step_mother.options, e, true)
89
88
  status!(:undefined)
90
89
  @step_match = NoStepMatch.new(@step, @name)
91
90
  rescue Ambiguous => e
92
- failed(configuration, e, false)
91
+ failed(step_mother.options, e, false)
93
92
  status!(:failed)
94
93
  @step_match = NoStepMatch.new(@step, @name)
95
94
  end
96
95
  step_mother.step_visited(self)
97
96
  end
98
97
 
99
- def failed(configuration, e, clear_backtrace)
98
+ def failed(options, e, clear_backtrace)
100
99
  e = filter_backtrace(e)
101
100
  e.set_backtrace([]) if clear_backtrace
102
101
  e.backtrace << @step.backtrace_line unless @step.backtrace_line.nil?
103
102
  @exception = e
104
- if(configuration.strict? || !(Undefined === e) || e.nested?)
103
+ if(options[:strict] || !(Undefined === e) || e.nested?)
105
104
  @reported_exception = e
106
105
  else
107
106
  @reported_exception = nil
108
107
  end
109
108
  end
110
109
 
111
- PWD_PATTERN = /#{Regexp.escape(Dir.pwd)}\//m
112
-
113
110
  def filter_backtrace(e)
114
111
  return e if Cucumber.use_full_backtrace
115
- (e.backtrace || []).each{|line| line.gsub!(PWD_PATTERN, "./")}
112
+ pwd = /#{Regexp.escape(Dir.pwd)}\//m
113
+ (e.backtrace || []).each{|line| line.gsub!(pwd, "./")}
116
114
 
117
115
  filtered = (e.backtrace || []).reject do |line|
118
116
  BACKTRACE_FILTER_PATTERNS.detect { |p| line =~ p }
@@ -187,10 +185,6 @@ module Cucumber
187
185
  @step.language
188
186
  end
189
187
 
190
- def gherkin_statement
191
- @step.gherkin_statement
192
- end
193
-
194
188
  def to_sexp
195
189
  [:step_invocation, @step.line, @step.keyword, @name, (@multiline_arg.nil? ? nil : @multiline_arg.to_sexp)].compact
196
190
  end
@@ -1,5 +1,4 @@
1
1
  require 'gherkin/rubify'
2
- require 'gherkin/lexer/i18n_lexer'
3
2
  require 'gherkin/formatter/escaping'
4
3
 
5
4
  module Cucumber
@@ -61,7 +60,7 @@ module Cucumber
61
60
 
62
61
  def self.parse(text, uri, offset)
63
62
  builder = Builder.new
64
- lexer = Gherkin::Lexer::I18nLexer.new(builder)
63
+ lexer = Gherkin::I18nLexer.new(builder)
65
64
  lexer.scan(text)
66
65
  new(builder.rows)
67
66
  end
@@ -74,6 +73,7 @@ module Cucumber
74
73
  def initialize(raw, conversion_procs = NULL_CONVERSIONS.dup)
75
74
  @cells_class = Cells
76
75
  @cell_class = Cell
76
+
77
77
  raw = ensure_array_of_array(rubify(raw))
78
78
  # Verify that it's square
79
79
  transposed = raw.transpose
@@ -153,7 +153,7 @@ module Cucumber
153
153
  #
154
154
  # gets converted into the following:
155
155
  #
156
- # [['a', 'b'], ['c', 'd']]
156
+ # [['a', 'b], ['c', 'd']]
157
157
  #
158
158
  def raw
159
159
  cell_matrix.map do |row|
@@ -163,14 +163,9 @@ module Cucumber
163
163
  end
164
164
  end
165
165
 
166
- def column_names #:nodoc:
167
- @col_names ||= cell_matrix[0].map { |cell| cell.value }
168
- end
169
-
166
+ # Same as #raw, but skips the first (header) row
170
167
  def rows
171
- hashes.map do |hash|
172
- hash.values_at *headers
173
- end
168
+ raw[1..-1]
174
169
  end
175
170
 
176
171
  def each_cells_row(&proc) #:nodoc:
@@ -276,9 +271,8 @@ module Cucumber
276
271
  # end
277
272
  #
278
273
  def map_column!(column_name, strict=true, &conversion_proc)
279
- verify_column(column_name.to_s) if strict
280
- @conversion_procs[column_name.to_s] = conversion_proc
281
- self
274
+ verify_column(column_name) if strict
275
+ @conversion_procs[column_name] = conversion_proc
282
276
  end
283
277
 
284
278
  # Compares +other_table+ to self. If +other_table+ contains columns
@@ -385,7 +379,7 @@ module Cucumber
385
379
  hash = Hash.new do |hash, key|
386
380
  hash[key.to_s] if key.is_a?(Symbol)
387
381
  end
388
- column_names.each_with_index do |column_name, column_index|
382
+ raw[0].each_with_index do |column_name, column_index|
389
383
  value = @conversion_procs[column_name].call(cells.value(column_index))
390
384
  hash[column_name] = value
391
385
  end
@@ -2,11 +2,11 @@ module Cucumber
2
2
  module Ast
3
3
  # Walks the AST, executing steps and notifying listeners
4
4
  class TreeWalker
5
- attr_accessor :configuration #:nodoc:
5
+ attr_accessor :options #:nodoc:
6
6
  attr_reader :step_mother #:nodoc:
7
7
 
8
- def initialize(step_mother, listeners = [], configuration = Cucumber::Configuration.default)
9
- @step_mother, @listeners, @configuration = step_mother, listeners, configuration
8
+ def initialize(step_mother, listeners = [], options = {}, io = STDOUT)
9
+ @step_mother, @listeners, @options, @io = step_mother, listeners, options, io
10
10
  end
11
11
 
12
12
  def visit_features(features)
@@ -122,7 +122,7 @@ module Cucumber
122
122
  broadcast(exception, status)
123
123
  end
124
124
 
125
- def visit_doc_string(string)
125
+ def visit_py_string(string)
126
126
  broadcast(string)
127
127
  end
128
128
 
@@ -142,15 +142,15 @@ module Cucumber
142
142
  broadcast(value, status)
143
143
  end
144
144
 
145
- # Print +messages+. This method can be called from within StepDefinitions.
146
- def puts(*messages)
147
- broadcast(*messages)
145
+ # Print +announcement+. This method can be called from within StepDefinitions.
146
+ def announce(announcement)
147
+ broadcast(announcement)
148
148
  end
149
149
 
150
150
  # Embed +file+ of +mime_type+ in the formatter. This method can be called from within StepDefinitions.
151
151
  # For most formatters this is a no-op.
152
- def embed(file, mime_type, label)
153
- broadcast(file, mime_type, label)
152
+ def embed(file, mime_type)
153
+ broadcast(file, mime_type)
154
154
  end
155
155
 
156
156
  private
@@ -171,10 +171,48 @@ module Cucumber
171
171
  def send_to_all(message, *args)
172
172
  @listeners.each do |listener|
173
173
  if listener.respond_to?(message)
174
- listener.__send__(message, *args)
174
+ if legacy_listener?(listener)
175
+ warn_legacy(listener)
176
+ legacy_invoke(listener, message, *args)
177
+ else
178
+ listener.__send__(message, *args)
179
+ end
175
180
  end
176
181
  end
177
182
  end
183
+
184
+ def legacy_listener?(listener)
185
+ listener.respond_to?(:feature_name) &&
186
+ (listener.method(:feature_name) rescue false) &&
187
+ listener.method(:feature_name).arity == 1
188
+ end
189
+
190
+ def warn_legacy(listener)
191
+ @warned_listeners ||= []
192
+ unless @warned_listeners.index(listener)
193
+ warn("#{listener.class} is using a deprecated formatter API. Starting with Cucumber 0.7.0 the signatures\n" +
194
+ "that have changed are:\n" +
195
+ " feature_name(keyword, name) # Two arguments. The keyword argument will not contain a colon.\n" +
196
+ " scenario_name(keyword, name, file_colon_line, source_indent) # The keyword argument will not contain a colon.\n" +
197
+ " examples_name(keyword, name) # The keyword argument will not contain a colon.\n"
198
+ )
199
+ end
200
+ @warned_listeners << listener
201
+ end
202
+
203
+ def legacy_invoke(listener, message, *args)
204
+ case message.to_sym
205
+ when :feature_name
206
+ listener.feature_name("#{args[0]}: #{args[1]}")
207
+ when :scenario_name, :examples_name
208
+ args_with_colon = args.dup
209
+ args_with_colon[0] += ':'
210
+ listener.__send__(message, *args_with_colon)
211
+ else
212
+ listener.__send__(message, *args)
213
+ end
214
+ end
215
+
178
216
  def extract_method_name_from(call_stack)
179
217
  call_stack[0].match(/in `(.*)'/).captures[0]
180
218
  end
@@ -12,7 +12,7 @@ module Cucumber
12
12
  class Configuration
13
13
  include Constantize
14
14
 
15
- attr_reader :out_stream
15
+ attr_reader :options, :out_stream
16
16
 
17
17
  def initialize(out_stream = STDOUT, error_stream = STDERR)
18
18
  @out_stream = out_stream
@@ -56,16 +56,8 @@ module Cucumber
56
56
  @options[:drb_port].to_i if @options[:drb_port]
57
57
  end
58
58
 
59
- def dry_run?
60
- @options[:dry_run]
61
- end
62
-
63
- def expand?
64
- @options[:expand]
65
- end
66
-
67
- def build_tree_walker(step_mother)
68
- Ast::TreeWalker.new(step_mother, formatters(step_mother), self)
59
+ def build_runner(step_mother, io)
60
+ Ast::TreeWalker.new(step_mother, formatters(step_mother), @options, io)
69
61
  end
70
62
 
71
63
  def formatter_class(format)
@@ -106,7 +98,7 @@ module Cucumber
106
98
  path = path.gsub(/\\/, '/') # In case we're on windows. Globs don't work with backslashes.
107
99
  path = path.chomp('/')
108
100
  if File.directory?(path)
109
- Dir["#{path}/**/*.feature"].sort
101
+ Dir["#{path}/**/*.feature"]
110
102
  elsif path[0..0] == '@' and # @listfile.txt
111
103
  File.file?(path[1..-1]) # listfile.txt is a file
112
104
  IO.read(path[1..-1]).split
@@ -129,27 +121,7 @@ module Cucumber
129
121
  logger.level = Logger::DEBUG if self.verbose?
130
122
  logger
131
123
  end
132
-
133
- def tag_expression
134
- Gherkin::TagExpression.new(@options[:tag_expressions])
135
- end
136
-
137
- def filters
138
- @options.filters
139
- end
140
-
141
- def formats
142
- @options[:formats]
143
- end
144
-
145
- def options
146
- warn("Deprecated: Configuration#options will be removed from the next release of Cucumber. Please use the configuration object directly instead.")
147
- @options
148
- end
149
-
150
- def paths
151
- @options[:paths].empty? ? ['features'] : @options[:paths]
152
- end
124
+
153
125
  private
154
126
 
155
127
  def formatters(step_mother)
@@ -179,6 +151,9 @@ module Cucumber
179
151
  end
180
152
  end
181
153
 
154
+ def paths
155
+ @options[:paths].empty? ? ['features'] : @options[:paths]
156
+ end
182
157
 
183
158
  def set_environment_variables
184
159
  @options[:env_vars].each do |var, value|
@@ -9,6 +9,7 @@ require 'cucumber'
9
9
  require 'logger'
10
10
  require 'cucumber/parser'
11
11
  require 'cucumber/feature_file'
12
+ require 'cucumber/formatter/color_io'
12
13
  require 'cucumber/cli/configuration'
13
14
  require 'cucumber/cli/drb_client'
14
15
 
@@ -16,32 +17,55 @@ module Cucumber
16
17
  module Cli
17
18
  class Main
18
19
  class << self
20
+ def step_mother
21
+ @step_mother ||= StepMother.new
22
+ end
23
+
19
24
  def execute(args)
20
- new(args).execute!
25
+ new(args).execute!(step_mother)
21
26
  end
22
27
  end
23
28
 
24
29
  def initialize(args, out_stream = STDOUT, error_stream = STDERR)
25
30
  @args = args
26
- @out_stream = out_stream
31
+ if Cucumber::WINDOWS_MRI
32
+ @out_stream = out_stream == STDOUT ? Formatter::ColorIO.new(Kernel, STDOUT) : out_stream
33
+ else
34
+ @out_stream = out_stream
35
+ end
27
36
 
28
37
  @error_stream = error_stream
29
38
  @configuration = nil
30
39
  end
31
40
 
32
- def execute!(existing_runtime = nil)
41
+ def execute!(step_mother)
33
42
  trap_interrupt
34
- return @drb_output if run_drb_client
43
+ if configuration.drb?
44
+ begin
45
+ return DRbClient.run(@args, @error_stream, @out_stream, configuration.drb_port)
46
+ rescue DRbClientError => e
47
+ @error_stream.puts "WARNING: #{e.message} Running features locally:"
48
+ end
49
+ end
50
+ step_mother.options = configuration.options
51
+ step_mother.log = configuration.log
52
+
53
+ step_mother.load_code_files(configuration.support_to_load)
54
+ step_mother.after_configuration(configuration)
55
+ features = step_mother.load_plain_text_features(configuration.feature_files)
56
+ step_mother.load_code_files(configuration.step_defs_to_load)
57
+
58
+ runner = configuration.build_runner(step_mother, @out_stream)
59
+ step_mother.visitor = runner # Needed to support World#announce
35
60
 
36
- runtime = if existing_runtime
37
- existing_runtime.configure(configuration)
38
- existing_runtime
61
+ runner.visit_features(features)
62
+
63
+ failure = if configuration.wip?
64
+ step_mother.scenarios(:passed).any?
39
65
  else
40
- Runtime.new(configuration)
66
+ step_mother.scenarios(:failed).any? ||
67
+ (configuration.strict? && (step_mother.steps(:undefined).any? || step_mother.steps(:pending).any?))
41
68
  end
42
-
43
- runtime.run!
44
- runtime.results.failure?
45
69
  rescue ProfilesNotDefinedError, YmlLoadError, ProfileNotFound => e
46
70
  @error_stream.puts e.message
47
71
  true
@@ -52,19 +76,10 @@ module Cucumber
52
76
 
53
77
  @configuration = Configuration.new(@out_stream, @error_stream)
54
78
  @configuration.parse!(@args)
55
- Cucumber.logger = @configuration.log
56
79
  @configuration
57
80
  end
58
81
 
59
82
  private
60
-
61
- def run_drb_client
62
- return false unless configuration.drb?
63
- @drb_output = DRbClient.run(@args, @error_stream, @out_stream, configuration.drb_port)
64
- true
65
- rescue DRbClientError => e
66
- @error_stream.puts "WARNING: #{e.message} Running features locally:"
67
- end
68
83
 
69
84
  def trap_interrupt
70
85
  trap('INT') do