cucumber 4.0.0.rc.3 → 4.0.0.rc.4

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.
Files changed (44) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +17 -1
  3. data/lib/cucumber/cli/options.rb +2 -1
  4. data/lib/cucumber/configuration.rb +5 -0
  5. data/lib/cucumber/deprecate.rb +29 -5
  6. data/lib/cucumber/errors.rb +3 -0
  7. data/lib/cucumber/events.rb +12 -7
  8. data/lib/cucumber/events/envelope.rb +9 -0
  9. data/lib/cucumber/events/hook_test_step_created.rb +13 -0
  10. data/lib/cucumber/events/test_case_created.rb +13 -0
  11. data/lib/cucumber/events/test_case_ready.rb +12 -0
  12. data/lib/cucumber/events/test_step_created.rb +13 -0
  13. data/lib/cucumber/filters.rb +1 -0
  14. data/lib/cucumber/filters/broadcast_test_case_ready_event.rb +12 -0
  15. data/lib/cucumber/formatter/console.rb +3 -8
  16. data/lib/cucumber/formatter/duration_extractor.rb +1 -1
  17. data/lib/cucumber/formatter/errors.rb +6 -0
  18. data/lib/cucumber/formatter/json.rb +15 -6
  19. data/lib/cucumber/formatter/junit.rb +1 -1
  20. data/lib/cucumber/formatter/message.rb +246 -0
  21. data/lib/cucumber/formatter/pretty.rb +3 -4
  22. data/lib/cucumber/formatter/query/hook_by_test_step.rb +31 -0
  23. data/lib/cucumber/formatter/query/pickle_by_test.rb +26 -0
  24. data/lib/cucumber/formatter/query/pickle_step_by_test_step.rb +26 -0
  25. data/lib/cucumber/formatter/query/step_definitions_by_test_step.rb +40 -0
  26. data/lib/cucumber/formatter/query/test_case_started_by_test_case.rb +40 -0
  27. data/lib/cucumber/gherkin/data_table_parser.rb +1 -1
  28. data/lib/cucumber/gherkin/steps_parser.rb +1 -1
  29. data/lib/cucumber/glue/hook.rb +18 -2
  30. data/lib/cucumber/glue/proto_world.rb +30 -18
  31. data/lib/cucumber/glue/registry_and_more.rb +31 -2
  32. data/lib/cucumber/glue/step_definition.rb +28 -4
  33. data/lib/cucumber/hooks.rb +8 -8
  34. data/lib/cucumber/multiline_argument.rb +1 -1
  35. data/lib/cucumber/multiline_argument/data_table.rb +17 -13
  36. data/lib/cucumber/runtime.rb +2 -2
  37. data/lib/cucumber/runtime/after_hooks.rb +6 -2
  38. data/lib/cucumber/runtime/before_hooks.rb +6 -2
  39. data/lib/cucumber/runtime/for_programming_languages.rb +1 -0
  40. data/lib/cucumber/runtime/step_hooks.rb +3 -2
  41. data/lib/cucumber/runtime/support_code.rb +3 -3
  42. data/lib/cucumber/runtime/user_interface.rb +2 -10
  43. data/lib/cucumber/version +1 -1
  44. metadata +40 -27
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: ee911dfd2e4141ad61af0c67b5c9be6e169fe2d27bd2a9c407a590fe9eb0e72a
4
- data.tar.gz: 28fd680ef1f6f8d60bbcaba4a44c153d94d0a626c873aac9956b7ee8b36e8c7b
3
+ metadata.gz: 3cf95e63d73ffec417fa0dfc1f13e208355e78783a9f092d8e143dc5ca26d636
4
+ data.tar.gz: 869fe72a5dd449be55d00e2e72d8f78c236961141bf1cc85a7919bca426ec299
5
5
  SHA512:
