datadog-ci 1.2.0 → 1.3.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.
Files changed (56) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +24 -2
  3. data/lib/datadog/ci/configuration/components.rb +30 -3
  4. data/lib/datadog/ci/contrib/cucumber/formatter.rb +13 -9
  5. data/lib/datadog/ci/contrib/minitest/runnable.rb +5 -1
  6. data/lib/datadog/ci/contrib/minitest/runner.rb +6 -2
  7. data/lib/datadog/ci/contrib/minitest/test.rb +7 -3
  8. data/lib/datadog/ci/contrib/rspec/example.rb +6 -2
  9. data/lib/datadog/ci/contrib/rspec/example_group.rb +5 -1
  10. data/lib/datadog/ci/contrib/rspec/knapsack_pro/runner.rb +6 -2
  11. data/lib/datadog/ci/contrib/rspec/runner.rb +6 -2
  12. data/lib/datadog/ci/ext/environment/providers/appveyor.rb +1 -1
  13. data/lib/datadog/ci/ext/environment/providers/aws_code_pipeline.rb +1 -1
  14. data/lib/datadog/ci/ext/environment/providers/azure.rb +1 -1
  15. data/lib/datadog/ci/ext/environment/providers/bitbucket.rb +1 -1
  16. data/lib/datadog/ci/ext/environment/providers/bitrise.rb +1 -1
  17. data/lib/datadog/ci/ext/environment/providers/buddy.rb +1 -1
  18. data/lib/datadog/ci/ext/environment/providers/buildkite.rb +1 -1
  19. data/lib/datadog/ci/ext/environment/providers/circleci.rb +1 -1
  20. data/lib/datadog/ci/ext/environment/providers/codefresh.rb +1 -1
  21. data/lib/datadog/ci/ext/environment/providers/github_actions.rb +1 -1
  22. data/lib/datadog/ci/ext/environment/providers/gitlab.rb +1 -1
  23. data/lib/datadog/ci/ext/environment/providers/jenkins.rb +1 -1
  24. data/lib/datadog/ci/ext/environment/providers/teamcity.rb +1 -1
  25. data/lib/datadog/ci/ext/environment/providers/travis.rb +1 -1
  26. data/lib/datadog/ci/ext/environment.rb +17 -0
  27. data/lib/datadog/ci/ext/telemetry.rb +120 -0
  28. data/lib/datadog/ci/git/local_repository.rb +116 -25
  29. data/lib/datadog/ci/git/search_commits.rb +20 -1
  30. data/lib/datadog/ci/git/telemetry.rb +37 -0
  31. data/lib/datadog/ci/git/tree_uploader.rb +7 -0
  32. data/lib/datadog/ci/git/upload_packfile.rb +22 -1
  33. data/lib/datadog/ci/test.rb +5 -0
  34. data/lib/datadog/ci/test_optimisation/component.rb +16 -2
  35. data/lib/datadog/ci/test_optimisation/coverage/transport.rb +10 -1
  36. data/lib/datadog/ci/test_optimisation/skippable.rb +24 -0
  37. data/lib/datadog/ci/test_optimisation/telemetry.rb +56 -0
  38. data/lib/datadog/ci/test_visibility/component.rb +95 -235
  39. data/lib/datadog/ci/test_visibility/context.rb +274 -0
  40. data/lib/datadog/ci/test_visibility/{context → store}/global.rb +1 -1
  41. data/lib/datadog/ci/test_visibility/{context → store}/local.rb +1 -1
  42. data/lib/datadog/ci/test_visibility/telemetry.rb +69 -0
  43. data/lib/datadog/ci/test_visibility/transport.rb +8 -9
  44. data/lib/datadog/ci/transport/adapters/net.rb +42 -11
  45. data/lib/datadog/ci/transport/adapters/net_http_client.rb +17 -0
  46. data/lib/datadog/ci/transport/adapters/telemetry_webmock_safe_adapter.rb +28 -0
  47. data/lib/datadog/ci/transport/event_platform_transport.rb +42 -5
  48. data/lib/datadog/ci/transport/http.rb +49 -21
  49. data/lib/datadog/ci/transport/remote_settings_api.rb +39 -1
  50. data/lib/datadog/ci/transport/telemetry.rb +93 -0
  51. data/lib/datadog/ci/utils/identity.rb +20 -0
  52. data/lib/datadog/ci/utils/parsing.rb +2 -1
  53. data/lib/datadog/ci/utils/telemetry.rb +23 -0
  54. data/lib/datadog/ci/version.rb +1 -1
  55. data/lib/datadog/ci.rb +30 -0
  56. metadata +16 -6
