cucumber 4.0.0.rc.4 → 4.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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