datadog-ci 0.8.3 → 1.0.0.beta2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (70) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +42 -0
  3. data/LICENSE-3rdparty.csv +1 -1
  4. data/README.md +40 -55
  5. data/ext/datadog_cov/datadog_cov.c +192 -0
  6. data/ext/datadog_cov/extconf.rb +18 -0
  7. data/lib/datadog/ci/configuration/components.rb +43 -9
  8. data/lib/datadog/ci/configuration/settings.rb +7 -1
  9. data/lib/datadog/ci/contrib/cucumber/configuration/settings.rb +0 -15
  10. data/lib/datadog/ci/contrib/cucumber/ext.rb +1 -5
  11. data/lib/datadog/ci/contrib/cucumber/formatter.rb +13 -18
  12. data/lib/datadog/ci/contrib/cucumber/integration.rb +1 -2
  13. data/lib/datadog/ci/contrib/cucumber/patcher.rb +3 -0
  14. data/lib/datadog/ci/contrib/cucumber/step.rb +27 -0
  15. data/lib/datadog/ci/contrib/minitest/configuration/settings.rb +0 -15
  16. data/lib/datadog/ci/contrib/minitest/ext.rb +1 -5
  17. data/lib/datadog/ci/contrib/minitest/helpers.rb +1 -2
  18. data/lib/datadog/ci/contrib/minitest/hooks.rb +4 -2
  19. data/lib/datadog/ci/contrib/minitest/integration.rb +1 -1
  20. data/lib/datadog/ci/contrib/rspec/configuration/settings.rb +0 -15
  21. data/lib/datadog/ci/contrib/rspec/example.rb +25 -23
  22. data/lib/datadog/ci/contrib/rspec/ext.rb +0 -4
  23. data/lib/datadog/ci/contrib/rspec/integration.rb +1 -2
  24. data/lib/datadog/ci/contrib/settings.rb +0 -3
  25. data/lib/datadog/ci/ext/environment/providers/base.rb +1 -1
  26. data/lib/datadog/ci/ext/environment/providers/bitbucket.rb +1 -1
  27. data/lib/datadog/ci/ext/environment/providers/local_git.rb +8 -79
  28. data/lib/datadog/ci/ext/environment.rb +11 -16
  29. data/lib/datadog/ci/ext/settings.rb +1 -0
  30. data/lib/datadog/ci/ext/test.rb +5 -0
  31. data/lib/datadog/ci/ext/transport.rb +12 -0
  32. data/lib/datadog/ci/git/local_repository.rb +238 -0
  33. data/lib/datadog/ci/git/packfiles.rb +70 -0
  34. data/lib/datadog/ci/git/search_commits.rb +77 -0
  35. data/lib/datadog/ci/git/tree_uploader.rb +90 -0
  36. data/lib/datadog/ci/git/upload_packfile.rb +66 -0
  37. data/lib/datadog/ci/git/user.rb +29 -0
  38. data/lib/datadog/ci/itr/coverage/ddcov.rb +14 -0
  39. data/lib/datadog/ci/itr/coverage/event.rb +81 -0
  40. data/lib/datadog/ci/itr/coverage/transport.rb +42 -0
  41. data/lib/datadog/ci/itr/coverage/writer.rb +108 -0
  42. data/lib/datadog/ci/itr/runner.rb +143 -6
  43. data/lib/datadog/ci/itr/skippable.rb +106 -0
  44. data/lib/datadog/ci/span.rb +9 -0
  45. data/lib/datadog/ci/test.rb +20 -14
  46. data/lib/datadog/ci/test_module.rb +2 -2
  47. data/lib/datadog/ci/test_session.rb +2 -2
  48. data/lib/datadog/ci/test_suite.rb +2 -2
  49. data/lib/datadog/ci/test_visibility/context/global.rb +1 -3
  50. data/lib/datadog/ci/test_visibility/null_recorder.rb +5 -2
  51. data/lib/datadog/ci/test_visibility/recorder.rb +63 -8
  52. data/lib/datadog/ci/test_visibility/serializers/base.rb +1 -1
  53. data/lib/datadog/ci/test_visibility/serializers/factories/test_level.rb +1 -1
  54. data/lib/datadog/ci/test_visibility/serializers/factories/test_suite_level.rb +1 -1
  55. data/lib/datadog/ci/test_visibility/transport.rb +11 -54
  56. data/lib/datadog/ci/transport/api/agentless.rb +8 -1
  57. data/lib/datadog/ci/transport/api/base.rb +23 -0
  58. data/lib/datadog/ci/transport/api/builder.rb +9 -1
  59. data/lib/datadog/ci/transport/api/evp_proxy.rb +8 -0
  60. data/lib/datadog/ci/transport/event_platform_transport.rb +88 -0
  61. data/lib/datadog/ci/transport/http.rb +43 -6
  62. data/lib/datadog/ci/transport/remote_settings_api.rb +12 -6
  63. data/lib/datadog/ci/utils/configuration.rb +2 -2
  64. data/lib/datadog/ci/utils/git.rb +6 -67
  65. data/lib/datadog/ci/utils/parsing.rb +16 -0
  66. data/lib/datadog/ci/utils/test_run.rb +13 -0
  67. data/lib/datadog/ci/version.rb +5 -5
  68. data/lib/datadog/ci/worker.rb +35 -0
  69. data/lib/datadog/ci.rb +4 -0
  70. metadata +36 -4