@@ -0,0 +1,56 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "../ext/telemetry"
4
+ require_relative "../ext/test"
5
+ require_relative "../utils/telemetry"
6
+ require_relative "../test_visibility/telemetry"
7
+
8
+ module Datadog
9
+ module CI
10
+ module TestOptimisation
11
+ # Telemetry for test optimisation component
12
+ module Telemetry
13
+ def self.code_coverage_started(test)
14
+ Utils::Telemetry.inc(Ext::Telemetry::METRIC_CODE_COVERAGE_STARTED, 1, tags_for_test(test))
15
+ end
16
+
17
+ def self.code_coverage_finished(test)
18
+ Utils::Telemetry.inc(Ext::Telemetry::METRIC_CODE_COVERAGE_FINISHED, 1, tags_for_test(test))
19
+ end
20
+
21
+ def self.code_coverage_is_empty
22
+ Utils::Telemetry.inc(Ext::Telemetry::METRIC_CODE_COVERAGE_IS_EMPTY, 1)
23
+ end
24
+
25
+ def self.code_coverage_files(count)
26
+ Utils::Telemetry.distribution(Ext::Telemetry::METRIC_CODE_COVERAGE_FILES, count.to_f)
27
+ end
28
+
29
+ def self.itr_skipped
30
+ Utils::Telemetry.inc(Ext::Telemetry::METRIC_ITR_SKIPPED, 1, tags_for_itr_metrics)
31
+ end
32
+
33
+ def self.itr_forced_run
34
+ Utils::Telemetry.inc(Ext::Telemetry::METRIC_ITR_FORCED_RUN, 1, tags_for_itr_metrics)
35
+ end
36
+
37
+ def self.itr_unskippable
38
+ Utils::Telemetry.inc(Ext::Telemetry::METRIC_ITR_UNSKIPPABLE, 1, tags_for_itr_metrics)
39
+ end
40
+
41
+ def self.tags_for_test(test)
42
+ {
43
+ Ext::Telemetry::TAG_TEST_FRAMEWORK => test.get_tag(Ext::Test::TAG_FRAMEWORK),
44
+ Ext::Telemetry::TAG_LIBRARY => Ext::Telemetry::Library::CUSTOM
45
+ }
46
+ end
47
+
48
+ def self.tags_for_itr_metrics
49
+ {
50
+ Ext::Telemetry::TAG_EVENT_TYPE => Ext::Telemetry::EventType::TEST
51
+ }
52
+ end
53
+ end
54
+ end
55
+ end
56
+ end
@@ -1,35 +1,23 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "datadog/tracing"
4
- require "datadog/tracing/contrib/component"
5
- require "datadog/tracing/trace_digest"
6
-
7
3
  require "rbconfig"
8
4
 
9
- require_relative "context/global"
10
- require_relative "context/local"
5
+ require_relative "context"
6
+ require_relative "telemetry"
11
7
 
12
8
  require_relative "../codeowners/parser"
13
9
  require_relative "../contrib/contrib"
14
- require_relative "../ext/app_types"
15
10
  require_relative "../ext/test"
16
- require_relative "../ext/environment"
17
11
  require_relative "../git/local_repository"
18
12
 
19
- require_relative "../span"
20
- require_relative "../test"
21
- require_relative "../test_session"
22
- require_relative "../test_module"
23
- require_relative "../test_suite"
24
13
  require_relative "../worker"
25
14
 
26
15
  module Datadog
27
16
  module CI
28
17
  module TestVisibility
29
18
  # Common behavior for CI tests
30
- # Note: this class has too many responsibilities and should be split into multiple classes
31
19
  class Component
32
- attr_reader :environment_tags, :test_suite_level_visibility_enabled
20
+ attr_reader :test_suite_level_visibility_enabled
33
21
 
34
22
  def initialize(
35
23
  test_optimisation:,
@@ -39,13 +27,8 @@ module Datadog
39
27
  codeowners: Codeowners::Parser.new(Git::LocalRepository.root).parse
40
28
  )
