cucumber 2.0.0.beta.3 → 2.0.0
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.
- checksums.yaml +4 -4
- data/.travis.yml +3 -3
- data/History.md +131 -32
- data/Rakefile +0 -2
- data/cucumber.gemspec +4 -3
- data/examples/i18n/ht/Rakefile +6 -0
- data/examples/i18n/ht/features/adisyon.feature +17 -0
- data/examples/i18n/ht/features/divizyon.feature +10 -0
- data/examples/i18n/ht/features/step_definitions/kalkilatris_steps.rb +25 -0
- data/examples/i18n/ht/lib/kalkilatris.rb +14 -0
- data/examples/tcl/features/step_definitions/fib_steps.rb +1 -1
- data/features/docs/cli/dry_run.feature +48 -0
- data/features/docs/cli/exclude_files.feature +1 -2
- data/features/docs/cli/run_specific_scenarios.feature +28 -66
- data/features/docs/cli/strict_mode.feature +24 -1
- data/features/docs/defining_steps/nested_steps.feature +49 -0
- data/features/docs/defining_steps/skip_scenario.feature +31 -2
- data/features/docs/defining_steps/snippets.feature +15 -0
- data/features/docs/exception_in_after_step_hook.feature +1 -1
- data/features/docs/exception_in_around_hook.feature +80 -0
- data/features/docs/extending_cucumber/custom_filter.feature +29 -0
- data/features/docs/extending_cucumber/custom_formatter.feature +65 -7
- data/features/docs/formatters/debug_formatter.feature +24 -17
- data/features/docs/formatters/json_formatter.feature +65 -1
- data/features/docs/formatters/junit_formatter.feature +40 -0
- data/features/docs/formatters/pretty_formatter.feature +42 -0
- data/features/docs/formatters/rerun_formatter.feature +3 -2
- data/features/docs/getting_started.feature +1 -1
- data/features/docs/{wire_protocol_erb.feature → wire_protocol/erb_configuration.feature} +2 -2
- data/features/docs/wire_protocol/handle_unexpected_response.feature +30 -0
- data/features/docs/wire_protocol/invoke_message.feature +216 -0
- data/features/docs/wire_protocol/readme.md +26 -0
- data/features/docs/wire_protocol/snippets_message.feature +51 -0
- data/features/docs/wire_protocol/step_matches_message.feature +81 -0
- data/features/docs/{wire_protocol_table_diffing.feature → wire_protocol/table_diffing.feature} +1 -0
- data/features/docs/{wire_protocol_tags.feature → wire_protocol/tags.feature} +1 -0
- data/features/docs/{wire_protocol_timeouts.feature → wire_protocol/timeouts.feature} +1 -0
- data/features/docs/work_in_progress.feature +1 -1
- data/features/docs/writing_support_code/after_hooks.feature +24 -0
- data/features/docs/writing_support_code/around_hooks.feature +31 -0
- data/features/docs/writing_support_code/before_hook.feature +7 -3
- data/features/docs/writing_support_code/tagged_hooks.feature +44 -6
- data/features/lib/step_definitions/wire_steps.rb +18 -1
- data/features/lib/support/fake_wire_server.rb +10 -7
- data/lib/cucumber/cli/configuration.rb +6 -11
- data/lib/cucumber/cli/main.rb +2 -2
- data/lib/cucumber/cli/options.rb +8 -1
- data/lib/cucumber/cli/profile_loader.rb +1 -1
- data/lib/cucumber/core_ext/instance_exec.rb +1 -1
- data/lib/cucumber/encoding.rb +5 -0
- data/lib/cucumber/errors.rb +8 -0
- data/lib/cucumber/file_specs.rb +3 -1
- data/lib/cucumber/filters/activate_steps.rb +33 -0
- data/lib/cucumber/filters/apply_after_hooks.rb +9 -0
- data/lib/cucumber/filters/apply_after_step_hooks.rb +12 -0
- data/lib/cucumber/filters/apply_around_hooks.rb +12 -0
- data/lib/cucumber/filters/apply_before_hooks.rb +9 -0
- data/lib/cucumber/{runtime → filters}/gated_receiver.rb +5 -1
- data/lib/cucumber/filters/prepare_world.rb +45 -0
- data/lib/cucumber/filters/quit.rb +28 -0
- data/lib/cucumber/filters/randomizer.rb +40 -0
- data/lib/cucumber/{runtime → filters}/tag_limits/test_case_index.rb +4 -2
- data/lib/cucumber/{runtime → filters}/tag_limits/verifier.rb +4 -2
- data/lib/cucumber/filters/tag_limits.rb +45 -0
- data/lib/cucumber/filters.rb +9 -0
- data/lib/cucumber/formatter/ansicolor.rb +0 -8
- data/lib/cucumber/formatter/console.rb +37 -20
- data/lib/cucumber/formatter/debug.rb +1 -8
- data/lib/cucumber/formatter/fanout.rb +27 -0
- data/lib/cucumber/formatter/gherkin_formatter_adapter.rb +10 -9
- data/lib/cucumber/formatter/html.rb +31 -6
- data/lib/cucumber/formatter/ignore_missing_messages.rb +20 -0
- data/lib/cucumber/formatter/junit.rb +97 -2
- data/lib/cucumber/formatter/legacy_api/adapter.rb +1060 -0
- data/lib/cucumber/formatter/legacy_api/ast.rb +376 -0
- data/lib/cucumber/formatter/legacy_api/results.rb +51 -0
- data/lib/cucumber/formatter/legacy_api/runtime_facade.rb +30 -0
- data/lib/cucumber/formatter/pretty.rb +14 -0
- data/lib/cucumber/formatter/progress.rb +10 -0
- data/lib/cucumber/formatter/rerun.rb +14 -88
- data/lib/cucumber/hooks.rb +97 -0
- data/lib/cucumber/language_support/language_methods.rb +0 -54
- data/lib/cucumber/multiline_argument/data_table.rb +41 -29
- data/lib/cucumber/platform.rb +3 -3
- data/lib/cucumber/project_initializer.rb +43 -0
- data/lib/cucumber/rb_support/rb_hook.rb +2 -2
- data/lib/cucumber/rb_support/rb_step_definition.rb +11 -2
- data/lib/cucumber/rb_support/rb_transform.rb +3 -1
- data/lib/cucumber/rb_support/rb_world.rb +2 -2
- data/lib/cucumber/rb_support/snippet.rb +1 -1
- data/lib/cucumber/rspec/doubles.rb +1 -1
- data/lib/cucumber/running_test_case.rb +115 -0
- data/lib/cucumber/runtime/after_hooks.rb +24 -0
- data/lib/cucumber/runtime/before_hooks.rb +23 -0
- data/lib/cucumber/runtime/for_programming_languages.rb +4 -8
- data/lib/cucumber/runtime/step_hooks.rb +22 -0
- data/lib/cucumber/runtime/support_code.rb +70 -5
- data/lib/cucumber/runtime.rb +56 -112
- data/lib/cucumber/step_match.rb +26 -2
- data/lib/cucumber.rb +7 -3
- data/spec/cucumber/cli/configuration_spec.rb +16 -1
- data/spec/cucumber/cli/profile_loader_spec.rb +10 -0
- data/spec/cucumber/core_ext/instance_exec_spec.rb +4 -0
- data/spec/cucumber/file_specs_spec.rb +21 -2
- data/spec/cucumber/filters/activate_steps_spec.rb +57 -0
- data/spec/cucumber/{runtime → filters}/gated_receiver_spec.rb +3 -3
- data/spec/cucumber/{runtime → filters}/tag_limits/test_case_index_spec.rb +3 -3
- data/spec/cucumber/{runtime → filters}/tag_limits/verifier_spec.rb +4 -4
- data/spec/cucumber/{runtime/tag_limits/filter_spec.rb → filters/tag_limits_spec.rb} +6 -6
- data/spec/cucumber/formatter/debug_spec.rb +25 -530
- data/spec/cucumber/formatter/html_spec.rb +140 -0
- data/spec/cucumber/formatter/junit_spec.rb +212 -156
- data/spec/cucumber/formatter/legacy_api/adapter_spec.rb +2090 -0
- data/spec/cucumber/formatter/pretty_spec.rb +248 -2
- data/spec/cucumber/formatter/rerun_spec.rb +107 -0
- data/spec/cucumber/formatter/spec_helper.rb +17 -8
- data/spec/cucumber/hooks_spec.rb +30 -0
- data/spec/cucumber/multiline_argument/data_table_spec.rb +53 -47
- data/spec/cucumber/project_initializer_spec.rb +87 -0
- data/spec/cucumber/rb_support/rb_language_spec.rb +2 -2
- data/spec/cucumber/rb_support/rb_step_definition_spec.rb +32 -7
- data/spec/cucumber/rb_support/rb_transform_spec.rb +20 -0
- data/spec/cucumber/rb_support/snippet_spec.rb +6 -6
- data/spec/cucumber/running_test_case_spec.rb +83 -0
- data/spec/cucumber/runtime_spec.rb +1 -5
- data/spec/spec_helper.rb +3 -4
- metadata +149 -107
- data/bin/cuke +0 -60
- data/features/docs/extending_cucumber/formatter_callbacks.feature +0 -370
- data/features/docs/output_from_hooks.feature +0 -128
- data/features/docs/report_called_undefined_steps.feature +0 -57
- data/features/docs/wire_protocol.feature +0 -337
- data/gem_tasks/yard/default/layout/html/bubble_32x32.png +0 -0
- data/gem_tasks/yard/default/layout/html/footer.erb +0 -5
- data/gem_tasks/yard/default/layout/html/index.erb +0 -1
- data/gem_tasks/yard/default/layout/html/layout.erb +0 -25
- data/gem_tasks/yard/default/layout/html/logo.erb +0 -1
- data/gem_tasks/yard/default/layout/html/setup.rb +0 -4
- data/gem_tasks/yard.rake +0 -43
- data/lib/cucumber/mappings.rb +0 -238
- data/lib/cucumber/reports/legacy_formatter.rb +0 -1349
- data/lib/cucumber/runtime/results.rb +0 -64
- data/lib/cucumber/runtime/tag_limits/filter.rb +0 -31
- data/lib/cucumber/runtime/tag_limits.rb +0 -15
- data/spec/cucumber/mappings_spec.rb +0 -180
- data/spec/cucumber/reports/legacy_formatter_spec.rb +0 -1860
- data/spec/cucumber/runtime/results_spec.rb +0 -88
|
@@ -0,0 +1,376 @@
|
|
|
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
|
+
legacy_multiline_arg = if multiline_arg.kind_of?(Core::Ast::EmptyMultilineArgument)
|
|
122
|
+
nil
|
|
123
|
+
else
|
|
124
|
+
step.multiline_arg
|
|
125
|
+
end
|
|
126
|
+
[keyword, step_match, legacy_multiline_arg, status, exception, source_indent, background, file_colon_line]
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
def failed?
|
|
130
|
+
status != :passed
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
def passed?
|
|
134
|
+
status == :passed
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
def dom_id
|
|
138
|
+
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
def actual_keyword(previous_step_keyword = nil)
|
|
142
|
+
step.actual_keyword(previous_step_keyword)
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
def file_colon_line
|
|
146
|
+
location.to_s
|
|
147
|
+
end
|
|
148
|
+
|
|
149
|
+
def backtrace_line
|
|
150
|
+
step_match.backtrace_line
|
|
151
|
+
end
|
|
152
|
+
|
|
153
|
+
def step_invocation
|
|
154
|
+
self
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
private
|
|
158
|
+
|
|
159
|
+
def source_indent
|
|
160
|
+
indent.of(self)
|
|
161
|
+
end
|
|
162
|
+
|
|
163
|
+
def print_step_name(formatter)
|
|
164
|
+
formatter.step_name(
|
|
165
|
+
keyword,
|
|
166
|
+
step_match,
|
|
167
|
+
status,
|
|
168
|
+
source_indent,
|
|
169
|
+
background,
|
|
170
|
+
location.to_s)
|
|
171
|
+
end
|
|
172
|
+
|
|
173
|
+
def print_exception(formatter)
|
|
174
|
+
return unless exception
|
|
175
|
+
raise exception if ENV['FAIL_FAST']
|
|
176
|
+
formatter.exception(exception, status)
|
|
177
|
+
end
|
|
178
|
+
end
|
|
179
|
+
|
|
180
|
+
class StepInvocations < Array
|
|
181
|
+
def failed?
|
|
182
|
+
any?(&:failed?)
|
|
183
|
+
end
|
|
184
|
+
|
|
185
|
+
def passed?
|
|
186
|
+
all?(&:passed?)
|
|
187
|
+
end
|
|
188
|
+
|
|
189
|
+
def status
|
|
190
|
+
return :passed if passed?
|
|
191
|
+
failed_step.status
|
|
192
|
+
end
|
|
193
|
+
|
|
194
|
+
def exception
|
|
195
|
+
failed_step.exception if failed_step
|
|
196
|
+
end
|
|
197
|
+
|
|
198
|
+
private
|
|
199
|
+
|
|
200
|
+
def failed_step
|
|
201
|
+
detect(&:failed?)
|
|
202
|
+
end
|
|
203
|
+
end
|
|
204
|
+
|
|
205
|
+
class DataTableRow
|
|
206
|
+
def initialize(row, line)
|
|
207
|
+
@values = row
|
|
208
|
+
@line = line
|
|
209
|
+
end
|
|
210
|
+
|
|
211
|
+
def dom_id
|
|
212
|
+
"row_#{line}"
|
|
213
|
+
end
|
|
214
|
+
|
|
215
|
+
def accept(formatter)
|
|
216
|
+
formatter.before_table_row(self)
|
|
217
|
+
values.each do |value|
|
|
218
|
+
formatter.before_table_cell(value)
|
|
219
|
+
formatter.table_cell_value(value, status)
|
|
220
|
+
formatter.after_table_cell(value)
|
|
221
|
+
end
|
|
222
|
+
formatter.after_table_row(self)
|
|
223
|
+
end
|
|
224
|
+
|
|
225
|
+
def status
|
|
226
|
+
:skipped
|
|
227
|
+
end
|
|
228
|
+
|
|
229
|
+
def exception
|
|
230
|
+
nil
|
|
231
|
+
end
|
|
232
|
+
|
|
233
|
+
attr_reader :values, :line
|
|
234
|
+
private :values, :line
|
|
235
|
+
end
|
|
236
|
+
|
|
237
|
+
ExampleTableRow = Struct.new(:exception, :status, :cells, :location, :language) do
|
|
238
|
+
def name
|
|
239
|
+
'| ' + cells.join(' | ') + ' |'
|
|
240
|
+
end
|
|
241
|
+
|
|
242
|
+
def failed?
|
|
243
|
+
status == :failed
|
|
244
|
+
end
|
|
245
|
+
|
|
246
|
+
def line
|
|
247
|
+
location.line
|
|
248
|
+
end
|
|
249
|
+
|
|
250
|
+
def keyword
|
|
251
|
+
# This method is only called when used for the scenario name line with
|
|
252
|
+
# the expand option, and on that line the keyword is "Scenario"
|
|
253
|
+
language.keywords('scenario')[0]
|
|
254
|
+
end
|
|
255
|
+
end
|
|
256
|
+
|
|
257
|
+
class LegacyTableRow < DataTableRow
|
|
258
|
+
def accept(formatter)
|
|
259
|
+
formatter.before_table_row(self)
|
|
260
|
+
values.each do |value|
|
|
261
|
+
formatter.before_table_cell(value.value)
|
|
262
|
+
formatter.table_cell_value(value.value, value.status)
|
|
263
|
+
formatter.after_table_cell(value.value)
|
|
264
|
+
end
|
|
265
|
+
formatter.after_table_row(self)
|
|
266
|
+
end
|
|
267
|
+
end
|
|
268
|
+
|
|
269
|
+
Tags = Struct.new(:tags) do
|
|
270
|
+
def accept(formatter)
|
|
271
|
+
formatter.before_tags tags
|
|
272
|
+
tags.each do |tag|
|
|
273
|
+
formatter.tag_name tag.name
|
|
274
|
+
end
|
|
275
|
+
formatter.after_tags tags
|
|
276
|
+
end
|
|
277
|
+
end
|
|
278
|
+
|
|
279
|
+
Scenario = Struct.new(:status, :name, :location) do
|
|
280
|
+
def backtrace_line(step_name = "#{name}", line = self.location.line)
|
|
281
|
+
"#{location.on_line(line)}:in `#{step_name}'"
|
|
282
|
+
end
|
|
283
|
+
|
|
284
|
+
def failed?
|
|
285
|
+
:failed == status
|
|
286
|
+
end
|
|
287
|
+
|
|
288
|
+
def line
|
|
289
|
+
location.line
|
|
290
|
+
end
|
|
291
|
+
end
|
|
292
|
+
|
|
293
|
+
ScenarioOutline = Struct.new(:status, :name, :location) do
|
|
294
|
+
def backtrace_line(step_name = "#{name}", line = self.location.line)
|
|
295
|
+
"#{location.on_line(line)}:in `#{step_name}'"
|
|
296
|
+
end
|
|
297
|
+
|
|
298
|
+
def failed?
|
|
299
|
+
:failed == status
|
|
300
|
+
end
|
|
301
|
+
|
|
302
|
+
def line
|
|
303
|
+
location.line
|
|
304
|
+
end
|
|
305
|
+
end
|
|
306
|
+
|
|
307
|
+
module MultilineArg
|
|
308
|
+
class << self
|
|
309
|
+
def for(node)
|
|
310
|
+
Builder.new(node).result
|
|
311
|
+
end
|
|
312
|
+
end
|
|
313
|
+
|
|
314
|
+
class Builder
|
|
315
|
+
def initialize(node)
|
|
316
|
+
node.describe_to(self)
|
|
317
|
+
end
|
|
318
|
+
|
|
319
|
+
def doc_string(node)
|
|
320
|
+
@result = DocString.new(node)
|
|
321
|
+
end
|
|
322
|
+
|
|
323
|
+
def data_table(node)
|
|
324
|
+
@result = DataTable.new(node)
|
|
325
|
+
end
|
|
326
|
+
|
|
327
|
+
def legacy_table(node)
|
|
328
|
+
@result = LegacyTable.new(node)
|
|
329
|
+
end
|
|
330
|
+
|
|
331
|
+
def result
|
|
332
|
+
@result || Node.new(nil)
|
|
333
|
+
end
|
|
334
|
+
end
|
|
335
|
+
|
|
336
|
+
class DocString < Node
|
|
337
|
+
def accept(formatter)
|
|
338
|
+
formatter.before_multiline_arg node
|
|
339
|
+
formatter.doc_string(node)
|
|
340
|
+
formatter.after_multiline_arg node
|
|
341
|
+
end
|
|
342
|
+
end
|
|
343
|
+
|
|
344
|
+
class DataTable < Cucumber::MultilineArgument::DataTable
|
|
345
|
+
def node
|
|
346
|
+
@ast_table
|
|
347
|
+
end
|
|
348
|
+
|
|
349
|
+
def accept(formatter)
|
|
350
|
+
formatter.before_multiline_arg self
|
|
351
|
+
node.raw.each_with_index do |row, index|
|
|
352
|
+
line = node.location.line + index
|
|
353
|
+
DataTableRow.new(row, line).accept(formatter)
|
|
354
|
+
end
|
|
355
|
+
formatter.after_multiline_arg self
|
|
356
|
+
end
|
|
357
|
+
end
|
|
358
|
+
end
|
|
359
|
+
|
|
360
|
+
class LegacyTable < SimpleDelegator
|
|
361
|
+
def accept(formatter)
|
|
362
|
+
formatter.before_multiline_arg self
|
|
363
|
+
cells_rows.each_with_index do |row, index|
|
|
364
|
+
line = location.line + index
|
|
365
|
+
LegacyTableRow.new(row, line).accept(formatter)
|
|
366
|
+
end
|
|
367
|
+
formatter.after_multiline_arg self
|
|
368
|
+
end
|
|
369
|
+
end
|
|
370
|
+
|
|
371
|
+
Features = Struct.new(:duration)
|
|
372
|
+
|
|
373
|
+
end
|
|
374
|
+
end
|
|
375
|
+
end
|
|
376
|
+
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
|
|
@@ -26,6 +26,8 @@ module Cucumber
|
|
|
26
26
|
@indent = 0
|
|
27
27
|
@prefixes = options[:prefixes] || {}
|
|
28
28
|
@delayed_messages = []
|
|
29
|
+
@previous_step_keyword = nil
|
|
30
|
+
@snippets_input = []
|
|
29
31
|
end
|
|
30
32
|
|
|
31
33
|
def before_features(features)
|
|
@@ -72,6 +74,7 @@ module Cucumber
|
|
|
72
74
|
end
|
|
73
75
|
|
|
74
76
|
def after_feature_element(feature_element)
|
|
77
|
+
print_messages
|
|
75
78
|
@io.puts
|
|
76
79
|
@io.flush
|
|
77
80
|
end
|
|
@@ -83,6 +86,7 @@ module Cucumber
|
|
|
83
86
|
end
|
|
84
87
|
|
|
85
88
|
def after_background(background)
|
|
89
|
+
print_messages
|
|
86
90
|
@in_background = nil
|
|
87
91
|
@io.puts
|
|
88
92
|
@io.flush
|
|
@@ -125,6 +129,7 @@ module Cucumber
|
|
|
125
129
|
def before_step(step)
|
|
126
130
|
@current_step = step
|
|
127
131
|
@indent = 6
|
|
132
|
+
print_messages
|
|
128
133
|
end
|
|
129
134
|
|
|
130
135
|
def before_step_result(keyword, step_match, multiline_arg, status, exception, source_indent, background, file_colon_line)
|
|
@@ -161,6 +166,7 @@ module Cucumber
|
|
|
161
166
|
|
|
162
167
|
def exception(exception, status)
|
|
163
168
|
return if @hide_this_step
|
|
169
|
+
print_messages
|
|
164
170
|
print_exception(exception, status, @indent)
|
|
165
171
|
@io.flush
|
|
166
172
|
end
|
|
@@ -205,6 +211,14 @@ module Cucumber
|
|
|
205
211
|
@io.flush
|
|
206
212
|
end
|
|
207
213
|
|
|
214
|
+
def before_test_case(test_case)
|
|
215
|
+
@previous_step_keyword = nil
|
|
216
|
+
end
|
|
217
|
+
|
|
218
|
+
def after_test_step(test_step, result)
|
|
219
|
+
collect_snippet_data(test_step, result)
|
|
220
|
+
end
|
|
221
|
+
|
|
208
222
|
private
|
|
209
223
|
|
|
210
224
|
def print_feature_element_name(keyword, name, file_colon_line, source_indent)
|
|
@@ -11,6 +11,8 @@ module Cucumber
|
|
|
11
11
|
|
|
12
12
|
def initialize(runtime, path_or_io, options)
|
|
13
13
|
@runtime, @io, @options = runtime, ensure_io(path_or_io, "progress"), options
|
|
14
|
+
@previous_step_keyword = nil
|
|
15
|
+
@snippets_input = []
|
|
14
16
|
end
|
|
15
17
|
|
|
16
18
|
def before_features(features)
|
|
@@ -64,6 +66,14 @@ module Cucumber
|
|
|
64
66
|
@exception_raised = true
|
|
65
67
|
end
|
|
66
68
|
|
|
69
|
+
def before_test_case(test_case)
|
|
70
|
+
@previous_step_keyword = nil
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
def after_test_step(test_step, result)
|
|
74
|
+
collect_snippet_data(test_step, result)
|
|
75
|
+
end
|
|
76
|
+
|
|
67
77
|
private
|
|
68
78
|
|
|
69
79
|
def print_summary(features)
|
|
@@ -2,106 +2,32 @@ require 'cucumber/formatter/io'
|
|
|
2
2
|
|
|
3
3
|
module Cucumber
|
|
4
4
|
module Formatter
|
|
5
|
-
# The formatter used for <tt>--format rerun</tt>
|
|
6
|
-
#
|
|
7
|
-
# This formatter keeps track of all failing features and print out their location.
|
|
8
|
-
# Example:
|
|
9
|
-
#
|
|
10
|
-
# features/foo.feature:34 features/bar.feature:11:76:81
|
|
11
|
-
#
|
|
12
|
-
# This formatter is used by AutoTest - it will use the output to decide what
|
|
13
|
-
# to run the next time, simply passing the output string on the command line.
|
|
14
|
-
#
|
|
15
5
|
class Rerun
|
|
16
|
-
include Io
|
|
6
|
+
include Formatter::Io
|
|
17
7
|
|
|
18
8
|
def initialize(runtime, path_or_io, options)
|
|
19
9
|
@io = ensure_io(path_or_io, "rerun")
|
|
20
|
-
@
|
|
21
|
-
@file_names = []
|
|
22
|
-
@file_colon_lines = Hash.new{|h,k| h[k] = []}
|
|
10
|
+
@failures = {}
|
|
23
11
|
end
|
|
24
12
|
|
|
25
|
-
def
|
|
26
|
-
|
|
27
|
-
@file
|
|
28
|
-
|
|
29
|
-
if @file.include?(' ')
|
|
30
|
-
warn("Filenames with spaces like '#{@file}' cause unexpected behaviour from the rerun formatter.")
|
|
31
|
-
end
|
|
13
|
+
def after_test_case(test_case, result)
|
|
14
|
+
return if result.passed?
|
|
15
|
+
@failures[test_case.location.file] ||= []
|
|
16
|
+
@failures[test_case.location.file] << test_case.location.line
|
|
32
17
|
end
|
|
33
18
|
|
|
34
|
-
def
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
@io.print ' '
|
|
38
|
-
end
|
|
39
|
-
@io.print "#{@file}:#{@lines.join(':')}"
|
|
40
|
-
@io.flush
|
|
41
|
-
end
|
|
19
|
+
def done
|
|
20
|
+
return if @failures.empty?
|
|
21
|
+
@io.print file_failures.join(' ')
|
|
42
22
|
end
|
|
43
23
|
|
|
44
|
-
|
|
45
|
-
|
|
24
|
+
[:before_test_case, :before_test_step, :after_test_step].each do |method|
|
|
25
|
+
define_method(method) { |*| }
|
|
46
26
|
end
|
|
47
27
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
def after_feature_element(feature_element)
|
|
53
|
-
if (@rerun || feature_element.failed? || feature_element.status == :skipped) && !(Cucumber::Reports::Legacy::Ast::ScenarioOutline === feature_element)
|
|
54
|
-
@lines << feature_element.line
|
|
55
|
-
end
|
|
56
|
-
end
|
|
57
|
-
|
|
58
|
-
def after_table_row(table_row)
|
|
59
|
-
return unless @in_examples and Cucumber::Reports::LegacyExampleTableRow === table_row
|
|
60
|
-
unless @header_row
|
|
61
|
-
if table_row.failed? || table_row.status == :skipped
|
|
62
|
-
@rerun = true
|
|
63
|
-
@lines << table_row.line
|
|
64
|
-
end
|
|
65
|
-
end
|
|
66
|
-
|
|
67
|
-
@header_row = false if @header_row
|
|
68
|
-
end
|
|
69
|
-
|
|
70
|
-
def before_examples(*args)
|
|
71
|
-
@header_row = true
|
|
72
|
-
@in_examples = true
|
|
73
|
-
@current_example_line = nil
|
|
74
|
-
end
|
|
75
|
-
|
|
76
|
-
def after_examples(*args)
|
|
77
|
-
@in_examples = false
|
|
78
|
-
if @current_example_line and @rerun
|
|
79
|
-
@lines << @current_example_line
|
|
80
|
-
end
|
|
81
|
-
end
|
|
82
|
-
|
|
83
|
-
def before_table_row(table_row)
|
|
84
|
-
return unless @in_examples
|
|
85
|
-
end
|
|
86
|
-
|
|
87
|
-
def step_name(keyword, step_match, status, source_indent, background, file_colon_line)
|
|
88
|
-
@rerun = true if [:failed, :pending, :undefined].index(status)
|
|
89
|
-
end
|
|
90
|
-
|
|
91
|
-
def scenario_name(keyword, name, file_colon_line, source_indent)
|
|
92
|
-
return unless @in_examples
|
|
93
|
-
if @current_example_line and @rerun
|
|
94
|
-
@lines << @current_example_line
|
|
95
|
-
end
|
|
96
|
-
@rerun = false
|
|
97
|
-
@current_example_line = file_colon_line.split(':')[1]
|
|
98
|
-
end
|
|
99
|
-
|
|
100
|
-
private
|
|
101
|
-
|
|
102
|
-
def after_first_time
|
|
103
|
-
yield if @not_first_time
|
|
104
|
-
@not_first_time = true
|
|
28
|
+
private
|
|
29
|
+
def file_failures
|
|
30
|
+
@failures.map { |file, lines| [file, lines].join(':') }
|
|
105
31
|
end
|
|
106
32
|
end
|
|
107
33
|
end
|