@@ -0,0 +1,42 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "event"
4
+ require_relative "../../transport/event_platform_transport"
5
+
6
+ module Datadog
7
+ module CI
8
+ module ITR
9
+ module Coverage
10
+ class Transport < Datadog::CI::Transport::EventPlatformTransport
11
+ private
12
+
13
+ def send_payload(encoded_payload)
14
+ api.citestcov_request(
15
+ path: Ext::Transport::TEST_COVERAGE_INTAKE_PATH,
16
+ payload: encoded_payload
17
+ )
18
+ end
19
+
20
+ def encode_events(events)
21
+ events.filter_map do |event|
22
+ next unless event.valid?
23
+
24
+ encoded = encoder.encode(event)
25
+ next if event_too_large?(event, encoded)
26
+
27
+ encoded
28
+ end
29
+ end
30
+
31
+ def write_payload_header(packer)
32
+ packer.write_map_header(2)
33
+ packer.write("version")
34
+ packer.write(2)
35
+
36
+ packer.write("coverages")
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,108 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "datadog/core/workers/async"
4
+ require "datadog/core/workers/queue"
5
+ require "datadog/core/workers/polling"
6
+
7
+ require "datadog/core/buffer/cruby"
8
+ require "datadog/core/buffer/thread_safe"
9
+
10
+ require "datadog/core/environment/ext"
11
+
12
+ module Datadog
13
+ module CI
14
+ module ITR
15
+ module Coverage
16
+ class Writer
17
+ include Core::Workers::Queue
18
+ include Core::Workers::Polling
19
+
20
+ attr_reader :transport
21
+
22
+ DEFAULT_BUFFER_MAX_SIZE = 10_000
23
+ DEFAULT_SHUTDOWN_TIMEOUT = 60
24
+
25
+ def initialize(transport:, options: {})
26
+ @transport = transport
27
+
28
+ # Workers::Polling settings
29
+ self.enabled = options.fetch(:enabled, true)
30
+
31
+ # Workers::Async::Thread settings
32
+ self.fork_policy = Core::Workers::Async::Thread::FORK_POLICY_RESTART
33
+
34
+ # Workers::IntervalLoop settings
35
+ self.loop_base_interval = options[:interval] if options.key?(:interval)
36
+ self.loop_back_off_ratio = options[:back_off_ratio] if options.key?(:back_off_ratio)
37
+ self.loop_back_off_max = options[:back_off_max] if options.key?(:back_off_max)
38
+
39
+ @buffer_size = options.fetch(:buffer_size, DEFAULT_BUFFER_MAX_SIZE)
40
+
41
+ self.buffer = buffer_klass.new(@buffer_size)
42
+
43
+ @shutdown_timeout = options.fetch(:shutdown_timeout, DEFAULT_SHUTDOWN_TIMEOUT)
44
+
45
+ @stopped = false
46
+ end
47
+
48
+ def write(event)
49
+ return if @stopped
50
+
51
+ # Start worker thread. If the process has forked, it will trigger #after_fork to
52
+ # reconfigure the worker accordingly.
53
+ perform
54
+
55
+ enqueue(event)
56
+ end
57
+
58
+ def perform(*events)
59
+ responses = transport.send_events(events)
60
+
61
+ loop_back_off! if responses.find(&:server_error?)
62
+
63
+ nil
64
+ end
65
+
66
+ def stop(force_stop = false, timeout = @shutdown_timeout)
67
+ @stopped = true
68
+
69
+ buffer.close if running?
70
+
71
+ super
72
+ end
73
+
74
+ def enqueue(event)
75
+ buffer.push(event)
76
+ end
77
+
78
+ def dequeue
79
+ buffer.pop
80
+ end
81
+
82
+ def work_pending?
83
+ !buffer.empty?
84
+ end
85
+
86
+ def async?
87
+ true
88
+ end
89
+
90
+ def after_fork
91
+ # In multiprocess environments, forks will share the same buffer until its written to.
92
+ # A.K.A. copy-on-write. We don't want forks to write events generated from another process.
93
+ # Instead, we reset it after the fork. (Make sure any enqueue operations happen after this.)
94
+ self.buffer = buffer_klass.new(@buffer_size)
95
+ end
96
+
97
+ def buffer_klass
98
+ if Core::Environment::Ext::RUBY_ENGINE == "ruby"
99
+ Core::Buffer::CRuby
100
+ else
101
+ Core::Buffer::ThreadSafe
102
+ end
103
+ end
104
+ end
105
+ end
106
+ end
107
+ end
108
+ end
@@ -1,8 +1,19 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "pp"
4
+
5
+ require "datadog/core/utils/forking"
6
+
3
7
  require_relative "../ext/test"