6
- metadata.gz: 75974422135d45e115c32f685e88971eeec3f1c13473a0fc312412c4f73b665e84d439840642c67b93076a7499cf0130e28caddbb6761e5780b8e29b66e767eb
7
- data.tar.gz: d0eebdfd398decebf6fd0982306f31d501794bb8c5866452e0e65354a3af10da9d50c49cd08a137ec87193902cc2934e70340bed5a41b23ee59f84191c66add8
6
+ metadata.gz: 37c240a47d8127723e75c33051ff4e546a7e5a084a22400bb55e6d00d6d578ab7d5d7daf905259cba6625a512986fcacd4076810202e6f63dbffea16b366e9f5
7
+ data.tar.gz: 4556b216164535c0c2b39a1f2116b511f0cb1cccfee41cddb513073d0d887014edb38a632978347d1c127e228f1bd683317fbc62588bd4b497cdd51e10a3c550
@@ -10,7 +10,23 @@ Please visit [cucumber/CONTRIBUTING.md](https://github.com/cucumber/cucumber/blo
10
10
 
11
11
  ----
12
12
 
13
- ## [4.0.0.rc.2](https://github.com/cucumber/cucumber-ruby/compare/v4.0.0.rc.2...v4.0.0.rc.3)
13
+ ## [4.0.0.rc.4](https://github.com/cucumber/cucumber-ruby/compare/v4.0.0.rc.3...4.0.0.rc.4)
14
+
15
+
16
+ ### Added
17
+
18
+ * Add `message`formatter which produces `Cucumber::Messages` ndjson output.
19
+ * Comply with [`cucumber-compatibility-kit](https://github.com/cucumber/cucumber/tree/master/compatibility-kit)
20
+ * Methods `log` and `attach` can be used in step definitions to attach text or images
21
+
22
+ ### Deprecated
23
+
24
+ * `--format=json` in favor of the `message` formatter and the stand-alone JSON formatter
25
+ * `puts` in step definitions in favor of `log` ([cucumber#897](https://github.com/cucumber/cucumber/issues/897))
26
+ * `embed` in step definitions in favor of `attach` ([cucumber#897](https://github.com/cucumber/cucumber/issues/897))
27
+
28
+
29
+ ## [4.0.0.rc.3](https://github.com/cucumber/cucumber-ruby/compare/v4.0.0.rc.2...v4.0.0.rc.3)
14
30
 
15
31
  ### Changed
16
32
 
@@ -22,7 +22,8 @@ module Cucumber
22
22
  'stepdefs' => ['Cucumber::Formatter::Stepdefs', "Prints All step definitions with their locations. Same as\n" \
23
23
  "#{INDENT}the usage formatter, except that steps are not printed."],
24
24
  'junit' => ['Cucumber::Formatter::Junit', 'Generates a report similar to Ant+JUnit.'],
25
- 'json' => ['Cucumber::Formatter::Json', 'Prints the feature as JSON'],
25
+ 'json' => ['Cucumber::Formatter::Json', '[DEPRECATED] Prints the feature as JSON'],
26
+ 'message' => ['Cucumber::Formatter::Message', 'Outputs protobuf messages'],
26
27
  'summary' => ['Cucumber::Formatter::Summary', 'Summary output of feature and scenarios']
27
28
  }.freeze
28
29
  max = BUILTIN_FORMATS.keys.map(&:length).max
@@ -3,6 +3,7 @@
3
3
  require 'cucumber/constantize'
4
4
  require 'cucumber/cli/rerun_file'
5
5
  require 'cucumber/events'
6
+ require 'cucumber/messages'
6
7
  require 'cucumber/core/event_bus'
7
8
  require 'cucumber/core/test/result'
8
9
  require 'forwardable'
@@ -242,6 +243,10 @@ module Cucumber
242
243
  @options[:event_bus]
243
244
  end
244
245
 
246
+ def id_generator
247
+ @id_generator ||= Cucumber::Messages::IdGenerator::UUID.new
248
+ end
249
+
245
250
  private
246
251
 
247
252
  def default_options
@@ -5,13 +5,37 @@ require 'cucumber/gherkin/formatter/ansi_escapes'
5
5
 
6
6
  module Cucumber
7
7
  module Deprecate
8
- module ForUsers
9
- AnsiEscapes = Cucumber::Gherkin::Formatter::AnsiEscapes
8
+ class AnsiString
9
+ include Cucumber::Gherkin::Formatter::AnsiEscapes
10
+
11
+ def self.failure_message(message)
12
+ AnsiString.new.failure_message(message)
13
+ end
14
+
15
+ def failure_message(message)
16
+ failed + message + reset
17
+ end
18
+ end
10
19
 
20
+ class CliOption
21
+ def self.deprecate(stream, option, message, remove_after_version)
22
+ return if stream.nil?
23
+ stream.puts(
24
+ AnsiString.failure_message(
25
+ "\nWARNING: #{option} is deprecated" \
26
+ " and will be removed after version #{remove_after_version}.\n#{message}.\n"
27
+ )
28
+ )
29
+ end
30
+ end
31
+
32
+ module ForUsers
11
33
  def self.call(message, method, remove_after_version)
12
- STDERR.puts AnsiEscapes.failed + "\nWARNING: ##{method} is deprecated" \
13
- " and will be removed after version #{remove_after_version}. #{message}.\n" \
14
- "(Called from #{caller(3..3).first})" + AnsiEscapes.reset
34
+ STDERR.puts AnsiString.failure_message(
35
+ "\nWARNING: ##{method} is deprecated" \
36
+ " and will be removed after version #{remove_after_version}. #{message}.\n" \
37
+ "(Called from #{caller(3..3).first})"
38
+ )
15
39
  end
16
40
  end
17
41
 
@@ -49,4 +49,7 @@ module Cucumber
49
49
  super(messages.join("\n"))
50
50
  end
51
51
  end
52
+
53
+ class LogTypeInvalid < StandardError
54
+ end
52
55
  end
@@ -24,16 +24,21 @@ module Cucumber
24
24
 
25
25
  def self.registry
26
26
  Core::Events.build_registry(
27
- TestCaseStarted,
27
+ GherkinSourceParsed,
28
+ GherkinSourceRead,
29
+ HookTestStepCreated,
30
+ StepActivated,
31
+ StepDefinitionRegistered,
32
+ TestCaseCreated,
28
33
  TestCaseFinished,
34
+ TestCaseStarted,
35
+ TestCaseReady,
36
+ TestRunFinished,
37
+ TestRunStarted,
38
+ TestStepCreated,
29
39
  TestStepFinished,
30
40
  TestStepStarted,
31
- StepDefinitionRegistered,
32
- StepActivated,
33
- TestRunFinished,
34
- GherkinSourceRead,
35
- GherkinSourceParsed,
36
- TestRunStarted
41
+ Envelope
37
42
  )
38
43
  end
39
44
  end
@@ -0,0 +1,9 @@
1
+ require 'cucumber/core/events'
2
+
3
+ module Cucumber
4
+ module Events
5
+ class Envelope < Core::Event.new(:envelope)
6
+ attr_reader :envelope
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'cucumber/core/events'
4
+
5
+ module Cucumber
6
+ module Events
7
+ # Event fired when a step is created from a hook
8
+ class HookTestStepCreated < Core::Event.new(:test_step, :hook)
9
+ attr_reader :test_step
10
+ attr_reader :hook
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'cucumber/core/events'
4
+
5
+ module Cucumber
6
+ module Events
7
+ # Event fired when a Test::Case is created from a Pickle
8
+ class TestCaseCreated < Core::Event.new(:test_case, :pickle)
9
+ attr_reader :test_case
10
+ attr_reader :pickle
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'cucumber/core/events'
4
+
5
+ module Cucumber
6
+ module Events
7
+ # Event fired when a Test::Case is ready to be ran (matching has been done, hooks added etc)
8
+ class TestCaseReady < Core::Event.new(:test_case)
9
+ attr_reader :test_case
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'cucumber/core/events'
4
+
5
+ module Cucumber
6
+ module Events
7
+ # Event fired when a TestStep is created from a PickleStep
8
+ class TestStepCreated < Core::Event.new(:test_step, :pickle_step)
9
+ attr_reader :test_step
10
+ attr_reader :pickle_step
11
+ end
12
+ end
13
+ end
@@ -11,3 +11,4 @@ require 'cucumber/filters/quit'
11
11
  require 'cucumber/filters/randomizer'
12
12
  require 'cucumber/filters/retry'
13
13
  require 'cucumber/filters/tag_limits'
14
+ require 'cucumber/filters/broadcast_test_case_ready_event'
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Cucumber
4
+ module Filters
5
+ class BroadcastTestCaseReadyEvent < Core::Filter.new(:config)
6
+ def test_case(test_case)
7
+ config.notify :test_case_ready, test_case
8
+ test_case.describe_to(receiver)
9
+ end
10
+ end
11
+ end
12
+ end
@@ -158,16 +158,11 @@ module Cucumber
158
158
  end
159
159
  end
160
160
 
161
- def embed(file, mime_type, label)
162
- # no-op
163
- end
164
-
165
- def puts(*messages)
161
+ def attach(src, media_type)
162
+ return unless media_type == 'text/x.cucumber.log+plain'
166
163
  return unless @io
167
164
  @io.puts
168
- messages.each do |message|
169
- @io.puts(format_string(message, :tag))
170
- end
165
+ @io.puts(format_string(src, :tag))
171
166
  @io.flush
172
167
  end
173
168
 
@@ -25,7 +25,7 @@ module Cucumber
25
25
  duration.tap { |dur| @result_duration = dur.nanoseconds / 10**9.0 }
26
26
  end
27
27
 
28
- def embed(*) end
28
+ def attach(*) end
29
29
  end
30
30
  end
31
31
  end
@@ -0,0 +1,6 @@
1
+ module Cucumber
2
+ module Formatter
3
+ class TestCaseUnknownError < StandardError; end
4
+ class TestStepUnknownError < StandardError; end
5
+ end
6
+ end
@@ -5,6 +5,7 @@ require 'base64'
5
5
  require 'cucumber/formatter/backtrace_filter'
6
6
  require 'cucumber/formatter/io'
7
7
  require 'cucumber/formatter/ast_lookup'
8
+ require 'cucumber/deprecate'
8
9
 
9
10
  module Cucumber
10
11
  module Formatter
@@ -13,6 +14,14 @@ module Cucumber
13
14
  include Io
14
15
 
15
16
  def initialize(config)
17
+ Cucumber::Deprecate::CliOption.deprecate(
18
+ config.error_stream,
19
+ '--format=json',
20
+ "Please use --format=message and stand-alone json-formatter.\n" \
21
+ 'json-formatter homepage: https://github.com/cucumber/cucumber/tree/master/json-formatter#cucumber-json-formatter',
22
+ '5.0.0'
23
+ )
24
+
16
25
  @io = ensure_io(config.out_stream)
17
26
  @ast_lookup = AstLookup.new(config)
18
27
  @feature_hashes = []
@@ -80,11 +89,11 @@ module Cucumber
80
89
  @io.write(MultiJson.dump(@feature_hashes, pretty: true))
81
90
  end
82
91
 
83
- def puts(message)
84
- test_step_output << message
85
- end
86
-
87
- def embed(src, mime_type, _label)
92
+ def attach(src, mime_type)
93
+ if mime_type == 'text/x.cucumber.log+plain'
94
+ test_step_output << src
95
+ return
96
+ end
88
97
  if File.file?(src)
89
98
  content = File.open(src, 'rb', &:read)
90
99
  data = encode64(content)
@@ -173,7 +182,7 @@ module Cucumber
173
182
  end
174
183
 
175
184
  def create_doc_string_hash(doc_string)
176
- content_type = doc_string.content_type || ''
185
+ content_type = doc_string.media_type || ''
177
186
  {
178
187
  value: doc_string.content,
179
188
  content_type: content_type,
@@ -239,7 +239,7 @@ module Cucumber
239
239
  duration.tap { |dur| @test_case_duration = dur.nanoseconds / 10**9.0 }
240
240
  end
241
241
 
242
- def embed(*) end
242
+ def attach(*) end
243
243
  end
244
244
  end
245
245
  end
@@ -0,0 +1,246 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'base64'
4
+ 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'
11
+
12
+ module Cucumber
13
+ module Formatter
14
+ # The formatter used for <tt>--format message</tt>
15
+ class Message
16
+ include Io
17
+ include Cucumber::Messages::TimeConversion
18
+
19
+ 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
+ @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)
63
+ end
64
+
65
+ private
66
+
67
+ def output_envelope(envelope)
68
+ envelope.write_ndjson_to(@io)
69
+ 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
+ end
245
+ end
246
+ end