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,9 +1,11 @@
1
+ require 'cucumber/formatter/color_io'
2
+
1
3
  module Cucumber
2
4
  module Formatter
3
5
  module Io
4
6
  def ensure_io(path_or_io, name)
5
7
  return nil if path_or_io.nil?
6
- return path_or_io if path_or_io.respond_to?(:write)
8
+ return path_or_io if ColorIO === path_or_io || path_or_io.respond_to?(:write)
7
9
  file = File.open(path_or_io, Cucumber.file_mode('w'))
8
10
  at_exit do
9
11
  unless file.closed?
@@ -28,4 +30,4 @@ module Cucumber
28
30
  end
29
31
  end
30
32
  end
31
- end
33
+ end
@@ -1,29 +1,166 @@
1
- require 'cucumber/formatter/gherkin_formatter_adapter'
2
- require 'cucumber/formatter/io'
3
- require 'gherkin/formatter/argument'
4
- require 'gherkin/formatter/json_formatter'
1
+ require "json"
2
+ require "cucumber/formatter/io"
5
3
 
6
4
  module Cucumber
7
5
  module Formatter
8
6
  # The formatter used for <tt>--format json</tt>
9
- class Json < GherkinFormatterAdapter
7
+ class Json
8
+ class Error < StandardError
9
+ end
10
+
10
11
  include Io
11
12
 
12
13
  def initialize(step_mother, io, options)
13
- @io = ensure_io(io, "json")
14
- @obj = {'features' => []}
15
- super(Gherkin::Formatter::JSONFormatter.new(nil), false)
14
+ @io = ensure_io(io, "json")
15
+ @options = options
16
+ end
17
+
18
+ def before_features(features)
19
+ @json = {:features => []}
20
+ end
21
+
22
+ def before_feature(feature)
23
+ @current_object = {:file => feature.file, :name => feature.name}
24
+ @json[:features] << @current_object
25
+ end
26
+
27
+ def before_tags(tags)
28
+ @current_object[:tags] = tags.tag_names.to_a
29
+ end
30
+
31
+ def before_background(background)
32
+ background = {}
33
+ @current_object[:background] = background
34
+ @current_object = background
35
+ end
36
+
37
+ def after_background(background)
38
+ @current_object = last_feature
39
+ end
40
+
41
+ def before_feature_element(feature_element)
42
+ elements = @current_object[:elements] ||= []
43
+
44
+ # change current object to the feature_element
45
+ @current_object = {}
46
+ elements << @current_object
47
+ end
48
+
49
+ def scenario_name(keyword, name, file_colon_line, source_indent)
50
+ @current_object[:keyword] = keyword
51
+ @current_object[:name] = name
52
+ @current_object[:file_colon_line] = file_colon_line
53
+ end
54
+
55
+ def before_steps(steps)
56
+ @current_object[:steps] = []
57
+ end
58
+
59
+ def before_step(step)
60
+ @current_step = {}
61
+ @current_object[:steps] << @current_step
16
62
  end
17
63
 
18
- def after_feature(feature)
19
- super
20
- @obj['features'] << @gf.gherkin_object
64
+ def before_step_result(keyword, step_match, multiline_arg, status, exception, source_indent, background)
65
+ if exception
66
+ @current_step[:exception] = exception_hash_for(exception)
67
+ end
68
+ end
69
+
70
+ def step_name(keyword, step_match, status, source_indent, background)
71
+ @current_step[:status] = status
72
+ @current_step[:keyword] = keyword
73
+ @current_step[:name] = "#{step_match.name || step_match.format_args}"
74
+ @current_step[:file_colon_line] = step_match.file_colon_line
75
+ end
76
+
77
+ def after_step(step)
78
+ @current_step = nil
79
+ end
80
+
81
+ def before_examples(examples)
82
+ @current_object[:examples] = {}
83
+ end
84
+
85
+ def examples_name(keyword, name)
86
+ @current_object[:examples][:name] = "#{keyword} #{name}"
87
+ end
88
+
89
+ def before_outline_table(*args)
90
+ @current_object[:examples][:table] = []
91
+ end
92
+
93
+ def before_table_row(row)
94
+ @current_row = {:cells => []}
95
+
96
+ if @current_object.member? :examples
97
+ @current_object[:examples][:table] << @current_row
98
+ elsif @current_step
99
+ (@current_step[:table] ||= []) << @current_row
100
+ else
101
+ internal_error
102
+ end
103
+ end
104
+
105
+ def table_cell_value(value, status)
106
+ @current_row[:cells] << {:text => value, :status => status}
107
+ end
108
+
109
+ def after_table_row(row)
110
+ if row.exception
111
+ @current_row[:exception] = exception_hash_for(row.exception)
112
+ end
113
+ @current_row = nil
114
+ end
115
+
116
+ def py_string(string)
117
+ @current_step[:py_string] = string
118
+ end
119
+
120
+ def after_feature_element(feature_element)
121
+ # change current object back to the last feature
122
+ @current_object = last_feature
21
123
  end
