cucumber 2.0.0.beta.3 → 2.0.0.beta.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (56) hide show
  1. checksums.yaml +4 -4
  2. data/History.md +20 -3
  3. data/cucumber.gemspec +2 -1
  4. data/examples/tcl/features/step_definitions/fib_steps.rb +1 -1
  5. data/features/docs/extending_cucumber/custom_formatter.feature +65 -7
  6. data/features/docs/formatters/debug_formatter.feature +24 -17
  7. data/features/docs/formatters/pretty_formatter.feature +42 -0
  8. data/features/docs/formatters/rerun_formatter.feature +3 -2
  9. data/lib/cucumber/cli/configuration.rb +3 -7
  10. data/lib/cucumber/cli/main.rb +1 -1
  11. data/lib/cucumber/{runtime → filters}/gated_receiver.rb +5 -1
  12. data/lib/cucumber/filters/quit.rb +24 -0
  13. data/lib/cucumber/filters/randomizer.rb +36 -0
  14. data/lib/cucumber/filters/tag_limits.rb +40 -0
  15. data/lib/cucumber/{runtime → filters}/tag_limits/test_case_index.rb +4 -2
  16. data/lib/cucumber/{runtime → filters}/tag_limits/verifier.rb +4 -2
  17. data/lib/cucumber/formatter/console.rb +2 -2
  18. data/lib/cucumber/formatter/debug.rb +1 -8
  19. data/lib/cucumber/formatter/fanout.rb +27 -0
  20. data/lib/cucumber/formatter/gherkin_formatter_adapter.rb +1 -3
  21. data/lib/cucumber/formatter/html.rb +12 -4
  22. data/lib/cucumber/formatter/ignore_missing_messages.rb +20 -0
  23. data/lib/cucumber/formatter/junit.rb +2 -2
  24. data/lib/cucumber/formatter/legacy_api/adapter.rb +1008 -0
  25. data/lib/cucumber/formatter/legacy_api/ast.rb +374 -0
  26. data/lib/cucumber/formatter/legacy_api/results.rb +51 -0
  27. data/lib/cucumber/formatter/legacy_api/runtime_facade.rb +30 -0
  28. data/lib/cucumber/formatter/pretty.rb +4 -0
  29. data/lib/cucumber/formatter/rerun.rb +14 -88
  30. data/lib/cucumber/language_support/language_methods.rb +0 -54
  31. data/lib/cucumber/multiline_argument/data_table.rb +3 -4
  32. data/lib/cucumber/platform.rb +1 -1
  33. data/lib/cucumber/runtime.rb +41 -107
  34. data/spec/cucumber/{runtime → filters}/gated_receiver_spec.rb +3 -3
  35. data/spec/cucumber/{runtime → filters}/tag_limits/test_case_index_spec.rb +3 -3
  36. data/spec/cucumber/{runtime → filters}/tag_limits/verifier_spec.rb +4 -4
  37. data/spec/cucumber/{runtime/tag_limits/filter_spec.rb → filters/tag_limits_spec.rb} +6 -6
  38. data/spec/cucumber/formatter/debug_spec.rb +39 -530
  39. data/spec/cucumber/formatter/html_spec.rb +56 -0
  40. data/spec/cucumber/formatter/legacy_api/adapter_spec.rb +1902 -0
  41. data/spec/cucumber/formatter/pretty_spec.rb +128 -0
  42. data/spec/cucumber/formatter/rerun_spec.rb +106 -0
  43. data/spec/cucumber/formatter/spec_helper.rb +6 -2
  44. data/spec/cucumber/rb_support/rb_language_spec.rb +2 -2
  45. data/spec/cucumber/rb_support/rb_step_definition_spec.rb +1 -1
  46. data/spec/cucumber/runtime_spec.rb +1 -5
  47. data/spec/spec_helper.rb +2 -0
  48. metadata +44 -29
  49. data/features/docs/extending_cucumber/formatter_callbacks.feature +0 -370
  50. data/features/docs/output_from_hooks.feature +0 -128
  51. data/lib/cucumber/reports/legacy_formatter.rb +0 -1349
  52. data/lib/cucumber/runtime/results.rb +0 -64
  53. data/lib/cucumber/runtime/tag_limits.rb +0 -15
  54. data/lib/cucumber/runtime/tag_limits/filter.rb +0 -31
  55. data/spec/cucumber/reports/legacy_formatter_spec.rb +0 -1860
  56. data/spec/cucumber/runtime/results_spec.rb +0 -88