4
8
  require_relative "../ext/transport"
5
9
 
10
+ require_relative "../git/local_repository"
11
+
12
+ require_relative "../utils/parsing"
13
+
14
+ require_relative "coverage/event"
15
+ require_relative "skippable"
16
+
6
17
  module Datadog
7
18
  module CI
8
19
  module ITR
@@ -10,26 +21,44 @@ module Datadog
10
21
  # Integrates with backend to provide test impact analysis data and
11
22
  # skip tests that are not impacted by the changes
12
23
  class Runner
24
+ include Core::Utils::Forking
25
+
26
+ attr_reader :correlation_id, :skippable_tests, :skipped_tests_count
27
+
13
28
  def initialize(
29
+ dd_env:,
30
+ api: nil,
31
+ coverage_writer: nil,
14
32
  enabled: false
15
33
  )
16
34
  @enabled = enabled
35
+ @api = api
36
+ @dd_env = dd_env
37
+
17
38
  @test_skipping_enabled = false
18
39
  @code_coverage_enabled = false
19
40
 
41
+ @coverage_writer = coverage_writer
42
+
43
+ @correlation_id = nil
44
+ @skippable_tests = []
45
+
46
+ @skipped_tests_count = 0
47
+ @mutex = Mutex.new
48
+
20
49
  Datadog.logger.debug("ITR Runner initialized with enabled: #{@enabled}")
21
50
  end
22
51
 
23
- def configure(remote_configuration, test_session)
52
+ def configure(remote_configuration, test_session:, git_tree_upload_worker:)
24
53
  Datadog.logger.debug("Configuring ITR Runner with remote configuration: #{remote_configuration}")
25
54
 
