cucumber 4.0.0.rc.4 → 4.1.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.
@@ -1,21 +1,27 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'cucumber/formatter/http_io'
4
+
3
5
  module Cucumber
4
6
  module Formatter
5
7
  module Io
6
8
  module_function
7
9
 
8
- def ensure_io(path_or_io)
9
- return nil if path_or_io.nil?
10
- return path_or_io if path_or_io.respond_to?(:write)
11
- file = File.open(path_or_io, Cucumber.file_mode('w'))
10
+ def ensure_io(path_or_url_or_io)
11
+ return nil if path_or_url_or_io.nil?
12
+ return path_or_url_or_io if path_or_url_or_io.respond_to?(:write)
13
+ io = if path_or_url_or_io.match(%r{^https?://})
14
+ HTTPIO.open(path_or_url_or_io)
15
+ else
16
+ File.open(path_or_url_or_io, Cucumber.file_mode('w'))
17
+ end
12
18
  at_exit do
13
- unless file.closed?
14
- file.flush
15
- file.close
19
+ unless io.closed?
20
+ io.flush
21
+ io.close
16
22
  end
17
23
  end
18
- file
24
+ io
19
25
  end
20
26
 
21
27
  def ensure_file(path, name)
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'multi_json'
3
+ require 'json'
4
4
  require 'base64'
5
5
  require 'cucumber/formatter/backtrace_filter'
6
6
  require 'cucumber/formatter/io'
@@ -86,7 +86,7 @@ module Cucumber
86
86
  end
87
87
 
88
88
  def on_test_run_finished(_event)
89
- @io.write(MultiJson.dump(@feature_hashes, pretty: true))
89
+ @io.write(JSON.generate(@feature_hashes, pretty: true))
90
90
  end
91
91
 
92
92
  def attach(src, mime_type)
@@ -1,246 +1,22 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'base64'
4
3
  require 'cucumber/formatter/io'
5
- require 'cucumber/formatter/backtrace_filter'
6
- require 'cucumber/formatter/query/hook_by_test_step'
7
- require 'cucumber/formatter/query/pickle_by_test'
8
- require 'cucumber/formatter/query/pickle_step_by_test_step'
9
- require 'cucumber/formatter/query/step_definitions_by_test_step'
10
- require 'cucumber/formatter/query/test_case_started_by_test_case'
4
+ require 'cucumber/formatter/message_builder'
11
5
 
12
6
  module Cucumber
13
7
  module Formatter
14
8
  # The formatter used for <tt>--format message</tt>
15
- class Message
9
+ class Message < MessageBuilder
16
10
  include Io
17
- include Cucumber::Messages::TimeConversion
18
11
 
19
12
  def initialize(config)
20
- @config = config
21
- @hook_by_test_step = Query::HookByTestStep.new(config)
22
- @pickle_by_test = Query::PickleByTest.new(config)
23
- @pickle_step_by_test_step = Query::PickleStepByTestStep.new(config)
24
- @step_definitions_by_test_step = Query::StepDefinitionsByTestStep.new(config)
25
- @test_case_started_by_test_case = Query::TestCaseStartedByTestCase.new(config)
26
-
27
13
  @io = ensure_io(config.out_stream)
28
- config.on_event :envelope, &method(:on_envelope)
29
- config.on_event :gherkin_source_read, &method(:on_gherkin_source_read)
30
- config.on_event :test_case_ready, &method(:on_test_case_ready)
31
- config.on_event :test_run_started, &method(:on_test_run_started)
32
- config.on_event :test_case_started, &method(:on_test_case_started)
33
- config.on_event :test_step_started, &method(:on_test_step_started)
34
- config.on_event :test_step_finished, &method(:on_test_step_finished)
35
- config.on_event :test_case_finished, &method(:on_test_case_finished)
36
- config.on_event :test_run_finished, &method(:on_test_run_finished)
37
-
38
- @test_case_by_step_id = {}
39
- @current_test_case_started_id = nil
40
- @current_test_step_id = nil
41
- end
42
-
43
- def attach(src, media_type)
44
- attachment_data = {
45
- test_step_id: @current_test_step_id,
46
- test_case_started_id: @current_test_case_started_id,
47
- media_type: media_type
48
- }
49
-
50
- if media_type.start_with?('text/')
51
- attachment_data[:text] = src
52
- elsif src.respond_to? :read
53
- attachment_data[:binary] = Base64.encode64(src.read)
54
- else
55
- attachment_data[:binary] = Base64.encode64(src)
56
- end
57
-
58
- message = Cucumber::Messages::Envelope.new(
59
- attachment: Cucumber::Messages::Attachment.new(**attachment_data)
60
- )
61
-
62
- output_envelope(message)
14
+ super(config)
63
15
  end
64
16
 
65
- private
66
-
67
17
  def output_envelope(envelope)
68
18
  envelope.write_ndjson_to(@io)
69
19
  end
70
-
71
- def on_envelope(event)
72
- output_envelope(event.envelope)
73
- end
74
-
75
- def on_gherkin_source_read(event)
76
- message = Cucumber::Messages::Envelope.new(
77
- source: Cucumber::Messages::Source.new(
78
- uri: event.path,
79
- data: event.body,
80
- media_type: 'text/x.cucumber.gherkin+plain'
81
- )
82
- )
83
-
84
- output_envelope(message)
85
- end
86
-
87
- def on_test_case_ready(event)
88
- event.test_case.test_steps.each do |step|
89
- @test_case_by_step_id[step.id] = event.test_case
90
- end
91
-
92
- message = Cucumber::Messages::Envelope.new(
93
- test_case: Cucumber::Messages::TestCase.new(
94
- id: event.test_case.id,
95
- pickle_id: @pickle_by_test.pickle_id(event.test_case),
96
- test_steps: event.test_case.test_steps.map { |step| test_step_to_message(step) }
97
- )
98
- )
99
-
100
- output_envelope(message)
101
- end
102
-
103
- def test_step_to_message(step)
104
- return hook_step_to_message(step) if step.hook?
105
-
106
- Cucumber::Messages::TestCase::TestStep.new(
107
- id: step.id,
108
- pickle_step_id: @pickle_step_by_test_step.pickle_step_id(step),
109
- step_definition_ids: @step_definitions_by_test_step.step_definition_ids(step),
110
- step_match_arguments_lists: step_match_arguments_lists(step)
111
- )
112
- end
113
-
114
- def hook_step_to_message(step)
115
- Cucumber::Messages::TestCase::TestStep.new(
116
- id: step.id,
117
- hook_id: @hook_by_test_step.hook_id(step)
118
- )
119
- end
120
-
121
- def step_match_arguments_lists(step)
122
- match_arguments = step_match_arguments(step)
123
- [Cucumber::Messages::TestCase::TestStep::StepMatchArgumentsList.new(
124
- step_match_arguments: match_arguments
125
- )]
126
- rescue Cucumber::Formatter::TestStepUnknownError
127
- []
128
- end
129
-
130
- def step_match_arguments(step)
131
- @step_definitions_by_test_step.step_match_arguments(step).map do |argument|
132
- Cucumber::Messages::StepMatchArgument.new(
133
- group: argument_group_to_message(argument.group),
134
- parameter_type_name: argument.parameter_type.name
135
- )
136
- end
137
- end
138
-
139
- def argument_group_to_message(group)
140
- Cucumber::Messages::StepMatchArgument::Group.new(
141
- start: group.start,
142
- value: group.value,
143
- children: group.children.map { |child| argument_group_to_message(child) }
144
- )
145
- end
146
-
147
- def on_test_run_started(*)
148
- message = Cucumber::Messages::Envelope.new(
149
- test_run_started: Cucumber::Messages::TestRunStarted.new(
150
- timestamp: time_to_timestamp(Time.now)
151
- )
152
- )
153
-
154
- output_envelope(message)
155
- end
156
-
157
- def on_test_case_started(event)
158
- @current_test_case_started_id = test_case_started_id(event.test_case)
159
-
160
- message = Cucumber::Messages::Envelope.new(
161
- test_case_started: Cucumber::Messages::TestCaseStarted.new(
162
- id: test_case_started_id(event.test_case),
163
- test_case_id: event.test_case.id,
164
- timestamp: time_to_timestamp(Time.now),
165
- attempt: @test_case_started_by_test_case.attempt_by_test_case(event.test_case)
166
- )
167
- )
168
-
169
- output_envelope(message)
170
- end
171
-
172
- def on_test_step_started(event)
173
- @current_test_step_id = event.test_step.id
174
- test_case = @test_case_by_step_id[event.test_step.id]
175
-
176
- message = Cucumber::Messages::Envelope.new(
177
- test_step_started: Cucumber::Messages::TestStepStarted.new(
178
- test_step_id: event.test_step.id,
179
- test_case_started_id: test_case_started_id(test_case),
180
- timestamp: time_to_timestamp(Time.now)
181
- )
182
- )
183
-
184
- output_envelope(message)
185
- end
186
-
187
- def on_test_step_finished(event)
188
- test_case = @test_case_by_step_id[event.test_step.id]
189
- result = event
190
- .result
191
- .with_filtered_backtrace(Cucumber::Formatter::BacktraceFilter)
192
-
193
- result_message = result.to_message
194
- if result.failed? || result.pending?
195
- result_message = Cucumber::Messages::TestStepResult.new(
196
- status: result_message.status,
197
- duration: result_message.duration,
198
- message: create_error_message(result)
199
- )
200
- end
201
-
202
- message = Cucumber::Messages::Envelope.new(
203
- test_step_finished: Cucumber::Messages::TestStepFinished.new(
204
- test_step_id: event.test_step.id,
205
- test_case_started_id: test_case_started_id(test_case),
206
- test_step_result: result_message,
207
- timestamp: time_to_timestamp(Time.now)
208
- )
209
- )
210
-
211
- output_envelope(message)
212
- end
213
-
214
- def create_error_message(result)
215
- message_element = result.failed? ? result.exception : result
216
- message = "#{message_element.message} (#{message_element.class})"
217
- ([message] + message_element.backtrace).join("\n")
218
- end
219
-
220
- def on_test_case_finished(event)
221
- message = Cucumber::Messages::Envelope.new(
222
- test_case_finished: Cucumber::Messages::TestCaseFinished.new(
223
- test_case_started_id: test_case_started_id(event.test_case),
224
- timestamp: time_to_timestamp(Time.now)
225
- )
226
- )
227
-
228
- output_envelope(message)
229
- end
230
-
231
- def on_test_run_finished(*)
232
- message = Cucumber::Messages::Envelope.new(
233
- test_run_finished: Cucumber::Messages::TestRunFinished.new(
234
- timestamp: time_to_timestamp(Time.now)
235
- )
236
- )
237
-
238
- output_envelope(message)
239
- end
240
-
241
- def test_case_started_id(test_case)
242
- @test_case_started_by_test_case.test_case_started_id_by_test_case(test_case)
243
- end
244
20
  end
245
21
  end
246
22
  end
@@ -0,0 +1,255 @@
1
+ require 'base64'
2
+ require 'cucumber/formatter/backtrace_filter'
3
+ require 'cucumber/formatter/query/hook_by_test_step'
4
+ require 'cucumber/formatter/query/pickle_by_test'
5
+ require 'cucumber/formatter/query/pickle_step_by_test_step'
6
+ require 'cucumber/formatter/query/step_definitions_by_test_step'
7
+ require 'cucumber/formatter/query/test_case_started_by_test_case'
8
+
9
+ module Cucumber
10
+ module Formatter
11
+ class MessageBuilder
12
+ include Cucumber::Messages::TimeConversion
13
+
14
+ def initialize(config)
15
+ @config = config
16
+
17
+ @hook_by_test_step = Query::HookByTestStep.new(config)
18
+ @pickle_by_test = Query::PickleByTest.new(config)
19
+ @pickle_step_by_test_step = Query::PickleStepByTestStep.new(config)
20
+ @step_definitions_by_test_step = Query::StepDefinitionsByTestStep.new(config)
21
+ @test_case_started_by_test_case = Query::TestCaseStartedByTestCase.new(config)
22
+
23
+ config.on_event :envelope, &method(:on_envelope)
24
+ config.on_event :gherkin_source_read, &method(:on_gherkin_source_read)
25
+ config.on_event :test_case_ready, &method(:on_test_case_ready)
26
+ config.on_event :test_run_started, &method(:on_test_run_started)
27
+ config.on_event :test_case_started, &method(:on_test_case_started)
28
+ config.on_event :test_step_started, &method(:on_test_step_started)
29
+ config.on_event :test_step_finished, &method(:on_test_step_finished)
30
+ config.on_event :test_case_finished, &method(:on_test_case_finished)
31
+ config.on_event :test_run_finished, &method(:on_test_run_finished)
32
+ config.on_event :undefined_parameter_type, &method(:on_undefined_parameter_type)
33
+
34
+ @test_case_by_step_id = {}
35
+ @current_test_case_started_id = nil
36
+ @current_test_step_id = nil
37
+ end
38
+
39
+ def output_message
40
+ raise 'To be implemented'
41
+ end
42
+
43
+ def attach(src, media_type)
44
+ attachment_data = {
45
+ test_step_id: @current_test_step_id,
46
+ test_case_started_id: @current_test_case_started_id,
47
+ media_type: media_type
48
+ }
49
+
50
+ if media_type.start_with?('text/')
51
+ attachment_data[:content_encoding] = Cucumber::Messages::Attachment::ContentEncoding::IDENTITY
52
+ attachment_data[:body] = src
53
+ else
54
+ body = src.respond_to?(:read) ? src.read : src
55
+
56
+ attachment_data[:content_encoding] = Cucumber::Messages::Attachment::ContentEncoding::BASE64
57
+ attachment_data[:body] = Base64.strict_encode64(body)
58
+ end
59
+
60
+ message = Cucumber::Messages::Envelope.new(
61
+ attachment: Cucumber::Messages::Attachment.new(**attachment_data)
62
+ )
63
+
64
+ output_envelope(message)
65
+ end
66
+
67
+ private
68
+
69
+ def on_envelope(event)
70
+ output_envelope(event.envelope)
71
+ end
72
+
73
+ def on_gherkin_source_read(event)
74
+ message = Cucumber::Messages::Envelope.new(
75
+ source: Cucumber::Messages::Source.new(
76
+ uri: event.path,
77
+ data: event.body,
78
+ media_type: 'text/x.cucumber.gherkin+plain'
79
+ )
80
+ )
81
+
82
+ output_envelope(message)
83
+ end
84
+
85
+ def on_test_case_ready(event)
86
+ event.test_case.test_steps.each do |step|
87
+ @test_case_by_step_id[step.id] = event.test_case
88
+ end
89
+
90
+ message = Cucumber::Messages::Envelope.new(
91
+ test_case: Cucumber::Messages::TestCase.new(
92
+ id: event.test_case.id,
93
+ pickle_id: @pickle_by_test.pickle_id(event.test_case),
94
+ test_steps: event.test_case.test_steps.map { |step| test_step_to_message(step) }
95
+ )
96
+ )
97
+
98
+ output_envelope(message)
99
+ end
100
+
101
+ def test_step_to_message(step)
102
+ return hook_step_to_message(step) if step.hook?
103
+
104
+ Cucumber::Messages::TestCase::TestStep.new(
105
+ id: step.id,
106
+ pickle_step_id: @pickle_step_by_test_step.pickle_step_id(step),
107
+ step_definition_ids: @step_definitions_by_test_step.step_definition_ids(step),
108
+ step_match_arguments_lists: step_match_arguments_lists(step)
109
+ )
110
+ end
111
+
112
+ def hook_step_to_message(step)
113
+ Cucumber::Messages::TestCase::TestStep.new(
114
+ id: step.id,
115
+ hook_id: @hook_by_test_step.hook_id(step)
116
+ )
117
+ end
118
+
119
+ def step_match_arguments_lists(step)
120
+ match_arguments = step_match_arguments(step)
121
+ [Cucumber::Messages::TestCase::TestStep::StepMatchArgumentsList.new(
122
+ step_match_arguments: match_arguments
123
+ )]
124
+ rescue Cucumber::Formatter::TestStepUnknownError
125
+ []
126
+ end
127
+
128
+ def step_match_arguments(step)
129
+ @step_definitions_by_test_step.step_match_arguments(step).map do |argument|
130
+ Cucumber::Messages::TestCase::TestStep::StepMatchArgumentsList::StepMatchArgument.new(
131
+ group: argument_group_to_message(argument.group),
132
+ parameter_type_name: argument.parameter_type.name
133
+ )
134
+ end
135
+ end
136
+
137
+ def argument_group_to_message(group)
138
+ Cucumber::Messages::TestCase::TestStep::StepMatchArgumentsList::StepMatchArgument::Group.new(
139
+ start: group.start,
140
+ value: group.value,
141
+ children: group.children.map { |child| argument_group_to_message(child) }
142
+ )
143
+ end
144
+
145
+ def on_test_run_started(*)
146
+ message = Cucumber::Messages::Envelope.new(
147
+ test_run_started: Cucumber::Messages::TestRunStarted.new(
148
+ timestamp: time_to_timestamp(Time.now)
149
+ )
150
+ )
151
+
152
+ output_envelope(message)
153
+ end
154
+
155
+ def on_test_case_started(event)
156
+ @current_test_case_started_id = test_case_started_id(event.test_case)
157
+
158
+ message = Cucumber::Messages::Envelope.new(
159
+ test_case_started: Cucumber::Messages::TestCaseStarted.new(
160
+ id: test_case_started_id(event.test_case),
161
+ test_case_id: event.test_case.id,
162
+ timestamp: time_to_timestamp(Time.now),
163
+ attempt: @test_case_started_by_test_case.attempt_by_test_case(event.test_case)
164
+ )
165
+ )
166
+
167
+ output_envelope(message)
168
+ end
169
+
170
+ def on_test_step_started(event)
171
+ @current_test_step_id = event.test_step.id
172
+ test_case = @test_case_by_step_id[event.test_step.id]
173
+
174
+ message = Cucumber::Messages::Envelope.new(
175
+ test_step_started: Cucumber::Messages::TestStepStarted.new(
176
+ test_step_id: event.test_step.id,
177
+ test_case_started_id: test_case_started_id(test_case),
178
+ timestamp: time_to_timestamp(Time.now)
179
+ )
180
+ )
181
+
182
+ output_envelope(message)
183
+ end
184
+
185
+ def on_test_step_finished(event)
186
+ test_case = @test_case_by_step_id[event.test_step.id]
187
+ result = event
188
+ .result
189
+ .with_filtered_backtrace(Cucumber::Formatter::BacktraceFilter)
190
+
191
+ result_message = result.to_message
192
+ if result.failed? || result.pending?
193
+ result_message = Cucumber::Messages::TestStepFinished::TestStepResult.new(
194
+ status: result_message.status,
195
+ duration: result_message.duration,
196
+ message: create_error_message(result)
197
+ )
198
+ end
199
+
200
+ message = Cucumber::Messages::Envelope.new(
201
+ test_step_finished: Cucumber::Messages::TestStepFinished.new(
202
+ test_step_id: event.test_step.id,
203
+ test_case_started_id: test_case_started_id(test_case),
204
+ test_step_result: result_message,
205
+ timestamp: time_to_timestamp(Time.now)
206
+ )
207
+ )
208
+
209
+ output_envelope(message)
210
+ end
211
+
212
+ def create_error_message(result)
213
+ message_element = result.failed? ? result.exception : result
214
+ message = "#{message_element.message} (#{message_element.class})"
215
+ ([message] + message_element.backtrace).join("\n")
216
+ end
217
+
218
+ def on_test_case_finished(event)
219
+ message = Cucumber::Messages::Envelope.new(
220
+ test_case_finished: Cucumber::Messages::TestCaseFinished.new(
221
+ test_case_started_id: test_case_started_id(event.test_case),
222
+ timestamp: time_to_timestamp(Time.now)
223
+ )
224
+ )
225
+
226
+ output_envelope(message)
227
+ end
228
+
229
+ def on_test_run_finished(*)
230
+ message = Cucumber::Messages::Envelope.new(
231
+ test_run_finished: Cucumber::Messages::TestRunFinished.new(
232
+ timestamp: time_to_timestamp(Time.now)
233
+ )
234
+ )
235
+
236
+ output_envelope(message)
237
+ end
238
+
239
+ def on_undefined_parameter_type(event)
240
+ message = Cucumber::Messages::Envelope.new(
241
+ undefined_parameter_type: Cucumber::Messages::UndefinedParameterType.new(
242
+ name: event.type_name,
243
+ expression: event.expression
244
+ )
245
+ )
246
+
247
+ output_envelope(message)
248
+ end
249
+
250
+ def test_case_started_id(test_case)
251
+ @test_case_started_by_test_case.test_case_started_id_by_test_case(test_case)
252
+ end
253
+ end
254
+ end
255
+ end