41
29
  @test_suite_level_visibility_enabled = test_suite_level_visibility_enabled
42
-
43
- @environment_tags = Ext::Environment.tags(ENV).freeze
44
- @local_context = Context::Local.new
45
- @global_context = Context::Global.new
46
-
30
+ @context = Context.new
47
31
  @codeowners = codeowners
48
-
49
32
  @test_optimisation = test_optimisation
50
33
  @remote_settings_api = remote_settings_api
51
34
  @git_tree_upload_worker = git_tree_upload_worker
@@ -58,155 +41,98 @@ module Datadog
58
41
  def start_test_session(service: nil, tags: {})
59
42
  return skip_tracing unless test_suite_level_visibility_enabled
60
43
 
61
- # finds and instruments additional test libraries that we support (ex: selenium-webdriver)
62
- Contrib.auto_instrument_on_session_start!
63
-
64
- @global_context.fetch_or_activate_test_session do
65
- tracer_span = start_datadog_tracer_span(
66
- "test.session", build_span_options(service, Ext::AppTypes::TYPE_TEST_SESSION)
67
- )
68
- set_session_context(tags, tracer_span)
69
-
70
- test_session = build_test_session(tracer_span, tags)
71
-
72
- @git_tree_upload_worker.perform(test_session.git_repository_url)
73
- configure_library(test_session)
74
-
75
- test_session
76
- end
44
+ test_session = @context.start_test_session(service: service, tags: tags)
45
+ on_test_session_started(test_session)
46
+ test_session
77
47
  end
78
48
 
79
49
  def start_test_module(test_module_name, service: nil, tags: {})
80
50
  return skip_tracing unless test_suite_level_visibility_enabled
81
51
 
82
- @global_context.fetch_or_activate_test_module do
83
- set_inherited_globals(tags)
84
- set_session_context(tags)
85
-
86
- tracer_span = start_datadog_tracer_span(
87
- test_module_name, build_span_options(service, Ext::AppTypes::TYPE_TEST_MODULE)
88
- )
89
- set_module_context(tags, tracer_span)
90
-
91
- build_test_module(tracer_span, tags)
92
- end
52
+ test_module = @context.start_test_module(test_module_name, service: service, tags: tags)
53
+ on_test_module_started(test_module)
54
+ test_module
93
55
  end
94
56
 
95
57
  def start_test_suite(test_suite_name, service: nil, tags: {})
96
58
  return skip_tracing unless test_suite_level_visibility_enabled
97
59
 
98
- @global_context.fetch_or_activate_test_suite(test_suite_name) do
99
- set_inherited_globals(tags)
100
- set_session_context(tags)
101
- set_module_context(tags)
102
-
103
- tracer_span = start_datadog_tracer_span(
104
- test_suite_name, build_span_options(service, Ext::AppTypes::TYPE_TEST_SUITE)
105
- )
106
- set_suite_context(tags, span: tracer_span)
107
-
108
- build_test_suite(tracer_span, tags)
109
- end
60
+ test_suite = @context.start_test_suite(test_suite_name, service: service, tags: tags)
61
+ on_test_suite_started(test_suite)
62
+ test_suite
110
63
  end
111
64
 
112
65
  def trace_test(test_name, test_suite_name, service: nil, tags: {}, &block)
113
- set_inherited_globals(tags)
114
- set_session_context(tags)
115
- set_module_context(tags)
116
- set_suite_context(tags, name: test_suite_name)
117
-
118
- tags[Ext::Test::TAG_NAME] = test_name
119
- tags[Ext::Test::TAG_TYPE] ||= Ext::Test::Type::TEST
120
-
121
- span_options = build_span_options(
122
- service,
123
- Ext::AppTypes::TYPE_TEST,
124
- # :resource is needed for the agent APM protocol to work correctly (for older agent versions)
125
- # :continue_from is required to start a new trace for each test
126
- {resource: test_name, continue_from: Datadog::Tracing::TraceDigest.new}
127
- )
128
-
129
66
  if block