22
124
 
23
125
  def after_features(features)
24
- @io.write(@obj.to_json)
126
+ @io.write json_string
127
+ @io.flush
25
128
  end
26
- end
27
- end
28
- end
129
+
130
+ def embed(file, mime_type)
131
+ obj = @current_step || @current_object
132
+ obj[:embedded] ||= []
133
+
134
+ obj[:embedded] << {
135
+ :file => file,
136
+ :mime_type => mime_type,
137
+ :data => [File.read(file)].pack("m*") # base64
138
+ }
139
+ end
140
+
141
+ private
142
+
143
+ def json_string
144
+ @json.to_json
145
+ end
146
+
147
+ def last_feature
148
+ @json[:features].last
149
+ end
150
+
151
+ def exception_hash_for(e)
152
+ {
153
+ :class => e.class.name,
154
+ :message => e.message,
155
+ :backtrace => e.backtrace
156
+ }
157
+ end
158
+
159
+ def internal_error
160
+ raise Error, "you've found a bug in the JSON formatter!"
161
+ end
162
+
163
+ end # Json
164
+ end # Formatter
165
+ end # Cucumber
29
166
 
@@ -1,13 +1,14 @@
1
- require 'cucumber/formatter/json'
1
+ require "cucumber/formatter/json"
2
2
 
3
3
  module Cucumber
4
4
  module Formatter
5
5
  # The formatter used for <tt>--format json_pretty</tt>
6
6
  class JsonPretty < Json
7
- def after_features(features)
8
- @io.write(JSON.pretty_generate(@obj))
7
+
8
+ def json_string
9
+ JSON.pretty_generate @json
9
10
  end
11
+
10
12
  end
11
13
  end
12
- end
13
-
14
+ end
@@ -21,22 +21,17 @@ module Cucumber
21
21
 
22
22
  def before_feature(feature)
23
23
  @current_feature = feature
24
- @failures = @errors = @tests = @skipped = 0
24
+ @failures = @errors = @tests = 0
25
25
  @builder = OrderedXmlMarkup.new( :indent => 2 )
26
26
  @time = 0
27
27
  end
28
28
 
29
- def before_feature_element(feature_element)
30
- @in_examples = Ast::ScenarioOutline === feature_element
31
- end
32
-
33
29
  def after_feature(feature)
34
30
  @testsuite = OrderedXmlMarkup.new( :indent => 2 )
35
31
  @testsuite.instruct!
36
32
  @testsuite.testsuite(
37
33
  :failures => @failures,
38
34
  :errors => @errors,
39
- :skipped => @skipped,
40
35
  :tests => @tests,
41
36
  :time => "%.6f" % @time,
42
37
  :name => @feature_name ) do
@@ -61,8 +56,13 @@ module Cucumber
61
56
  end
62
57
 
63
58
  def scenario_name(keyword, name, file_colon_line, source_indent)
64
- @scenario = (name.nil? || name == "") ? "Unnamed scenario" : name.split("\n")[0]
65
- @output = "#{keyword}: #{@scenario}\n\n"
59
+ # TODO: What's all this ugly weird code doing? Why not just use keyword and name????
60
+ scenario_name = name.strip.delete(".\r\n")
61
+ scenario_name = "Unnamed scenario" if name == ""
62
+ @scenario = scenario_name
63
+ description = "Scenario"
64
+ description << " outline" if keyword.include?('Scenario Outline')
65
+ @output = "#{description}: #{@scenario}\n\n"
66
66
  end
67
67
 
68
68
  def before_steps(steps)
@@ -96,7 +96,7 @@ module Cucumber
96
96
  end
97
97
 
98
98
  def after_table_row(table_row)
99
- return unless @in_examples and Cucumber::Ast::OutlineTable::ExampleRow === table_row
99
+ return unless @in_examples
100
100
  duration = Time.now - @table_start
