cucumber 11.1.0 → 12.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/VERSION +1 -1
- data/lib/cucumber/cli/configuration.rb +0 -6
- data/lib/cucumber/cli/options.rb +0 -16
- data/lib/cucumber/configuration.rb +5 -5
- data/lib/cucumber/errors.rb +43 -23
- data/lib/cucumber/events/attach_called.rb +28 -0
- data/lib/cucumber/events/envelope.rb +2 -2
- data/lib/cucumber/events/gherkin_source_parsed.rb +1 -3
- data/lib/cucumber/events/gherkin_source_read.rb +1 -1
- data/lib/cucumber/events/hook_test_step_created.rb +1 -3
- data/lib/cucumber/events/step_activated.rb +1 -1
- data/lib/cucumber/events/step_definition_registered.rb +1 -3
- data/lib/cucumber/events/test_case_created.rb +1 -1
- data/lib/cucumber/events/test_case_finished.rb +1 -1
- data/lib/cucumber/events/test_case_ready.rb +1 -1
- data/lib/cucumber/events/test_case_started.rb +1 -3
- data/lib/cucumber/events/test_run_finished.rb +1 -1
- data/lib/cucumber/events/test_run_hook_finished.rb +1 -1
- data/lib/cucumber/events/test_run_hook_started.rb +1 -3
- data/lib/cucumber/events/test_run_started.rb +1 -3
- data/lib/cucumber/events/test_step_created.rb +1 -3
- data/lib/cucumber/events/test_step_finished.rb +1 -3
- data/lib/cucumber/events/test_step_started.rb +1 -3
- data/lib/cucumber/events/undefined_parameter_type.rb +1 -1
- data/lib/cucumber/events.rb +7 -2
- data/lib/cucumber/filters/retry.rb +7 -22
- data/lib/cucumber/formatter/console.rb +5 -5
- data/lib/cucumber/formatter/console_counts.rb +5 -3
- data/lib/cucumber/formatter/console_issues.rb +3 -3
- data/lib/cucumber/formatter/duration_extractor.rb +0 -2
- data/lib/cucumber/formatter/fail_fast.rb +2 -2
- data/lib/cucumber/formatter/html.rb +10 -6
- data/lib/cucumber/formatter/json.rb +10 -8
- data/lib/cucumber/formatter/junit.rb +3 -3
- data/lib/cucumber/formatter/message.rb +1 -5
- data/lib/cucumber/formatter/message_builder.rb +39 -147
- data/lib/cucumber/formatter/message_handlers.rb +13 -0
- data/lib/cucumber/formatter/pretty.rb +7 -6
- data/lib/cucumber/formatter/progress.rb +1 -0
- data/lib/cucumber/formatter/rerun.rb +15 -42
- data/lib/cucumber/formatter/summary.rb +15 -1
- data/lib/cucumber/glue/hook.rb +0 -1
- data/lib/cucumber/glue/multiple_world.rb +26 -0
- data/lib/cucumber/glue/nil_world.rb +12 -0
- data/lib/cucumber/glue/proto_world.rb +4 -5
- data/lib/cucumber/glue/registry_and_more.rb +15 -32
- data/lib/cucumber/multiline_argument/data_table.rb +5 -7
- data/lib/cucumber/retry_policy.rb +27 -0
- data/lib/cucumber/rspec/doubles.rb +1 -7
- data/lib/cucumber/runtime/meta_message_builder.rb +1 -1
- data/lib/cucumber/runtime/user_interface.rb +18 -3
- data/lib/cucumber/runtime.rb +34 -53
- metadata +53 -26
- data/lib/cucumber/events/base.rb +0 -25
- data/lib/cucumber/formatter/fanout.rb +0 -28
- data/lib/cucumber/query.rb +0 -273
- data/lib/cucumber/repository.rb +0 -136
|
@@ -22,6 +22,7 @@ module Cucumber
|
|
|
22
22
|
config.on_event :test_step_started, &method(:on_test_step_started)
|
|
23
23
|
config.on_event :test_step_finished, &method(:on_test_step_finished)
|
|
24
24
|
config.on_event :test_run_finished, &method(:on_test_run_finished)
|
|
25
|
+
config.on_event :attach_called, &method(:on_attach_called)
|
|
25
26
|
end
|
|
26
27
|
|
|
27
28
|
def on_test_case_started(event)
|
|
@@ -87,18 +88,19 @@ module Cucumber
|
|
|
87
88
|
@io.write(JSON.pretty_generate(@feature_hashes))
|
|
88
89
|
end
|
|
89
90
|
|
|
90
|
-
def
|
|
91
|
-
if
|
|
92
|
-
test_step_output << src
|
|
91
|
+
def on_attach_called(event)
|
|
92
|
+
if event.media_type == 'text/x.cucumber.log+plain'
|
|
93
|
+
test_step_output << event.src
|
|
93
94
|
return
|
|
94
95
|
end
|
|
95
|
-
if
|
|
96
|
-
|
|
97
|
-
data = src
|
|
96
|
+
if event.media_type =~ /;base64$/
|
|
97
|
+
media_type = event.media_type[0..-8]
|
|
98
|
+
data = event.src
|
|
98
99
|
else
|
|
99
|
-
data = encode64(src)
|
|
100
|
+
data = encode64(event.src)
|
|
101
|
+
media_type = event.media_type
|
|
100
102
|
end
|
|
101
|
-
test_step_embeddings << { mime_type:
|
|
103
|
+
test_step_embeddings << { mime_type: media_type, data: data }
|
|
102
104
|
end
|
|
103
105
|
|
|
104
106
|
private
|
|
@@ -53,7 +53,7 @@ module Cucumber
|
|
|
53
53
|
def on_test_step_finished(event)
|
|
54
54
|
return if @failing_test_step
|
|
55
55
|
|
|
56
|
-
@failing_test_step = event.test_step unless event.result.ok?
|
|
56
|
+
@failing_test_step = event.test_step unless event.result.ok?
|
|
57
57
|
end
|
|
58
58
|
|
|
59
59
|
def on_test_case_finished(event)
|
|
@@ -109,7 +109,7 @@ module Cucumber
|
|
|
109
109
|
scenario_source = @ast_lookup.scenario_source(test_case)
|
|
110
110
|
keyword = scenario_source.type == :Scenario ? scenario_source.scenario.keyword : scenario_source.scenario_outline.keyword
|
|
111
111
|
output = "#{keyword}: #{scenario}\n\n"
|
|
112
|
-
return output if result.ok?
|
|
112
|
+
return output if result.ok?
|
|
113
113
|
|
|
114
114
|
if scenario_source.type == :Scenario
|
|
115
115
|
if @failing_test_step
|
|
@@ -138,7 +138,7 @@ module Cucumber
|
|
|
138
138
|
testcase_attributes = get_testcase_attributes(classname, name, duration, filename)
|
|
139
139
|
|
|
140
140
|
@current_feature_data[:builder].testcase(testcase_attributes) do
|
|
141
|
-
if !result.passed? && result.ok?
|
|
141
|
+
if !result.passed? && result.ok?
|
|
142
142
|
@current_feature_data[:builder].skipped
|
|
143
143
|
@current_feature_data[:skipped] += 1
|
|
144
144
|
elsif !result.passed?
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
require 'cucumber/query'
|
|
3
|
+
require_relative 'io'
|
|
5
4
|
|
|
6
5
|
module Cucumber
|
|
7
6
|
module Formatter
|
|
@@ -11,14 +10,11 @@ module Cucumber
|
|
|
11
10
|
|
|
12
11
|
def initialize(config)
|
|
13
12
|
@io = ensure_io(config.out_stream, config.error_stream)
|
|
14
|
-
@repository = Cucumber::Repository.new
|
|
15
|
-
@query = Cucumber::Query.new(@repository)
|
|
16
13
|
config.on_event :envelope, &method(:output_envelope)
|
|
17
14
|
end
|
|
18
15
|
|
|
19
16
|
def output_envelope(event)
|
|
20
17
|
envelope = event.envelope
|
|
21
|
-
@repository.update(envelope)
|
|
22
18
|
@io.write(envelope.to_json)
|
|
23
19
|
@io.write("\n")
|
|
24
20
|
end
|
|
@@ -3,14 +3,17 @@
|
|
|
3
3
|
require 'base64'
|
|
4
4
|
require 'json'
|
|
5
5
|
|
|
6
|
-
require 'cucumber/formatter/backtrace_filter'
|
|
7
6
|
require 'cucumber/query'
|
|
8
7
|
|
|
8
|
+
require_relative 'backtrace_filter'
|
|
9
|
+
require_relative 'message_handlers'
|
|
10
|
+
|
|
9
11
|
module Cucumber
|
|
10
12
|
module Formatter
|
|
11
13
|
class MessageBuilder
|
|
12
14
|
include Cucumber::Messages::Helpers::TimeConversion
|
|
13
15
|
include Io
|
|
16
|
+
include MessageHandlers
|
|
14
17
|
include Console
|
|
15
18
|
|
|
16
19
|
def initialize(config)
|
|
@@ -20,8 +23,7 @@ module Cucumber
|
|
|
20
23
|
|
|
21
24
|
@test_run_started_id = config.test_run_started_id
|
|
22
25
|
|
|
23
|
-
# Fake Query objects
|
|
24
|
-
@test_case_by_step_id = {}
|
|
26
|
+
# Fake Query objects - used to build specific parts of the messages defined inside handlers
|
|
25
27
|
@pickle_id_by_test_case_id = {}
|
|
26
28
|
@pickle_id_step_by_test_step_id = {}
|
|
27
29
|
@hook_id_by_test_step_id = {}
|
|
@@ -30,56 +32,60 @@ module Cucumber
|
|
|
30
32
|
|
|
31
33
|
# Ensure all handlers for events occur after all ivars are instantiated
|
|
32
34
|
|
|
33
|
-
config.on_event :gherkin_source_parsed, &method(:on_gherkin_source_parsed)
|
|
34
|
-
|
|
35
35
|
config.on_event :hook_test_step_created, &method(:on_hook_test_step_created)
|
|
36
36
|
|
|
37
37
|
config.on_event :step_activated, &method(:on_step_activated)
|
|
38
38
|
|
|
39
39
|
config.on_event :test_case_created, &method(:on_test_case_created)
|
|
40
40
|
config.on_event :test_case_ready, &method(:on_test_case_ready)
|
|
41
|
-
config.on_event :test_case_started, &method(:on_test_case_started)
|
|
42
|
-
config.on_event :test_case_finished, &method(:on_test_case_finished)
|
|
43
41
|
|
|
44
42
|
config.on_event :test_run_started, &method(:on_test_run_started)
|
|
45
43
|
config.on_event :test_run_finished, &method(:on_test_run_finished)
|
|
46
44
|
|
|
47
45
|
config.on_event :test_step_created, &method(:on_test_step_created)
|
|
48
|
-
config.on_event :test_step_started, &method(:on_test_step_started)
|
|
49
46
|
config.on_event :test_step_finished, &method(:on_test_step_finished)
|
|
50
47
|
|
|
48
|
+
config.on_event :attach_called, &method(:on_attach_called)
|
|
51
49
|
config.on_event :envelope, &method(:on_envelope)
|
|
52
50
|
end
|
|
53
51
|
|
|
54
52
|
def on_envelope(event)
|
|
55
|
-
@
|
|
53
|
+
@repository.update(event.envelope)
|
|
54
|
+
store_current_test_run_hook_started_id(event)
|
|
55
|
+
@current_test_step_id = event.envelope.test_step_started.test_step_id if event.envelope.test_step_started
|
|
56
|
+
return unless event.envelope.test_case_started
|
|
57
|
+
|
|
58
|
+
@current_test_case_started_id = event.envelope.test_case_started.id
|
|
59
|
+
@current_test_run_hook_started_id = nil
|
|
56
60
|
end
|
|
57
61
|
|
|
58
|
-
def
|
|
62
|
+
def on_attach_called(event)
|
|
59
63
|
attachment_data =
|
|
60
64
|
if @current_test_run_hook_started_id.nil?
|
|
61
65
|
{
|
|
62
66
|
test_step_id: @current_test_step_id,
|
|
63
67
|
test_case_started_id: @current_test_case_started_id,
|
|
64
|
-
media_type: media_type,
|
|
65
|
-
file_name: filename,
|
|
68
|
+
media_type: event.media_type,
|
|
69
|
+
file_name: event.filename,
|
|
66
70
|
timestamp: time_to_timestamp(Time.now)
|
|
67
71
|
}
|
|
68
72
|
else
|
|
69
73
|
{
|
|
70
74
|
test_run_hook_started_id: @current_test_run_hook_started_id,
|
|
71
|
-
media_type: media_type,
|
|
72
|
-
file_name: filename,
|
|
75
|
+
media_type: event.media_type,
|
|
76
|
+
file_name: event.filename,
|
|
73
77
|
timestamp: time_to_timestamp(Time.now)
|
|
74
78
|
}
|
|
75
79
|
end
|
|
76
80
|
|
|
81
|
+
streamed_file = event.src.encoding == Encoding::BINARY
|
|
82
|
+
|
|
77
83
|
if streamed_file
|
|
78
84
|
attachment_data[:content_encoding] = Cucumber::Messages::AttachmentContentEncoding::BASE64
|
|
79
|
-
attachment_data[:body] = Base64.strict_encode64(src)
|
|
85
|
+
attachment_data[:body] = Base64.strict_encode64(event.src)
|
|
80
86
|
else
|
|
81
87
|
attachment_data[:content_encoding] = Cucumber::Messages::AttachmentContentEncoding::IDENTITY
|
|
82
|
-
attachment_data[:body] = src.is_a?(Hash) ? src.to_json : src
|
|
88
|
+
attachment_data[:body] = event.src.is_a?(Hash) ? event.src.to_json : event.src
|
|
83
89
|
end
|
|
84
90
|
|
|
85
91
|
message = Cucumber::Messages::Envelope.new(attachment: Cucumber::Messages::Attachment.new(**attachment_data))
|
|
@@ -88,28 +94,31 @@ module Cucumber
|
|
|
88
94
|
|
|
89
95
|
private
|
|
90
96
|
|
|
91
|
-
def on_gherkin_source_parsed(_event)
|
|
92
|
-
# TODO: Handle GherkinSourceParsed
|
|
93
|
-
end
|
|
94
|
-
|
|
95
97
|
def on_hook_test_step_created(event)
|
|
98
|
+
# Set iVar value for `hook_id`
|
|
96
99
|
@hook_id_by_test_step_id[event.test_step.id] = event.hook.id
|
|
97
100
|
end
|
|
98
101
|
|
|
99
102
|
def on_step_activated(event)
|
|
103
|
+
# Add/Update iVar value for `step_definition_ids...`
|
|
100
104
|
@step_definition_ids_by_test_step_id[event.test_step.id] << event.step_match.step_definition.id
|
|
105
|
+
# Add/Update iVar value for `step_match_arguments...`
|
|
101
106
|
@step_match_arguments_by_test_step_id[event.test_step.id] = event.step_match.step_arguments
|
|
102
107
|
end
|
|
103
108
|
|
|
104
109
|
def on_test_case_created(event)
|
|
110
|
+
# Set iVar value for `pickle_id`
|
|
105
111
|
@pickle_id_by_test_case_id[event.test_case.id] = event.pickle.id
|
|
106
112
|
end
|
|
107
113
|
|
|
108
114
|
def on_test_case_ready(event)
|
|
115
|
+
# Use iVar value for `pickle_id`
|
|
116
|
+
pickle_id = @pickle_id_by_test_case_id.fetch(event.test_case.id)
|
|
117
|
+
|
|
109
118
|
message = Cucumber::Messages::Envelope.new(
|
|
110
119
|
test_case: Cucumber::Messages::TestCase.new(
|
|
111
120
|
id: event.test_case.id,
|
|
112
|
-
pickle_id:
|
|
121
|
+
pickle_id: pickle_id,
|
|
113
122
|
test_steps: event.test_case.test_steps.map { |step| test_step_to_message(step) },
|
|
114
123
|
test_run_started_id: @test_run_started_id
|
|
115
124
|
)
|
|
@@ -121,55 +130,6 @@ module Cucumber
|
|
|
121
130
|
@config.event_bus.envelope(message)
|
|
122
131
|
end
|
|
123
132
|
|
|
124
|
-
def on_test_case_started(event)
|
|
125
|
-
# For any new test_case_started events, we must ALWAYS generate a new id for a new run
|
|
126
|
-
@current_test_case_started_id = @config.id_generator.new_id
|
|
127
|
-
@current_test_run_hook_started_id = nil
|
|
128
|
-
|
|
129
|
-
find_all_test_case_started_by_test_case_id =
|
|
130
|
-
@repository.test_case_started_by_id
|
|
131
|
-
.values
|
|
132
|
-
.select { |test_case_started| test_case_started.test_case_id == event.test_case.id }
|
|
133
|
-
|
|
134
|
-
# If no TestCaseStarted messages exist. We must be on attempt 1 (Hence the .to_i casting for a `nil` value)
|
|
135
|
-
attempts_previously_made = find_all_test_case_started_by_test_case_id.map(&:attempt).max.to_i
|
|
136
|
-
|
|
137
|
-
message = Cucumber::Messages::Envelope.new(
|
|
138
|
-
test_case_started: Cucumber::Messages::TestCaseStarted.new(
|
|
139
|
-
id: @current_test_case_started_id,
|
|
140
|
-
test_case_id: event.test_case.id,
|
|
141
|
-
timestamp: time_to_timestamp(Time.now),
|
|
142
|
-
attempt: attempts_previously_made + 1
|
|
143
|
-
)
|
|
144
|
-
)
|
|
145
|
-
|
|
146
|
-
@config.event_bus.envelope(message)
|
|
147
|
-
@repository.update(message)
|
|
148
|
-
end
|
|
149
|
-
|
|
150
|
-
def on_test_case_finished(event)
|
|
151
|
-
test_case_started_id =
|
|
152
|
-
@repository.test_case_started_by_id
|
|
153
|
-
.values
|
|
154
|
-
.detect { |test_case_started_message| test_case_started_message.test_case_id == event.test_case.id }
|
|
155
|
-
.id
|
|
156
|
-
|
|
157
|
-
test_case_started_message = @repository.test_case_started_by_id[test_case_started_id]
|
|
158
|
-
max_attempts = @config.retry_attempts
|
|
159
|
-
retries_attempted = test_case_started_message.attempt - 1
|
|
160
|
-
will_be_retried = event.result.failed? && (retries_attempted < max_attempts)
|
|
161
|
-
|
|
162
|
-
message = Cucumber::Messages::Envelope.new(
|
|
163
|
-
test_case_finished: Cucumber::Messages::TestCaseFinished.new(
|
|
164
|
-
test_case_started_id: test_case_started_id,
|
|
165
|
-
timestamp: time_to_timestamp(Time.now),
|
|
166
|
-
will_be_retried: will_be_retried
|
|
167
|
-
)
|
|
168
|
-
)
|
|
169
|
-
|
|
170
|
-
@config.event_bus.envelope(message)
|
|
171
|
-
end
|
|
172
|
-
|
|
173
133
|
def on_test_run_started(*)
|
|
174
134
|
message = Cucumber::Messages::Envelope.new(
|
|
175
135
|
test_run_started: Cucumber::Messages::TestRunStarted.new(
|
|
@@ -194,71 +154,14 @@ module Cucumber
|
|
|
194
154
|
end
|
|
195
155
|
|
|
196
156
|
def on_test_step_created(event)
|
|
157
|
+
# Set iVar value for `pickle_id_step_...`
|
|
197
158
|
@pickle_id_step_by_test_step_id[event.test_step.id] = event.pickle_step.id
|
|
159
|
+
# Set iVar value for `step_definition_ids...`
|
|
198
160
|
@step_definition_ids_by_test_step_id[event.test_step.id] = []
|
|
199
161
|
end
|
|
200
162
|
|
|
201
|
-
def on_test_step_started(event)
|
|
202
|
-
@current_test_step_id = event.test_step.id
|
|
203
|
-
find_test_case_by_step_id =
|
|
204
|
-
@repository.test_case_by_id
|
|
205
|
-
.values
|
|
206
|
-
.detect { |test_case_message| test_case_message.test_steps.any? { |step_message| step_message.id == event.test_step.id } }
|
|
207
|
-
|
|
208
|
-
find_test_case_started_by_test_case =
|
|
209
|
-
@repository.test_case_started_by_id
|
|
210
|
-
.values
|
|
211
|
-
.select { |test_case_started_message| test_case_started_message.test_case_id == find_test_case_by_step_id.id }
|
|
212
|
-
.max_by(&:attempt)
|
|
213
|
-
|
|
214
|
-
message = Cucumber::Messages::Envelope.new(
|
|
215
|
-
test_step_started: Cucumber::Messages::TestStepStarted.new(
|
|
216
|
-
test_step_id: event.test_step.id,
|
|
217
|
-
test_case_started_id: find_test_case_started_by_test_case.id,
|
|
218
|
-
timestamp: time_to_timestamp(Time.now)
|
|
219
|
-
)
|
|
220
|
-
)
|
|
221
|
-
|
|
222
|
-
@config.event_bus.envelope(message)
|
|
223
|
-
end
|
|
224
|
-
|
|
225
163
|
def on_test_step_finished(event)
|
|
226
|
-
find_test_case_by_step_id =
|
|
227
|
-
@repository.test_case_by_id
|
|
228
|
-
.values
|
|
229
|
-
.detect { |test_case_message| test_case_message.test_steps.any? { |step_message| step_message.id == event.test_step.id } }
|
|
230
|
-
|
|
231
|
-
find_test_case_started_by_test_case =
|
|
232
|
-
@repository.test_case_started_by_id
|
|
233
|
-
.values
|
|
234
|
-
.select { |test_case_started_message| test_case_started_message.test_case_id == find_test_case_by_step_id.id }
|
|
235
|
-
.max_by(&:attempt)
|
|
236
|
-
|
|
237
|
-
result = event.result.with_filtered_backtrace(Cucumber::Formatter::BacktraceFilter)
|
|
238
|
-
result_message = result.to_message
|
|
239
|
-
if result.failed? || result.pending?
|
|
240
|
-
message_element = result.failed? ? result.exception : result
|
|
241
|
-
|
|
242
|
-
result_message = Cucumber::Messages::TestStepResult.new(
|
|
243
|
-
status: result_message.status,
|
|
244
|
-
duration: result_message.duration,
|
|
245
|
-
message: create_error_message(message_element),
|
|
246
|
-
exception: create_exception_object(result, message_element)
|
|
247
|
-
)
|
|
248
|
-
end
|
|
249
|
-
|
|
250
164
|
output_snippet_envelope(event)
|
|
251
|
-
|
|
252
|
-
message = Cucumber::Messages::Envelope.new(
|
|
253
|
-
test_step_finished: Cucumber::Messages::TestStepFinished.new(
|
|
254
|
-
test_step_id: event.test_step.id,
|
|
255
|
-
test_case_started_id: find_test_case_started_by_test_case.id,
|
|
256
|
-
test_step_result: result_message,
|
|
257
|
-
timestamp: time_to_timestamp(Time.now)
|
|
258
|
-
)
|
|
259
|
-
)
|
|
260
|
-
|
|
261
|
-
@config.event_bus.envelope(message)
|
|
262
165
|
end
|
|
263
166
|
|
|
264
167
|
def output_snippet_envelope(event)
|
|
@@ -305,8 +208,10 @@ module Cucumber
|
|
|
305
208
|
|
|
306
209
|
Cucumber::Messages::TestStep.new(
|
|
307
210
|
id: step.id,
|
|
211
|
+
# Use iVar value for `pickle_id_step_...`
|
|
308
212
|
pickle_step_id: @pickle_id_step_by_test_step_id[step.id],
|
|
309
|
-
step_definition_ids
|
|
213
|
+
# Use iVar value for `step_definition_ids...`
|
|
214
|
+
step_definition_ids: @step_definition_ids_by_test_step_id.fetch(step.id),
|
|
310
215
|
step_match_arguments_lists: step_match_arguments_lists(step)
|
|
311
216
|
)
|
|
312
217
|
end
|
|
@@ -314,6 +219,7 @@ module Cucumber
|
|
|
314
219
|
def hook_step_to_message(step)
|
|
315
220
|
Cucumber::Messages::TestStep.new(
|
|
316
221
|
id: step.id,
|
|
222
|
+
# Use iVar value for `hook_id`
|
|
317
223
|
hook_id: @hook_id_by_test_step_id[step.id]
|
|
318
224
|
)
|
|
319
225
|
end
|
|
@@ -328,7 +234,9 @@ module Cucumber
|
|
|
328
234
|
end
|
|
329
235
|
|
|
330
236
|
def step_match_arguments(step)
|
|
331
|
-
|
|
237
|
+
# Use iVar value for `step_match_arguments...`
|
|
238
|
+
step_matches = @step_match_arguments_by_test_step_id[step.id]
|
|
239
|
+
step_matches&.map do |argument|
|
|
332
240
|
Cucumber::Messages::StepMatchArgument.new(
|
|
333
241
|
group: argument_group_to_message(argument.group),
|
|
334
242
|
parameter_type_name: parameter_type_name(argument)
|
|
@@ -364,22 +272,6 @@ module Cucumber
|
|
|
364
272
|
stack_trace: message_element.backtrace.join("\n")
|
|
365
273
|
)
|
|
366
274
|
end
|
|
367
|
-
|
|
368
|
-
def fake_query_hook_id(test_step)
|
|
369
|
-
@hook_id_by_test_step_id.fetch(test_step.id)
|
|
370
|
-
end
|
|
371
|
-
|
|
372
|
-
def fake_query_pickle_id(test_case)
|
|
373
|
-
@pickle_id_by_test_case_id.fetch(test_case.id)
|
|
374
|
-
end
|
|
375
|
-
|
|
376
|
-
def fake_query_step_definition_ids(test_step)
|
|
377
|
-
@step_definition_ids_by_test_step_id.fetch(test_step.id)
|
|
378
|
-
end
|
|
379
|
-
|
|
380
|
-
def fake_query_step_match_arguments(test_step)
|
|
381
|
-
@step_match_arguments_by_test_step_id.fetch(test_step.id, nil)
|
|
382
|
-
end
|
|
383
275
|
end
|
|
384
276
|
end
|
|
385
277
|
end
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Cucumber
|
|
4
|
+
module Formatter
|
|
5
|
+
# Common Message Handlers to be used across all message-based formatters
|
|
6
|
+
# Designed to work solely with events of type `Envelope`
|
|
7
|
+
module MessageHandlers
|
|
8
|
+
def store_current_test_run_hook_started_id(event)
|
|
9
|
+
@current_test_run_hook_started_id = event.envelope.test_run_hook_started.id if event.envelope.test_run_hook_started
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
end
|
|
@@ -64,6 +64,7 @@ module Cucumber
|
|
|
64
64
|
config.on_event :test_case_finished, &method(:on_test_case_finished)
|
|
65
65
|
config.on_event :test_run_finished, &method(:on_test_run_finished)
|
|
66
66
|
config.on_event :undefined_parameter_type, &method(:collect_undefined_parameter_type_names)
|
|
67
|
+
config.on_event :attach_called, &method(:on_attach_called)
|
|
67
68
|
end
|
|
68
69
|
|
|
69
70
|
def on_gherkin_source_read(event)
|
|
@@ -137,20 +138,20 @@ module Cucumber
|
|
|
137
138
|
print_summary
|
|
138
139
|
end
|
|
139
140
|
|
|
140
|
-
def
|
|
141
|
-
return unless media_type == 'text/x.cucumber.log+plain'
|
|
141
|
+
def on_attach_called(event)
|
|
142
|
+
return unless event.media_type == 'text/x.cucumber.log+plain'
|
|
142
143
|
|
|
143
|
-
if filename
|
|
144
|
-
@test_step_output.push("#{filename}: #{src}")
|
|
144
|
+
if event.filename
|
|
145
|
+
@test_step_output.push("#{event.filename}: #{event.src}")
|
|
145
146
|
else
|
|
146
|
-
@test_step_output.push(src)
|
|
147
|
+
@test_step_output.push(event.src)
|
|
147
148
|
end
|
|
148
149
|
end
|
|
149
150
|
|
|
150
151
|
private
|
|
151
152
|
|
|
152
153
|
def find_exception_to_be_printed(result)
|
|
153
|
-
return nil if result.ok?
|
|
154
|
+
return nil if result.ok?
|
|
154
155
|
|
|
155
156
|
result = result.with_filtered_backtrace(Cucumber::Formatter::BacktraceFilter)
|
|
156
157
|
exception = result.failed? ? result.exception : result
|
|
@@ -36,6 +36,7 @@ module Cucumber
|
|
|
36
36
|
config.on_event :test_case_finished, &method(:on_test_case_finished)
|
|
37
37
|
config.on_event :test_run_finished, &method(:on_test_run_finished)
|
|
38
38
|
config.on_event :undefined_parameter_type, &method(:collect_undefined_parameter_type_names)
|
|
39
|
+
config.on_event :attach_called, &method(:on_attach_called)
|
|
39
40
|
end
|
|
40
41
|
|
|
41
42
|
def on_step_activated(event)
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require 'cucumber/formatter/io'
|
|
4
3
|
require 'cucumber/query'
|
|
5
4
|
|
|
5
|
+
require_relative 'io'
|
|
6
|
+
|
|
6
7
|
module Cucumber
|
|
7
8
|
module Formatter
|
|
8
9
|
class Rerun
|
|
@@ -27,42 +28,20 @@ module Cucumber
|
|
|
27
28
|
def finish_report
|
|
28
29
|
@query.find_all_test_case_started.each do |test_case|
|
|
29
30
|
status = @query.find_most_severe_test_step_result_by(test_case).status
|
|
30
|
-
|
|
31
|
+
|
|
32
|
+
# RULE: Don't log test cases without a pickle (We cannot query their location data to log them)
|
|
31
33
|
pickle = @query.find_pickle_by(test_case)
|
|
32
34
|
next if pickle.nil?
|
|
33
35
|
|
|
34
|
-
# RULE: (
|
|
35
|
-
|
|
36
|
-
|
|
36
|
+
# RULE: Test cases with the worst result as Passing is not considered a failure (Don't log these)
|
|
37
|
+
if status == Cucumber::Messages::TestStepResultStatus::PASSED
|
|
38
|
+
# If the test case in question had already been logged as a failure (And we're retrying), remove the prior reference of failure
|
|
37
39
|
uri_and_location_hash[pickle.uri].delete(pickle.location.line)
|
|
38
40
|
next
|
|
39
41
|
end
|
|
40
42
|
|
|
41
|
-
# RULE:
|
|
42
|
-
|
|
43
|
-
if status == 'UNDEFINED' && !@config.strict.strict?(:undefined)
|
|
44
|
-
Cucumber.deprecate(
|
|
45
|
-
'The strict configuration in cucumber is going away and moving towards a standardised set of behaviours',
|
|
46
|
-
'--strict=undefined',
|
|
47
|
-
'12.0.0'
|
|
48
|
-
)
|
|
49
|
-
next
|
|
50
|
-
end
|
|
51
|
-
|
|
52
|
-
if status == 'PENDING' && !@config.strict.strict?(:pending)
|
|
53
|
-
Cucumber.deprecate(
|
|
54
|
-
'The strict configuration in cucumber is going away and moving towards a standardised set of behaviours',
|
|
55
|
-
'--strict=pending',
|
|
56
|
-
'12.0.0'
|
|
57
|
-
)
|
|
58
|
-
next
|
|
59
|
-
end
|
|
60
|
-
|
|
61
|
-
# RULE: Passing test cases are not considered failures (Don't log these)
|
|
62
|
-
next if passing?(test_case)
|
|
63
|
-
|
|
64
|
-
# RULE: Skipped test cases are not considered failures (on their own, don't log these)
|
|
65
|
-
next if skipped?(test_case)
|
|
43
|
+
# RULE: Test cases with the worst result as Skipped/Pending/Undefined are not considered failures (don't log these)
|
|
44
|
+
next if non_rerunnable_status?(status)
|
|
66
45
|
|
|
67
46
|
# RULE: Before logging a failure, ensure we are not on a retried test case (Don't log a retry multiple times)
|
|
68
47
|
next if test_case.attempt > 1
|
|
@@ -85,18 +64,12 @@ module Cucumber
|
|
|
85
64
|
@uri_and_location_hash ||= Hash.new { |hash, key| hash[key] = Set.new }
|
|
86
65
|
end
|
|
87
66
|
|
|
88
|
-
def
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
most_severe_test_step_result.status == Cucumber::Messages::TestStepResultStatus::PASSED
|
|
95
|
-
end
|
|
96
|
-
|
|
97
|
-
def skipped?(test_case_started)
|
|
98
|
-
most_severe_test_step_result = @query.find_most_severe_test_step_result_by(test_case_started)
|
|
99
|
-
most_severe_test_step_result.status == Cucumber::Messages::TestStepResultStatus::SKIPPED
|
|
67
|
+
def non_rerunnable_status?(status)
|
|
68
|
+
[
|
|
69
|
+
Cucumber::Messages::TestStepResultStatus::SKIPPED,
|
|
70
|
+
Cucumber::Messages::TestStepResultStatus::PENDING,
|
|
71
|
+
Cucumber::Messages::TestStepResultStatus::UNDEFINED
|
|
72
|
+
].include?(status)
|
|
100
73
|
end
|
|
101
74
|
end
|
|
102
75
|
end
|
|
@@ -4,12 +4,13 @@ require 'cucumber/formatter/io'
|
|
|
4
4
|
require 'cucumber/formatter/console'
|
|
5
5
|
require 'cucumber/formatter/console_counts'
|
|
6
6
|
require 'cucumber/formatter/console_issues'
|
|
7
|
+
require 'cucumber/formatter/backtrace_filter'
|
|
7
8
|
require 'cucumber/core/test/result'
|
|
8
9
|
require 'cucumber/formatter/ast_lookup'
|
|
9
10
|
|
|
10
11
|
module Cucumber
|
|
11
12
|
module Formatter
|
|
12
|
-
# Summary formatter, outputting
|
|
13
|
+
# Summary formatter, outputting feature / scenario titles plus failure details
|
|
13
14
|
class Summary
|
|
14
15
|
include Io
|
|
15
16
|
include Console
|
|
@@ -20,6 +21,7 @@ module Cucumber
|
|
|
20
21
|
@ast_lookup = AstLookup.new(config)
|
|
21
22
|
@counts = ConsoleCounts.new(@config)
|
|
22
23
|
@issues = ConsoleIssues.new(@config, @ast_lookup)
|
|
24
|
+
@failed_results = []
|
|
23
25
|
@start_time = Time.now
|
|
24
26
|
|
|
25
27
|
@config.on_event :test_case_started do |event|
|
|
@@ -31,9 +33,14 @@ module Cucumber
|
|
|
31
33
|
print_result event.result
|
|
32
34
|
end
|
|
33
35
|
|
|
36
|
+
@config.on_event :test_step_finished do |event|
|
|
37
|
+
collect_failed_result(event.test_step, event.result)
|
|
38
|
+
end
|
|
39
|
+
|
|
34
40
|
@config.on_event :test_run_finished do |_event|
|
|
35
41
|
duration = Time.now - @start_time
|
|
36
42
|
@io.puts
|
|
43
|
+
print_elements(@failed_results, :failed, 'steps')
|
|
37
44
|
print_statistics(duration, @config, @counts, @issues)
|
|
38
45
|
end
|
|
39
46
|
end
|
|
@@ -61,6 +68,13 @@ module Cucumber
|
|
|
61
68
|
def print_result(result)
|
|
62
69
|
@io.puts format_string(result, result.to_sym)
|
|
63
70
|
end
|
|
71
|
+
|
|
72
|
+
def collect_failed_result(test_step, result)
|
|
73
|
+
return if test_step.hook?
|
|
74
|
+
|
|
75
|
+
result = result.with_filtered_backtrace(Cucumber::Formatter::BacktraceFilter)
|
|
76
|
+
@failed_results << result if result.failed?
|
|
77
|
+
end
|
|
64
78
|
end
|
|
65
79
|
end
|
|
66
80
|
end
|
data/lib/cucumber/glue/hook.rb
CHANGED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Cucumber
|
|
4
|
+
module Glue
|
|
5
|
+
# Raised if there are 2 or more World blocks.
|
|
6
|
+
class MultipleWorld < StandardError
|
|
7
|
+
def initialize(first_proc, second_proc)
|
|
8
|
+
super(error_message(first_proc, second_proc))
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def error_message(first_proc, second_proc)
|
|
12
|
+
<<~MESSAGE
|
|
13
|
+
You can only pass a proc to #World once, but it's happening
|
|
14
|
+
in 2 places:
|
|
15
|
+
#{Glue.backtrace_line(first_proc, 'World')}
|
|
16
|
+
#{Glue.backtrace_line(second_proc, 'World')}
|
|
17
|
+
Use Ruby modules instead to extend your worlds. See the Cucumber::Glue::Dsl#World RDoc
|
|
18
|
+
or http://wiki.github.com/cucumber/cucumber/a-whole-new-world.
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
MESSAGE
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
end
|
|
26
|
+
end
|
|
@@ -93,12 +93,11 @@ module Cucumber
|
|
|
93
93
|
if File.file?(file)
|
|
94
94
|
media_type = MiniMime.lookup_by_filename(file)&.content_type if media_type.nil?
|
|
95
95
|
file = File.read(file, mode: 'rb')
|
|
96
|
-
streamed_file = true
|
|
97
96
|
end
|
|
98
97
|
# We pass in the concept of whether the file is streamed to ensure that the envelope encoding is correct
|
|
99
|
-
super(file, media_type, filename
|
|
98
|
+
super(file, media_type, filename)
|
|
100
99
|
rescue StandardError
|
|
101
|
-
super(file, media_type, filename
|
|
100
|
+
super(file, media_type, filename)
|
|
102
101
|
end
|
|
103
102
|
|
|
104
103
|
# Mark the matched step as pending.
|
|
@@ -155,8 +154,8 @@ module Cucumber
|
|
|
155
154
|
runtime.ask(question, timeout_seconds)
|
|
156
155
|
end
|
|
157
156
|
|
|
158
|
-
define_method(:attach) do |file, media_type, filename
|
|
159
|
-
runtime.attach(file, media_type, filename
|
|
157
|
+
define_method(:attach) do |file, media_type, filename|
|
|
158
|
+
runtime.attach(file, media_type, filename)
|
|
160
159
|
end
|
|
161
160
|
|
|
162
161
|
# Prints the list of modules that are included in the World
|