130
- start_datadog_tracer_span(test_name, span_options) do |tracer_span|
131
- test = build_test(tracer_span, tags)
132
-
133
- @local_context.activate_test(test) do
134
- on_test_started(test)
135
- res = block.call(test)
136
- on_test_finished(test)
137
- res
138
- end
67
+ @context.trace_test(test_name, test_suite_name, service: service, tags: tags) do |test|
68
+ on_test_started(test)
69
+ res = block.call(test)
70
+ on_test_finished(test)
71
+ res
139
72
  end
140
73
  else
141
- tracer_span = start_datadog_tracer_span(test_name, span_options)
142
- test = build_test(tracer_span, tags)
143
-
144
- @local_context.activate_test(test)
74
+ test = @context.trace_test(test_name, test_suite_name, service: service, tags: tags)
145
75
  on_test_started(test)
146
-
147
76
  test
148
77
  end
149
78
  end
150
79
 
151
80
  def trace(span_name, type: "span", tags: {}, &block)
152
- span_options = build_span_options(
153
- nil, # service name is completely optional for custom spans
154
- type,
155
- {resource: span_name}
156
- )
157
-
158
81
  if block
159
- start_datadog_tracer_span(span_name, span_options) do |tracer_span|
160
- block.call(build_span(tracer_span, tags))
82
+ @context.trace(span_name, type: type, tags: tags) do |span|
83
+ block.call(span)
161
84
  end
162
85
  else
163
- tracer_span = start_datadog_tracer_span(span_name, span_options)
164
-
165
- build_span(tracer_span, tags)
86
+ @context.trace(span_name, type: type, tags: tags)
166
87
  end
167
88
  end
168
89
 
169
90
  def active_span
170
- tracer_span = Datadog::Tracing.active_span
171
- Span.new(tracer_span) if tracer_span
91
+ @context.active_span
172
92
  end
173
93
 
174
94
  def active_test
175
- @local_context.active_test
95
+ @context.active_test
176
96
  end
177
97
 
178
98
  def active_test_session
179
- @global_context.active_test_session
99
+ @context.active_test_session
180
100
  end
181
101
 
182
102
  def active_test_module
183
- @global_context.active_test_module
103
+ @context.active_test_module
184
104
  end
185
105
 
186
106
  def active_test_suite(test_suite_name)
187
- @global_context.active_test_suite(test_suite_name)
107
+ @context.active_test_suite(test_suite_name)
188
108
  end
189
109
 
190
110
  def deactivate_test
191
111
  test = active_test
192
112
  on_test_finished(test) if test
193
113
 
194
- @local_context.deactivate_test
114
+ @context.deactivate_test
195
115
  end
196
116
 
197
117
  def deactivate_test_session
198
118
  test_session = active_test_session
199
119
  on_test_session_finished(test_session) if test_session
200
120
 
201
- @global_context.deactivate_test_session!
121
+ @context.deactivate_test_session
202
122
  end
203
123
 
204
124
  def deactivate_test_module
205
- @global_context.deactivate_test_module!
125
+ test_module = active_test_module
126
+ on_test_module_finished(test_module) if test_module
127
+
128
+ @context.deactivate_test_module
206
129
  end
207
130
 
208
131
  def deactivate_test_suite(test_suite_name)
209
- @global_context.deactivate_test_suite!(test_suite_name)
132
+ test_suite = active_test_suite(test_suite_name)
133
+ on_test_suite_finished(test_suite) if test_suite
134
+
135
+ @context.deactivate_test_suite(test_suite_name)
210
136
  end
211
137
 
212
138
  def itr_enabled?
@@ -215,63 +141,27 @@ module Datadog
215
141
 
216
142
  private
217
143
 
218
- def configure_library(test_session)
219
- # this will change when EFD is implemented
220
- return unless itr_enabled?
221
-
222
- remote_configuration = @remote_settings_api.fetch_library_settings(test_session)
223
- # sometimes we can skip code coverage for default branch if there are no changes in the repository
224
- # backend needs git metadata uploaded for this test session to check if we can skip code coverage
225
- if remote_configuration.require_git?
226
- Datadog.logger.debug { "Library configuration endpoint requires git upload to be finished, waiting..." }
227
- @git_tree_upload_worker.wait_until_done
228
-
229
- Datadog.logger.debug { "Requesting library configuration again..." }
230
- remote_configuration = @remote_settings_api.fetch_library_settings(test_session)
144
+ # DOMAIN EVENTS
145
+ def on_test_session_started(test_session)
146
+ Telemetry.event_created(test_session)
147
+ Telemetry.test_session_started(test_session)
231
148
 