@@ -0,0 +1,374 @@
1
+ module Cucumber
2
+ module Formatter
3
+ module LegacyApi
4
+ # Adapters to pass to the legacy API formatters that provide the interface
5
+ # of the old AST classes
6
+ module Ast
7
+
8
+ # Acts as a null object, or a base class
9
+ class Node
10
+ def initialize(node = nil)
11
+ @node = node
12
+ end
13
+
14
+ def accept(formatter)
15
+ end
16
+
17
+ attr_reader :node
18
+ private :node
19
+ end
20
+
21
+ # Null object for HeaderRow language.
22
+ # ExampleTableRow#keyword is never called on them,
23
+ # but this will pass silently if it happens anyway
24
+ class NullLanguage
25
+ def method_missing(*args, &block)
26
+ self
27
+ end
28
+
29
+ def to_ary
30
+ ['']
31
+ end
32
+ end
33
+
34
+ class HookResultCollection
35
+ def initialize
36
+ @children = []
37
+ end
38
+
39
+ def accept(formatter)
40
+ @children.each { |child| child.accept(formatter) }
41
+ end
42
+
43
+ def send_output_to(formatter)
44
+ @children.each { |child| child.send_output_to(formatter) }
45
+ end
46
+
47
+ def describe_exception_to(formatter)
48
+ @children.each { |child| child.describe_exception_to(formatter) }
49
+ end
50
+
51
+ def <<(child)
52
+ @children << child
53
+ end
54
+ end
55
+
56
+ Comments = Struct.new(:comments) do
57
+ def accept(formatter)
58
+ return if comments.empty?
59
+ formatter.before_comment comments
60
+ comments.each do |comment|
61
+ formatter.comment_line comment.to_s.strip
62
+ end
63
+ end
64
+ end
65
+
66
+ class HookResult
67
+ def initialize(result, messages, embeddings)
68
+ @result, @messages, @embeddings = result, messages, embeddings
69
+ @already_accepted = false
70
+ end
71
+
72
+ def accept(formatter)
73
+ unless @already_accepted
74
+ send_output_to(formatter)
75
+ describe_exception_to(formatter)
76
+ end
77
+ self
78
+ end
79
+
80
+ def send_output_to(formatter)
81
+ unless @already_accepted
82
+ @messages.each { |message| formatter.puts(message) }
83
+ @embeddings.each { |embedding| embedding.send_to_formatter(formatter) }
84
+ end
85
+ end
86
+
87
+ def describe_exception_to(formatter)
88
+ unless @already_accepted
89
+ @result.describe_exception_to(formatter)
90
+ @already_accepted = true
91
+ end
92
+ end
93
+ end
94
+
95
+ StepInvocation = Struct.new(:step_match,
96
+ :status,
97
+ :duration,
98
+ :exception,
99
+ :indent,
100
+ :background,
101
+ :step,
102
+ :messages,
103
+ :embeddings) do
104
+ extend Forwardable
105
+
106
+ def_delegators :step, :keyword, :name, :multiline_arg, :location, :gherkin_statement
107
+
108
+ def accept(formatter)
109
+ formatter.before_step(self)
110
+ messages.each { |message| formatter.puts(message) }
111
+ embeddings.each { |embedding| embedding.send_to_formatter(formatter) }
112
+ formatter.before_step_result *step_result_attributes
113
+ print_step_name(formatter)
114
+ Ast::MultilineArg.for(multiline_arg).accept(formatter)
115
+ print_exception(formatter)
116
+ formatter.after_step_result *step_result_attributes
117
+ formatter.after_step(self)
118
+ end
119
+
120
+ def step_result_attributes
121
+ [keyword, step_match, multiline_arg, status, exception, source_indent, background, file_colon_line]
122
+ end
123
+
124
+ def failed?
125
+ status != :passed
126
+ end
127
+
128
+ def passed?
129
+ status == :passed
130
+ end
131
+
132
+ def dom_id
133
+
134
+ end
135
+
136
+ def actual_keyword
137
+ # TODO: This should return the keyword for the snippet
138
+ # `actual_keyword` translates 'And', 'But', etc. to 'Given', 'When',
139
+ # 'Then' as appropriate
140
+ "Given"
141
+ end
142
+
143
+ def file_colon_line
144
+ location.to_s
145
+ end
146
+
147
+ def backtrace_line
148
+ step_match.backtrace_line
149
+ end
150
+
151
+ def step_invocation
152
+ self
153
+ end
154
+
155
+ private
156
+
157
+ def source_indent
158
+ indent.of(self)
159
+ end
160
+
161
+ def print_step_name(formatter)
162
+ formatter.step_name(
163
+ keyword,
164
+ step_match,
165
+ status,
166
+ source_indent,
167
+ background,
168
+ location.to_s)
169
+ end
170
+
171
+ def print_exception(formatter)
172
+ return unless exception
173
+ raise exception if ENV['FAIL_FAST']
174
+ formatter.exception(exception, status)
175
+ end
176
+ end
177
+
178
+ class StepInvocations < Array
179
+ def failed?
180
+ any?(&:failed?)
181
+ end
182
+
183
+ def passed?
184
+ all?(&:passed?)
185
+ end
186
+
187
+ def status
188
+ return :passed if passed?
189
+ failed_step.status
190
+ end
191
+
192
+ def exception
193
+ failed_step.exception if failed_step
194
+ end
195
+
196
+ private
197
+
198
+ def failed_step
199
+ detect(&:failed?)
200
+ end
201
+ end
202
+
203
+ class DataTableRow
204
+ def initialize(row, line)
205
+ @values = row
206
+ @line = line
207
+ end
208
+
209
+ def dom_id
210
+ "row_#{line}"
211
+ end
212
+
213
+ def accept(formatter)
214
+ formatter.before_table_row(self)
215
+ values.each do |value|
216
+ formatter.before_table_cell(value)
217
+ formatter.table_cell_value(value, status)
218
+ formatter.after_table_cell(value)
219
+ end
220
+ formatter.after_table_row(self)
221
+ end
222
+
223
+ def status
224
+ :skipped
225
+ end
226
+
227
+ def exception
228
+ nil
229
+ end
230
+
231
+ attr_reader :values, :line
232
+ private :values, :line
233
+ end
234
+
235
+ ExampleTableRow = Struct.new(:exception, :status, :cells, :location, :language) do
236
+ def name
237
+ '| ' + cells.join(' | ') + ' |'
238
+ end
239
+
240
+ def failed?
241
+ status == :failed
242
+ end
243
+
244
+ def line
245
+ location.line
246
+ end
247
+
248
+ def keyword
249
+ # This method is only called when used for the scenario name line with
250
+ # the expand option, and on that line the keyword is "Scenario"
251
+ language.keywords('scenario')[0]
252
+ end
253
+ end
254
+
255
+ class LegacyTableRow < DataTableRow
256
+ def accept(formatter)
257
+ formatter.before_table_row(self)
258
+ values.each do |value|
259
+ formatter.before_table_cell(value.value)
260
+ formatter.table_cell_value(value.value, value.status)
261
+ formatter.after_table_cell(value.value)
262
+ end
263
+ formatter.after_table_row(self)
264
+ end
265
+ end
266
+
267
+ Tags = Struct.new(:tags) do
268
+ def accept(formatter)
269
+ formatter.before_tags tags
270
+ tags.each do |tag|
271
+ formatter.tag_name tag.name
272
+ end
273
+ formatter.after_tags tags
274
+ end
275
+ end
276
+
277
+ Scenario = Struct.new(:status, :name, :location) do
278
+ def backtrace_line(step_name = "#{name}", line = self.location.line)
279
+ "#{location.on_line(line)}:in `#{step_name}'"
280
+ end
281
+
282
+ def failed?
283
+ :failed == status
284
+ end
285
+
286
+ def line
287
+ location.line
288
+ end
289
+ end
290
+
291
+ ScenarioOutline = Struct.new(:status, :name, :location) do
292
+ def backtrace_line(step_name = "#{name}", line = self.location.line)
293
+ "#{location.on_line(line)}:in `#{step_name}'"
294
+ end
295
+
296
+ def failed?
297
+ :failed == status
298
+ end
299
+
300
+ def line
301
+ location.line
302
+ end
303
+ end
304
+
305
+ module MultilineArg
306
+ class << self
307
+ def for(node)
308
+ Builder.new(node).result
309
+ end
310
+ end
311
+
312
+ class Builder
313
+ def initialize(node)
314
+ node.describe_to(self)
315
+ end
316
+
317
+ def doc_string(node)
318
+ @result = DocString.new(node)
319
+ end
320
+
321
+ def data_table(node)
322
+ @result = DataTable.new(node)
323
+ end
324
+
325
+ def legacy_table(node)
326
+ @result = LegacyTable.new(node)
327
+ end
328
+
329
+ def result
330
+ @result || Node.new(nil)
331
+ end
332
+ end
333
+
334
+ class DocString < Node
335
+ def accept(formatter)
336
+ formatter.before_multiline_arg node
337
+ formatter.doc_string(node)
338
+ formatter.after_multiline_arg node
339
+ end
340
+ end
341
+
342
+ class DataTable < Cucumber::MultilineArgument::DataTable
343
+ def node
344
+ @ast_table
345
+ end
346
+
347
+ def accept(formatter)
348
+ formatter.before_multiline_arg self
349
+ node.raw.each_with_index do |row, index|
350
+ line = node.location.line + index
351
+ DataTableRow.new(row, line).accept(formatter)
352
+ end
353
+ formatter.after_multiline_arg self
354
+ end
355
+ end
356
+ end
357
+
358
+ class LegacyTable < SimpleDelegator
359
+ def accept(formatter)
360
+ formatter.before_multiline_arg self
361
+ cells_rows.each_with_index do |row, index|
362
+ line = location.line + index
363
+ LegacyTableRow.new(row, line).accept(formatter)
364
+ end
365
+ formatter.after_multiline_arg self
366
+ end
367
+ end
368
+
369
+ Features = Struct.new(:duration)
370
+
371
+ end
372
+ end
373
+ end
374
+ end
@@ -0,0 +1,51 @@
1
+ module Cucumber
2
+ module Formatter
3
+ module LegacyApi
4
+
5
+ class Results
6
+ def initialize
7
+ # Optimization - quicker lookup.
8
+ @inserted_steps = {}
9
+ @inserted_scenarios = {}
10
+ end
11
+
12
+ def step_visited(step) #:nodoc:
13
+ step_id = step.object_id
14
+
15
+ unless @inserted_steps.has_key?(step_id)
16
+ @inserted_steps[step_id] = step
17
+ steps.push(step)
18
+ end
19
+ end
20
+
21
+ def scenario_visited(scenario) #:nodoc:
22
+ scenario_id = scenario.object_id
23
+
24
+ unless @inserted_scenarios.has_key?(scenario_id)
25
+ @inserted_scenarios[scenario_id] = scenario
26
+ scenarios.push(scenario)
27
+ end
28
+ end
29
+
30
+ def steps(status = nil) #:nodoc:
31
+ @steps ||= []
32
+ if(status)
33
+ @steps.select{|step| step.status == status}
34
+ else
35
+ @steps
36
+ end
37
+ end
38
+
39
+ def scenarios(status = nil) #:nodoc:
40
+ @scenarios ||= []
41
+ if(status)
42
+ @scenarios.select{|scenario| scenario.status == status}
43
+ else
44
+ @scenarios
45
+ end
46
+ end
47
+ end
48
+
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,30 @@
1
+ module Cucumber
2
+ module Formatter
3
+ module LegacyApi
4
+
5
+ # This is what's passed to the constructor of the formatters
6
+ class RuntimeFacade < Struct.new(:results, :support_code, :configuration)
7
+ def unmatched_step_definitions
8
+ support_code.unmatched_step_definitions
9
+ end
10
+
11
+ def snippet_text(step_keyword, step_name, multiline_arg) #:nodoc:
12
+ support_code.snippet_text(::Gherkin::I18n.code_keyword_for(step_keyword), step_name, multiline_arg)
13
+ end
14
+
15
+ def unknown_programming_language?
16
+ support_code.unknown_programming_language?
17
+ end
18
+
19
+ def scenarios(status = nil)
20
+ results.scenarios(status)
21
+ end
22
+
23
+ def steps(status = nil)
24
+ results.steps(status)
25
+ end
26
+ end
27
+
28
+ end
29
+ end
30
+ end