26
- @enabled = convert_to_bool(
55
+ @enabled = Utils::Parsing.convert_to_bool(
27
56
  remote_configuration.fetch(Ext::Transport::DD_API_SETTINGS_RESPONSE_ITR_ENABLED_KEY, false)
28
57
  )
29
- @test_skipping_enabled = @enabled && convert_to_bool(
58
+ @test_skipping_enabled = @enabled && Utils::Parsing.convert_to_bool(
30
59
  remote_configuration.fetch(Ext::Transport::DD_API_SETTINGS_RESPONSE_TESTS_SKIPPING_KEY, false)
31
60
  )
32
- @code_coverage_enabled = @enabled && convert_to_bool(
61
+ @code_coverage_enabled = @enabled && Utils::Parsing.convert_to_bool(
33
62
  remote_configuration.fetch(Ext::Transport::DD_API_SETTINGS_RESPONSE_CODE_COVERAGE_KEY, false)
34
63
  )
35
64
 
@@ -41,7 +70,11 @@ module Datadog
41
70
  # we skip tests, not suites
42
71
  test_session.set_tag(Ext::Test::TAG_ITR_TEST_SKIPPING_TYPE, Ext::Test::ITR_TEST_SKIPPING_MODE)
43
72
 
73
+ load_datadog_cov! if @code_coverage_enabled
74
+
44
75
  Datadog.logger.debug("Configured ITR Runner with enabled: #{@enabled}, skipping_tests: #{@test_skipping_enabled}, code_coverage: #{@code_coverage_enabled}")
76
+
77
+ fetch_skippable_tests(test_session: test_session, git_tree_upload_worker: git_tree_upload_worker)
45
78
  end
46
79
 
47
80
  def enabled?
@@ -56,10 +89,114 @@ module Datadog
56
89
  @code_coverage_enabled
57
90
  end
58
91
 
92
+ def start_coverage(test)
93
+ return if !enabled? || !code_coverage?
94
+
95
+ coverage_collector&.start
96
+ end
97
+
98
+ def stop_coverage(test)
99
+ return if !enabled? || !code_coverage?
100
+
101
+ coverage = coverage_collector&.stop
102
+ return if coverage.nil? || coverage.empty?
103
+
104
+ return if test.skipped?
105
+
106
+ test_source_file = test.source_file
107
+
108
+ # cucumber's gherkin files are not covered by the code coverage collector
109
+ ensure_test_source_covered(test_source_file, coverage) unless test_source_file.nil?
110
+
111
+ event = Coverage::Event.new(
112
+ test_id: test.id.to_s,
113
+ test_suite_id: test.test_suite_id.to_s,
114
+ test_session_id: test.test_session_id.to_s,
115
+ coverage: coverage
116
+ )
117
+
118
+ Datadog.logger.debug { "Writing coverage event \n #{event.pretty_inspect}" }
119
+
120
+ write(event)
121
+
122
+ event
123
+ end
124
+
125
+ def mark_if_skippable(test)
126
+ return if !enabled? || !skipping_tests?
127
+
128
+ skippable_test_id = Utils::TestRun.skippable_test_id(test.name, test.test_suite_name, test.parameters)
129
+ if @skippable_tests.include?(skippable_test_id)
130
+ test.set_tag(Ext::Test::TAG_ITR_SKIPPED_BY_ITR, "true")
131
+
132
+ Datadog.logger.debug { "Marked test as skippable: #{skippable_test_id}" }
133
+ else
134
+ Datadog.logger.debug { "Test is not skippable: #{skippable_test_id}" }
135
+ end
136
+ end
137
+
138
+ def count_skipped_test(test)
139
+ if forked?
140
+ Datadog.logger.warn { "ITR is not supported for forking test runners yet" }
141
+ return
142
+ end
143
+
144
+ return if !test.skipped? || !test.skipped_by_itr?
145
+
146
+ @mutex.synchronize do
147
+ @skipped_tests_count += 1
148
+ end
149
+ end
150
+
151
+ def write_test_session_tags(test_session)
152
+ return if !enabled?
153
+
154
+ test_session.set_tag(Ext::Test::TAG_ITR_TESTS_SKIPPED, @skipped_tests_count.positive?.to_s)
155
+ test_session.set_tag(Ext::Test::TAG_ITR_TEST_SKIPPING_COUNT, @skipped_tests_count)
156
+ end
157
+
158
+ def shutdown!
159
+ @coverage_writer&.stop
160
+ end
161
+
59
162
  private
60
163
 
61
- def convert_to_bool(value)
62
- value.to_s == "true"
164
+ def write(event)
165
+ # skip sending events if writer is not configured
166
+ @coverage_writer&.write(event)
167
+ end
168
+
169
+ def coverage_collector
170
+ Thread.current[:dd_coverage_collector] ||= Coverage::DDCov.new(root: Git::LocalRepository.root)
171
+ end
172
+
173
+ def load_datadog_cov!
174
+ require "datadog_cov.#{RUBY_VERSION}_#{RUBY_PLATFORM}"
175
+ rescue LoadError => e
176
+ Datadog.logger.error("Failed to load coverage collector: #{e}. Code coverage will not be collected.")
177
+
178
+ @code_coverage_enabled = false
179
+ end
180
+
181
+ def ensure_test_source_covered(test_source_file, coverage)
182
+ absolute_test_source_file_path = File.join(Git::LocalRepository.root, test_source_file)
183
+ return if coverage.key?(absolute_test_source_file_path)
184
+
185
+ coverage[absolute_test_source_file_path] = true
186
+ end
187
+
188
+ def fetch_skippable_tests(test_session:, git_tree_upload_worker:)
189
+ return unless skipping_tests?
190
+
191
+ # we can only request skippable tests if git metadata is already uploaded
192
+ git_tree_upload_worker.wait_until_done
193
+
194
+ skippable_response = Skippable.new(api: @api, dd_env: @dd_env).fetch_skippable_tests(test_session)
195
+ @correlation_id = skippable_response.correlation_id
196
+ @skippable_tests = skippable_response.tests
197
+
198
+ Datadog.logger.debug { "Fetched skippable tests: \n #{@skippable_tests}" }
199
+ Datadog.logger.debug { "ITR correlation ID: #{@correlation_id}" }
63
200
  end
64
201
  end
65
202
  end
@@ -0,0 +1,106 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "json"
4
+
5
+ require_relative "../ext/transport"
6
+ require_relative "../ext/test"
7
+ require_relative "../utils/test_run"
8
+
9
+ module Datadog
10
+ module CI
11
+ module ITR
12
+ class Skippable
13
+ class Response
14
+ def initialize(http_response)
15
+ @http_response = http_response
16
+ @json = nil
17
+ end
18
+
19
+ def ok?
20
+ resp = @http_response
21
+ !resp.nil? && resp.ok?
22
+ end
23
+
24
+ def correlation_id
25
+ payload.dig("meta", "correlation_id")
26
+ end
27
+
28
+ def tests
29
+ res = Set.new
30
+
31
+ payload.fetch("data", [])
32
+ .each do |test_data|
33
+ next unless test_data["type"] == Ext::Test::ITR_TEST_SKIPPING_MODE
34
+
35
+ attrs = test_data["attributes"] || {}
36
+ res << Utils::TestRun.skippable_test_id(attrs["name"], attrs["suite"], attrs["parameters"])
37
+ end
38
+
39
+ res
40
+ end
41
+
42
+ private
43
+
44
+ def payload
45
+ cached = @json
46
+ return cached unless cached.nil?
47
+
48
+ resp = @http_response
49
+ return @json = {} if resp.nil? || !ok?
50
+
51
+ begin
52
+ @json = JSON.parse(resp.payload)
53
+ rescue JSON::ParserError => e
54
+ Datadog.logger.error("Failed to parse skippable tests response payload: #{e}. Payload was: #{resp.payload}")
55
+ @json = {}
56
+ end
57
+ end
58
+ end
59
+
60
+ def initialize(dd_env:, api: nil)
61
+ @api = api
62
+ @dd_env = dd_env
63
+ end
64
+
65
+ def fetch_skippable_tests(test_session)
66
+ api = @api
67
+ return Response.new(nil) unless api
68
+
69
+ request_payload = payload(test_session)
70
+ Datadog.logger.debug("Fetching skippable tests with request: #{request_payload}")
71
+
72
+ http_response = api.api_request(
73
+ path: Ext::Transport::DD_API_SKIPPABLE_TESTS_PATH,
74
+ payload: request_payload
75
+ )
76
+
77
+ Response.new(http_response)
78
+ end
79
+
80
+ private
81
+
82
+ def payload(test_session)
83
+ {
84
+ "data" => {
85
+ "type" => Ext::Transport::DD_API_SKIPPABLE_TESTS_TYPE,
86
+ "attributes" => {
87
+ "test_level" => Ext::Test::ITR_TEST_SKIPPING_MODE,
88
+ "service" => test_session.service,
89
+ "env" => @dd_env,
90
+ "repository_url" => test_session.git_repository_url,
91
+ "sha" => test_session.git_commit_sha,
92
+ "configurations" => {
93
+ Ext::Test::TAG_OS_PLATFORM => test_session.os_platform,
94
+ Ext::Test::TAG_OS_ARCHITECTURE => test_session.os_architecture,
95
+ Ext::Test::TAG_OS_VERSION => test_session.os_version,
96
+ Ext::Test::TAG_RUNTIME_NAME => test_session.runtime_name,
97
+ Ext::Test::TAG_RUNTIME_VERSION => test_session.runtime_version
98
+ }
99
+ }
100
+ }
101
+ }.to_json
102
+ end
103
+ end
104
+ end
105
+ end
106
+ end
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "datadog/core/environment/platform"
4
+
3
5
  require_relative "ext/test"
4
6
  require_relative "utils/test_run"
5
7
 
@@ -151,6 +153,12 @@ module Datadog
151
153
  tracer_span.get_tag(Ext::Test::TAG_OS_PLATFORM)
152
154
  end
153
155
 
156
+ # Returns the OS version extracted from the environment.
157
+ # @return [String] OS version.
158
+ def os_version
159
+ tracer_span.get_tag(Ext::Test::TAG_OS_VERSION)
160
+ end
161
+
154
162
  # Returns the runtime name extracted from the environment.
155
163
  # @return [String] runtime name.
156
164
  def runtime_name
@@ -166,6 +174,7 @@ module Datadog
166
174
  def set_environment_runtime_tags
167
175
  tracer_span.set_tag(Ext::Test::TAG_OS_ARCHITECTURE, ::RbConfig::CONFIG["host_cpu"])
168
176
  tracer_span.set_tag(Ext::Test::TAG_OS_PLATFORM, ::RbConfig::CONFIG["host_os"])
177
+ tracer_span.set_tag(Ext::Test::TAG_OS_VERSION, Core::Environment::Platform.kernel_release)
169
178
  tracer_span.set_tag(Ext::Test::TAG_RUNTIME_NAME, Core::Environment::Ext::LANG_ENGINE)
170
179
  tracer_span.set_tag(Ext::Test::TAG_RUNTIME_VERSION, Core::Environment::Ext::ENGINE_VERSION)
171
180
  tracer_span.set_tag(Ext::Test::TAG_COMMAND, Utils::TestRun.command)
@@ -3,6 +3,7 @@
3
3
  require "json"
4
4
 
5
5
  require_relative "span"
6
+ require_relative "utils/test_run"
6
7
 
7
8
  module Datadog
8
9
  module CI
@@ -18,9 +19,9 @@ module Datadog
18
19
  # Finishes the current test.
19
20
  # @return [void]
20
21
  def finish
21
- super
22
-
23
22
  recorder.deactivate_test
23
+
24
+ super
24
25
  end
25
26
 
26
27
  # Running test suite that this test is part of (if any).
@@ -62,6 +63,12 @@ module Datadog
62
63
  get_tag(Ext::Test::TAG_SOURCE_FILE)
63
64
  end
64
65
 
66
+ # Returns "true" if the test is skipped by the intelligent test runner.
67
+ # @return [Boolean] true if the test is skipped by the intelligent test runner, false otherwise.
68
+ def skipped_by_itr?
69
+ get_tag(Ext::Test::TAG_ITR_SKIPPED_BY_ITR) == "true"
70
+ end
71
+
65
72
  # Sets the status of the span to "pass".
66
73
  # @return [void]
67
74
  def passed!
@@ -89,7 +96,7 @@ module Datadog
89
96
  record_test_result(Ext::Test::Status::SKIP)
90
97
  end
91
98
 
92
- # Sets the parameters for this test (e.g. Cucumber example or RSpec shared specs).
99
+ # Sets the parameters for this test (e.g. Cucumber example or RSpec specs).
93
100
  # Parameters are needed to compute test fingerprint to distinguish between different tests having same names.
94
101
  #
95
102
  # @param [Hash] arguments the arguments that test accepts as key-value hash
@@ -98,22 +105,21 @@ module Datadog
98
105
  def set_parameters(arguments, metadata = {})
99
106
  return if arguments.nil?
100
107
 
101
- set_tag(
102
- Ext::Test::TAG_PARAMETERS,
103
- JSON.generate(
104
- {
105
- arguments: arguments,
106
- metadata: metadata
107
- }
108
- )
109
- )
108
+ set_tag(Ext::Test::TAG_PARAMETERS, Utils::TestRun.test_parameters(arguments: arguments, metadata: metadata))
109
+ end
110
+
111
+ # Gets the parameters for this test (e.g. Cucumber example or RSpec specs) as a serialized JSON.
112
+ #
113
+ # @return [String] the serialized JSON of the parameters
114
+ # @return [nil] if this test does not have parameters
115
+ def parameters
116
+ get_tag(Ext::Test::TAG_PARAMETERS)
110
117
  end
111
118
 
112
119
  private
113
120
 
114
121
  def record_test_result(datadog_status)
115
- suite = test_suite
116
- suite.record_test_result(datadog_status) if suite
122
+ test_suite&.record_test_result(datadog_status)
117
123
  end
118
124
  end
119
125
  end
@@ -14,9 +14,9 @@ module Datadog
14
14
  # Finishes this test module.
15
15
  # @return [void]
16
16
  def finish
17
- super
18
-
19
17
  recorder.deactivate_test_module
18
+
19
+ super
20
20
  end
21
21
  end
22
22
  end
@@ -15,9 +15,9 @@ module Datadog
15
15
  # Finishes the current test session.
16
16
  # @return [void]
17
17
  def finish
18
- super
19
-
20
18
  recorder.deactivate_test_session
19
+
20
+ super
21
21
  end
22
22
 
23
23
  # Return the test session's name which is equal to test command used
@@ -26,9 +26,9 @@ module Datadog
26
26
  # we try to derive test suite status from execution stats if no status was set explicitly
27
27
  set_status_from_stats! if undefined?
28
28
 
29
- super
30
-
31
29
  recorder.deactivate_test_suite(name)
30
+
31
+ super
32
32
  end
33
33
  end
34
34
 
@@ -55,9 +55,7 @@ module Datadog
55
55
 
56
56
  def service
57
57
  @mutex.synchronize do
58
- # thank you RBS for this weirdness
59
- test_session = @test_session
60
- test_session.service if test_session
58
+ @test_session&.service
61
59
  end
62
60
  end
63
61
 
@@ -23,7 +23,7 @@ module Datadog
23
23
  skip_tracing(block)
24
24
  end
25
25
 
26
- def trace(type, span_name, tags: {}, &block)
26
+ def trace(span_name, type: "span", tags: {}, &block)
27
27
  skip_tracing(block)
28
28
  end
29
29
 
@@ -42,10 +42,13 @@ module Datadog
42
42
  def active_test_suite(test_suite_name)
43
43
  end
44
44
 
45
+ def shutdown!
46
+ end
47
+
45
48
  private
46
49
 
47
50
  def skip_tracing(block = nil)
48
- block.call(nil) if block
51
+ block&.call(nil)
49
52
  end
50
53
  end
51
54
  end