232
- if remote_configuration.require_git?
233
- Datadog.logger.debug { "git metadata upload did not complete in time when configuring library" }
234
- end
235
- end
236
-
237
- @test_optimisation.configure(
238
- remote_configuration.payload,
239
- test_session: test_session,
240
- git_tree_upload_worker: @git_tree_upload_worker
241
- )
242
- end
243
-
244
- def skip_tracing(block = nil)
245
- block&.call(nil)
246
- end
247
-
248
- # Sets trace's origin to ciapp-test
249
- def set_trace_origin(trace)
250
- trace&.origin = Ext::Test::CONTEXT_ORIGIN
251
- end
149
+ # finds and instruments additional test libraries that we support (ex: selenium-webdriver)
150
+ Contrib.auto_instrument_on_session_start!
252
151
 
253
- def build_test_session(tracer_span, tags)
254
- test_session = TestSession.new(tracer_span)
255
- set_initial_tags(test_session, tags)
256
- test_session
152
+ @git_tree_upload_worker.perform(test_session.git_repository_url)
153
+ configure_library(test_session)
257
154
  end
258
155
 
259
- def build_test_module(tracer_span, tags)
260
- test_module = TestModule.new(tracer_span)
261
- set_initial_tags(test_module, tags)
262
- test_module
156
+ def on_test_module_started(test_module)
157
+ Telemetry.event_created(test_module)
263
158
  end
264
159
 
265
- def build_test_suite(tracer_span, tags)
266
- test_suite = TestSuite.new(tracer_span)
267
- set_initial_tags(test_suite, tags)
268
- test_suite
160
+ def on_test_suite_started(test_suite)
161
+ Telemetry.event_created(test_suite)
269
162
  end
270
163
 
271
- def build_test(tracer_span, tags)
272
- test = Test.new(tracer_span)
273
- set_initial_tags(test, tags)
274
-
164
+ def on_test_started(test)
275
165
  # sometimes test suite is not being assigned correctly
276
166
  # fix it by fetching the one single running test suite from the global context
277
167
  fix_test_suite!(test) if test.test_suite_id.nil?
@@ -279,49 +169,63 @@ module Datadog
279
169
  validate_test_suite_level_visibility_correctness(test)
280
170
  set_codeowners(test)
281
171
 
282
- test
283
- end
172
+ Telemetry.event_created(test)
284
173
 
285
- def build_span(tracer_span, tags)
286
- span = Span.new(tracer_span)
287
- set_initial_tags(span, tags)
288
- span
174
+ @test_optimisation.mark_if_skippable(test)
175
+ @test_optimisation.start_coverage(test)
289
176
  end
290
177
 
291
- def build_span_options(service, type, other_options = {})
292
- other_options[:service] = service || @global_context.service
293
- other_options[:type] = type
178
+ def on_test_session_finished(test_session)
179
+ @test_optimisation.write_test_session_tags(test_session)
294
180
 
295
- other_options
181
+ Telemetry.event_finished(test_session)
296
182
  end
297
183
 
298
- def set_inherited_globals(tags)
299
- # this code achieves the same as @global_context.inheritable_session_tags.merge(tags)
300
- # but without allocating a new hash
301
- @global_context.inheritable_session_tags.each do |key, value|
302
- tags[key] = value unless tags.key?(key)
303
- end
184
+ def on_test_module_finished(test_module)
185
+ Telemetry.event_finished(test_module)
304
186
  end
305
187
 
306
- def set_initial_tags(ci_span, tags)
307
- ci_span.set_default_tags
308
- ci_span.set_environment_runtime_tags
309
-
310
- ci_span.set_tags(tags)
311
- ci_span.set_tags(environment_tags)
188
+ def on_test_suite_finished(test_suite)
189
+ Telemetry.event_finished(test_suite)
312
190
  end
313
191
 
314
- def set_session_context(tags, test_session = nil)
315
- test_session ||= active_test_session
316
- tags[Ext::Test::TAG_TEST_SESSION_ID] = test_session.id.to_s if test_session
192
+ def on_test_finished(test)
193
+ @test_optimisation.stop_coverage(test)
194
+ @test_optimisation.count_skipped_test(test)
195
+
196
+ Telemetry.event_finished(test)
317
197
  end