101
101
  unless @header_row
102
102
  name_suffix = " (outline example : #{table_row.name})"
@@ -116,23 +116,20 @@ module Cucumber
116
116
  @time += duration
117
117
  classname = "#{@feature_name}.#{@scenario}"
118
118
  name = "#{@scenario}#{suffix}"
119
- pending = [:pending, :undefined].include?(status)
120
- passed = (status == :passed || (pending && !@options[:strict]))
121
-
122
- @builder.testcase(:classname => classname, :name => name, :time => "%.6f" % duration) do
123
- unless passed
124
- @builder.failure(:message => "#{status.to_s} #{name}", :type => status.to_s) do
125
- @builder.cdata! @output
126
- @builder.cdata!(format_exception(exception)) if exception
119
+ failed = (status == :failed || (status == :pending && @options[:strict]))
120
+ #puts "FAILED:!!#{failed}"
121
+ if status == :passed || failed
122
+ @builder.testcase(:classname => classname, :name => name, :time => "%.6f" % duration) do
123
+ if failed
124
+ @builder.failure(:message => "#{status.to_s} #{name}", :type => status.to_s) do
125
+ @builder.text! @output
126
+ @builder.text!(format_exception(exception)) if exception
127
+ end
128
+ @failures += 1
127
129
  end
128
- @failures += 1
129
- end
130
- if passed and (status == :skipped || pending)
131
- @builder.skipped
132
- @skipped += 1
133
130
  end
131
+ @tests += 1
134
132
  end
135
- @tests += 1
136
133
  end
137
134
 
138
135
  def format_exception(exception)
@@ -140,12 +137,9 @@ module Cucumber
140
137
  end
141
138
 
142
139
  def feature_result_filename(feature_file)
143
- File.join(@reportdir, "TEST-#{basename(feature_file)}.xml")
144
- end
145
-
146
- def basename(feature_file)
147
140
  ext_length = File.extname(feature_file).length
148
- feature_file.gsub('features/', '').gsub(File::SEPARATOR, '_')[0...-ext_length]
141
+ basename = File.basename(feature_file)[0...-ext_length]
142
+ File.join(@reportdir, "TEST-#{basename}.xml")
149
143
  end
150
144
 
151
145
  def write_file(feature_filename, data)
@@ -28,9 +28,9 @@ module Cucumber
28
28
  @file = ensure_file(path_or_io, "pdf")
29
29
 
30
30
  if(options[:dry_run])
31
- @status_colors = { :passed => BLACK, :skipped => BLACK, :undefined => BLACK, :failed => BLACK, :putsd => GREY}
31
+ @status_colors = { :passed => BLACK, :skipped => BLACK, :undefined => BLACK, :failed => BLACK, :announced => GREY}
32
32
  else
33
- @status_colors = { :passed => '055902', :skipped => GREY, :undefined => 'F27405', :failed => '730202', :putsd => GREY}
33
+ @status_colors = { :passed => '055902', :skipped => GREY, :undefined => 'F27405', :failed => '730202', :announced => GREY}
34
34
  end
35
35
 
36
36
  @pdf = Prawn::Document.new
@@ -71,9 +71,9 @@ module Cucumber
71
71
  end
72
72
  end
73
73
 
74
- def puts(message)
75
- @pdf.fill_color(@status_colors[:putsd])
76
- @pdf.text message, :size => 10
74
+ def announce(announcement)
75
+ @pdf.fill_color(@status_colors[:announced])
76
+ @pdf.text announcement, :size => 10
77
77
  @pdf.fill_color BLACK
78
78
  end
79
79
 
@@ -172,7 +172,7 @@ module Cucumber
172
172
  end
173
173
  end
174
174
 
175
- def before_doc_string(string)
175
+ def before_py_string(string)
176
176
  return if @hide_this_step
177
177
  s = %{"""\n#{string}\n"""}.indent(10)
178
178
  s = s.split("\n").map{|l| l =~ /^\s+$/ ? '' : l}
@@ -25,7 +25,7 @@ module Cucumber
25
25
  @exceptions = []
26
26
  @indent = 0
27
27
  @prefixes = options[:prefixes] || {}
28
- @delayed_messages = []
28
+ @delayed_announcements = []
29
29
  end
30
30
 
31
31
  def after_features(features)
@@ -101,7 +101,7 @@ module Cucumber
101
101
  end
102
102
 
103
103
  def examples_name(keyword, name)
104
- @io.puts unless @visiting_first_example_name
104
+ puts unless @visiting_first_example_name
105
105
  @visiting_first_example_name = false
106
106
  names = name.strip.empty? ? [name.strip] : name.split("\n")
107
107
  @io.puts(" #{keyword}: #{names[0]}")
@@ -150,10 +150,10 @@ module Cucumber
150
150
  source_indent = nil unless @options[:source]
151
151
  name_to_report = format_step(keyword, step_match, status, source_indent)
152
152
  @io.puts(name_to_report.indent(@scenario_indent + 2))
153
- print_messages
153
+ print_announcements
154
154
  end
155
155
 
156
- def doc_string(string)
156
+ def py_string(string)
157
157
  return if @hide_this_step
158
158
  s = %{"""\n#{string}\n"""}.indent(@indent)
159
159
  s = s.split("\n").map{|l| l =~ /^\s+$/ ? '' : l}.join("\n")
@@ -184,7 +184,7 @@ module Cucumber
184
184
 
185
185
  def after_table_row(table_row)
186
186
  return if !@table || @hide_this_step
187
- print_table_row_messages
187
+ print_table_row_announcements
188
188
  @io.puts
189
189
  if table_row.exception && !@exceptions.include?(table_row.exception)
190
190
  print_exception(table_row.exception, table_row.status, @indent)
@@ -21,21 +21,17 @@ module Cucumber
21
21
  @file_names = []
22
22
  @file_colon_lines = Hash.new{|h,k| h[k] = []}
23
23
  end
24
-
25
- def before_feature(*)
26
- @lines = []
27
- @file = nil
28
- end
29
-
30
- def after_feature(*)
31
- after_first_time do
32
- @io.print ' '
33
- end
34
- @io.print "#{@file}:#{@lines.join(':')}"
35
- @io.flush
36
- end
37
24
 
25
+ # features() is never executed at all... ?
38
26
  def after_features(features)
27
+ files = @file_names.uniq.map do |file|
28
+ lines = @file_colon_lines[file]
29
+ "#{file}:#{lines.join(':')}"
30
+ end
31
+ @io.puts files.join(' ')
32
+
33
+ # Flusing output to rerun tempfile here...
34
+ @io.flush
39
35
  @io.close
40
36
  end
41
37
 
@@ -46,21 +42,14 @@ module Cucumber
46
42
  def after_feature_element(feature_element)
47
43
  if @rerun
48
44
  file, line = *feature_element.file_colon_line.split(':')
49
- @lines << line
50
- @file = file
45
+ @file_colon_lines[file] << line
46
+ @file_names << file
51
47
  end
52
48
  end
53
49
 
54
50
  def step_name(keyword, step_match, status, source_indent, background)
55
51
  @rerun = true if [:failed, :pending, :undefined].index(status)
56
52
  end
57
-
58
- private
59
-
60
- def after_first_time
61
- yield if @not_first_time
62
- @not_first_time = true
63
- end
64
53
  end
65
54
  end
66
55
  end
@@ -0,0 +1,35 @@
1
+ require 'cucumber/formatter/io'
2
+ require 'cucumber/formatter/pretty'
3
+
4
+ module Cucumber
5
+ module Formatter
6
+ # The formatter used for <tt>--format tag_cloud</tt>
7
+ # Custom formatter that prints a tag cloud as a table.
8
+ class TagCloud
9
+ include Io
10
+
11
+ def initialize(step_mother, path_or_io, options)
12
+ @io = ensure_io(path_or_io, "tag_cloud")
13
+ @options = options
14
+ @counts = Hash.new{|h,k| h[k] = 0}
15
+ end
16
+
17
+ def after_features(features)
18
+ print_summary(features)
19
+ end
20
+
21
+ def tag_name(tag_name)
22
+ @counts[tag_name] += 1
23
+ end
24
+
25
+ private
26
+
27
+ def print_summary(features)
28
+ matrix = @counts.to_a.sort{|paira, pairb| paira[0] <=> pairb[0]}.transpose
29
+ table = Cucumber::Ast::Table.new(matrix)
30
+ formatter = Cucumber::Formatter::Pretty.new(@step_mother, @io, {})
31
+ Cucumber::Ast::TreeWalker.new(@step_mother, [formatter], {}).visit_multiline_arg(table)
32
+ end
33
+ end
34
+ end
35
+ end