318
198
 
319
- def set_module_context(tags, test_module = nil)
320
- test_module ||= active_test_module
321
- if test_module
322
- tags[Ext::Test::TAG_TEST_MODULE_ID] = test_module.id.to_s
323
- tags[Ext::Test::TAG_MODULE] = test_module.name
199
+ # TODO: move this to CI::Configuration::Remote
200
+ def configure_library(test_session)
201
+ # this will change when EFD is implemented
202
+ return unless itr_enabled?
203
+
204
+ remote_configuration = @remote_settings_api.fetch_library_settings(test_session)
205
+ # sometimes we can skip code coverage for default branch if there are no changes in the repository
206
+ # backend needs git metadata uploaded for this test session to check if we can skip code coverage
207
+ if remote_configuration.require_git?
208
+ Datadog.logger.debug { "Library configuration endpoint requires git upload to be finished, waiting..." }
209
+ @git_tree_upload_worker.wait_until_done
210
+
211
+ Datadog.logger.debug { "Requesting library configuration again..." }
212
+ remote_configuration = @remote_settings_api.fetch_library_settings(test_session)
213
+
214
+ if remote_configuration.require_git?
215
+ Datadog.logger.debug { "git metadata upload did not complete in time when configuring library" }
216
+ end
324
217
  end
218
+
219
+ @test_optimisation.configure(
220
+ remote_configuration.payload,
221
+ test_session: test_session,
222
+ git_tree_upload_worker: @git_tree_upload_worker
223
+ )
224
+ end
225
+
226
+ # HELPERS
227
+ def skip_tracing(block = nil)
228
+ block&.call(nil)
325
229
  end
326
230
 
327
231
  def set_codeowners(test)
@@ -330,21 +234,8 @@ module Datadog
330
234
  test.set_tag(Ext::Test::TAG_CODEOWNERS, owners) unless owners.nil?
331
235
  end
332
236
 
333
- def set_suite_context(tags, span: nil, name: nil)
334
- return if span.nil? && name.nil?
335
-
336
- test_suite = span || active_test_suite(name)
337
-
338
- if test_suite
339
- tags[Ext::Test::TAG_TEST_SUITE_ID] = test_suite.id.to_s
340
- tags[Ext::Test::TAG_SUITE] = test_suite.name
341
- else
342
- tags[Ext::Test::TAG_SUITE] = name
343
- end
344
- end
345
-
346
237
  def fix_test_suite!(test)
347
- test_suite = @global_context.fetch_single_test_suite
238
+ test_suite = @context.single_active_test_suite
348
239
  unless test_suite
349
240
  Datadog.logger.debug do
350
241
  "Trying to fix test suite for test [#{test.name}] but no single test suite is running."
@@ -361,22 +252,6 @@ module Datadog
361
252
  test.set_tag(Ext::Test::TAG_SUITE, test_suite.name)
362
253
  end
363
254
 
364
- def start_datadog_tracer_span(span_name, span_options, &block)
365
- if block
366
- Datadog::Tracing.trace(span_name, **span_options) do |tracer_span, trace|
367
- set_trace_origin(trace)
368
-
369
- yield tracer_span
370
- end
371
- else
372
- tracer_span = Datadog::Tracing.trace(span_name, **span_options)
373
- trace = Datadog::Tracing.active_trace
374
- set_trace_origin(trace)
375
-
376
- tracer_span
377
- end
378
- end
379
-
380
255
  def validate_test_suite_level_visibility_correctness(test)
381
256
  return unless test_suite_level_visibility_enabled
382
257
 
@@ -401,21 +276,6 @@ module Datadog
401
276
  end
402
277
  end
403
278
  end
404
-
405
- # TODO: use kind of event system to notify about test finished?
406
- def on_test_finished(test)
407
- @test_optimisation.stop_coverage(test)
408
- @test_optimisation.count_skipped_test(test)
409
- end
410
-
411
- def on_test_started(test)
412
- @test_optimisation.mark_if_skippable(test)
413
- @test_optimisation.start_coverage(test)
414
- end
415
-
416
- def on_test_session_finished(test_session)
417
- @test_optimisation.write_test_session_tags(test_session)
418
- end
419
279
  end
420
280
  end
421
281
  end