datadog-ci 0.5.1 → 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (45) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +16 -0
  3. data/lib/datadog/ci/configuration/components.rb +11 -7
  4. data/lib/datadog/ci/contrib/cucumber/configuration/settings.rb +1 -1
  5. data/lib/datadog/ci/contrib/cucumber/ext.rb +7 -5
  6. data/lib/datadog/ci/contrib/cucumber/formatter.rb +99 -19
  7. data/lib/datadog/ci/contrib/minitest/configuration/settings.rb +1 -1
  8. data/lib/datadog/ci/contrib/minitest/ext.rb +6 -4
  9. data/lib/datadog/ci/contrib/minitest/helpers.rb +22 -0
  10. data/lib/datadog/ci/contrib/minitest/hooks.rb +45 -17
  11. data/lib/datadog/ci/contrib/minitest/patcher.rb +7 -0
  12. data/lib/datadog/ci/contrib/minitest/plugin.rb +73 -0
  13. data/lib/datadog/ci/contrib/minitest/runnable.rb +42 -0
  14. data/lib/datadog/ci/contrib/rspec/configuration/settings.rb +1 -1
  15. data/lib/datadog/ci/contrib/rspec/example.rb +2 -2
  16. data/lib/datadog/ci/contrib/rspec/example_group.rb +46 -0
  17. data/lib/datadog/ci/contrib/rspec/ext.rb +5 -4
  18. data/lib/datadog/ci/contrib/rspec/integration.rb +1 -1
  19. data/lib/datadog/ci/contrib/rspec/patcher.rb +5 -0
  20. data/lib/datadog/ci/contrib/rspec/runner.rb +57 -0
  21. data/lib/datadog/ci/contrib/settings.rb +1 -1
  22. data/lib/datadog/ci/ext/test.rb +2 -0
  23. data/lib/datadog/ci/span.rb +24 -0
  24. data/lib/datadog/ci/test.rb +30 -0
  25. data/lib/datadog/ci/test_session.rb +8 -0
  26. data/lib/datadog/ci/test_visibility/null_recorder.rb +73 -0
  27. data/lib/datadog/ci/test_visibility/recorder.rb +30 -9
  28. data/lib/datadog/ci/version.rb +2 -2
  29. data/sig/datadog/ci/contrib/cucumber/ext.rbs +1 -5
  30. data/sig/datadog/ci/contrib/cucumber/formatter.rbs +17 -4
  31. data/sig/datadog/ci/contrib/minitest/ext.rbs +1 -5
  32. data/sig/datadog/ci/contrib/minitest/helpers.rbs +13 -0
  33. data/sig/datadog/ci/contrib/minitest/hooks.rbs +9 -1
  34. data/sig/datadog/ci/contrib/minitest/plugin.rbs +31 -0
  35. data/sig/datadog/ci/contrib/minitest/runnable.rbs +24 -0
  36. data/sig/datadog/ci/contrib/rspec/example_group.rbs +21 -0
  37. data/sig/datadog/ci/contrib/rspec/ext.rbs +2 -8
  38. data/sig/datadog/ci/contrib/rspec/runner.rbs +21 -0
  39. data/sig/datadog/ci/ext/test.rbs +2 -0
  40. data/sig/datadog/ci/span.rbs +8 -0
  41. data/sig/datadog/ci/test.rbs +5 -0
  42. data/sig/datadog/ci/test_visibility/null_recorder.rbs +45 -0
  43. data/sig/datadog/ci/test_visibility/recorder.rbs +5 -5
  44. data/sig/datadog/ci.rbs +2 -0
  45. metadata +15 -3
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 85bb3584dc8081e8f6e8531d2a600e3948f4f9ea23d551dd99df0eab9daf2a3c
4
- data.tar.gz: b6f686d49d3dbb1695c0f6e20b434b77648a118c32e1691f4a0f30b13d38dc62
3
+ metadata.gz: 63e9fdf2c856764bb9567cf89d76f27a4f327244152c510abcd4d64e180a0cc6
4
+ data.tar.gz: 963f5b534027215799efe65a108a4aa8267c2c31aa4fc1402d19d02f996fc2e9
5
5
  SHA512:
6
- metadata.gz: 8e8ae716ea7c7408c59c11efa5a3bc30e0767a02c659e231f1cec2a02d5494d451c1e2b43c7c16240cbe7c9418f004ead32faa09b08c83bcd878156fa1062ae9
7
- data.tar.gz: 15bdfb45e32660356fcc4c5726c4a640c78cfc2d5007807623f532a0b7c321f0b11a32d0a75f571a64ae263159d4b86b0a750dda5d7e8a5c33f9c110bf7682a0
6
+ metadata.gz: e94bbd5cc929f95a386cadd633b93f2a53962eefe686354712a9801a8b9865a52fc74c6401f96635a47b9001d71287cadc568ba3bb81ed764d68bdf232b85e5b
7
+ data.tar.gz: 7a33d2dc09b32798f2fcae80a96bec0e919b4c60f65283f4cf158a020ecd573e450bb925c790c822c63a86b4cf214fae4427e7d4bdb6cde28ca1105dcc95a20a
data/CHANGELOG.md CHANGED
@@ -1,5 +1,17 @@
1
1
  ## [Unreleased]
2
2
 
3
+ ## [0.6.0] - 2024-01-03
4
+
5
+ ### Added
6
+
7
+ * Test suite level visibility instrumentation for RSpec ([#86][])
8
+ * Test suite level visibility instrumentation for Cucumber ([#90][])
9
+ * Test suite level visibility instrumentation for Minitest framework ([#92][])
10
+
11
+ ### Fixed
12
+
13
+ * Do not instantiate TestVisibility::Recorder unless CI visibility is enabled ([#89][])
14
+
3
15
  ## [0.5.1] - 2023-12-11
4
16
 
5
17
  ### Fixed
@@ -153,4 +165,8 @@ Currently test suite level visibility is not used by our instrumentation: it wil
153
165
  [#82]: https://github.com/DataDog/datadog-ci-rb/issues/82
154
166
  [#84]: https://github.com/DataDog/datadog-ci-rb/issues/84
155
167
  [#85]: https://github.com/DataDog/datadog-ci-rb/issues/85
168
+ [#86]: https://github.com/DataDog/datadog-ci-rb/issues/86
156
169
  [#87]: https://github.com/DataDog/datadog-ci-rb/issues/87
170
+ [#89]: https://github.com/DataDog/datadog-ci-rb/issues/89
171
+ [#90]: https://github.com/DataDog/datadog-ci-rb/issues/90
172
+ [#92]: https://github.com/DataDog/datadog-ci-rb/issues/92
@@ -7,6 +7,7 @@ require_relative "../ext/transport"
7
7
  require_relative "../ext/settings"
8
8
  require_relative "../test_visibility/flush"
9
9
  require_relative "../test_visibility/recorder"
10
+ require_relative "../test_visibility/null_recorder"
10
11
  require_relative "../test_visibility/serializers/factories/test_level"
11
12
  require_relative "../test_visibility/serializers/factories/test_suite_level"
12
13
  require_relative "../test_visibility/transport"
@@ -21,14 +22,12 @@ module Datadog
21
22
 
22
23
  def initialize(settings)
23
24
  # Activate CI mode if enabled
24
- activate_ci!(settings) if settings.ci.enabled
25
-
26
- @ci_recorder = TestVisibility::Recorder.new(
27
- enabled: settings.ci.enabled,
28
- test_suite_level_visibility_enabled: settings.ci.experimental_test_suite_level_visibility_enabled
29
- )
25
+ if settings.ci.enabled
26
+ activate_ci!(settings)
27
+ else
28
+ @ci_recorder = TestVisibility::NullRecorder.new
29
+ end
30
30
 
31
- # Initialize normally
32
31
  super
33
32
  end
34
33
 
@@ -65,11 +64,16 @@ module Datadog
65
64
  if test_visibility_transport
66
65
  writer_options[:transport] = test_visibility_transport
67
66
  writer_options[:shutdown_timeout] = 60
67
+ writer_options[:buffer_size] = 10_000
68
68
 
69
69
  settings.tracing.test_mode.async = true
70
70
  end
71
71
 
72
72
  settings.tracing.test_mode.writer_options = writer_options
73
+
74
+ @ci_recorder = TestVisibility::Recorder.new(
75
+ test_suite_level_visibility_enabled: settings.ci.experimental_test_suite_level_visibility_enabled
76
+ )
73
77
  end
74
78
 
75
79
  def can_use_evp_proxy?(settings, agent_settings)
@@ -21,7 +21,7 @@ module Datadog
21
21
 
22
22
  option :service_name do |o|
23
23
  o.type :string
24
- o.default { Datadog.configuration.service_without_fallback || Ext::SERVICE_NAME }
24
+ o.default { Datadog.configuration.service_without_fallback || Ext::DEFAULT_SERVICE_NAME }
25
25
  end
26
26
 
27
27
  # @deprecated Will be removed in 1.0
@@ -7,14 +7,16 @@ module Datadog
7
7
  # Cucumber integration constants
8
8
  # TODO: mark as `@public_api` when GA, to protect from resource and tag name changes.
9
9
  module Ext
10
- APP = "cucumber"
11
10
  ENV_ENABLED = "DD_TRACE_CUCUMBER_ENABLED"
12
- ENV_OPERATION_NAME = "DD_TRACE_CUCUMBER_OPERATION_NAME"
11
+ DEFAULT_SERVICE_NAME = "cucumber"
12
+
13
13
  FRAMEWORK = "cucumber"
14
- OPERATION_NAME = "cucumber.test"
15
- SERVICE_NAME = "cucumber"
14
+
16
15
  STEP_SPAN_TYPE = "step"
17
- TEST_TYPE = "test"
16
+
17
+ # TODO: remove in 1.0
18
+ ENV_OPERATION_NAME = "DD_TRACE_CUCUMBER_OPERATION_NAME"
19
+ OPERATION_NAME = "cucumber.test"
18
20
  end
19
21
  end
20
22
  end
@@ -9,31 +9,60 @@ module Datadog
9
9
  module Cucumber
10
10
  # Defines collection of instrumented Cucumber events
11
11
  class Formatter
12
- attr_reader :config, :current_feature_span, :current_step_span
12
+ attr_reader :config
13
13
  private :config
14
- private :current_feature_span, :current_step_span
15
14
 
16
15
  def initialize(config)
17
16
  @config = config
17
+ @failed_tests_count = 0
18
+
19
+ @current_test_suite = nil
20
+ @failed_tests_in_current_test_suite = 0
18
21
 
19
22
  bind_events(config)
20
23
  end
21
24
 
22
25
  def bind_events(config)
26
+ config.on_event :test_run_started, &method(:on_test_run_started)
27
+ config.on_event :test_run_finished, &method(:on_test_run_finished)
23
28
  config.on_event :test_case_started, &method(:on_test_case_started)
24
29
  config.on_event :test_case_finished, &method(:on_test_case_finished)
25
30
  config.on_event :test_step_started, &method(:on_test_step_started)
26
31
  config.on_event :test_step_finished, &method(:on_test_step_finished)
27
32
  end
28
33
 
34
+ def on_test_run_started(event)
35
+ test_session = CI.start_test_session(
36
+ tags: {
37
+ CI::Ext::Test::TAG_FRAMEWORK => Ext::FRAMEWORK,
38
+ CI::Ext::Test::TAG_FRAMEWORK_VERSION => CI::Contrib::Cucumber::Integration.version.to_s,
39
+ CI::Ext::Test::TAG_TYPE => CI::Ext::Test::TEST_TYPE
40
+ },
41
+ service: configuration[:service_name]
42
+ )
43
+ CI.start_test_module(test_session.name)
44
+ end
45
+
46
+ def on_test_run_finished(event)
47
+ if event.respond_to?(:success)
48
+ finish_session(event.success)
49
+ else
50
+ finish_session(@failed_tests_count.zero?)
51
+ end
52
+ end
53
+
29
54
  def on_test_case_started(event)
55
+ test_suite_name = event.test_case.location.file
56
+
57
+ start_test_suite(test_suite_name) unless same_test_suite_as_current?(test_suite_name)
58
+
30
59
  CI.start_test(
31
60
  event.test_case.name,
32
- event.test_case.location.file,
61
+ test_suite_name,
33
62
  tags: {
34
63
  CI::Ext::Test::TAG_FRAMEWORK => Ext::FRAMEWORK,
35
64
  CI::Ext::Test::TAG_FRAMEWORK_VERSION => CI::Contrib::Cucumber::Integration.version.to_s,
36
- CI::Ext::Test::TAG_TYPE => Ext::TEST_TYPE
65
+ CI::Ext::Test::TAG_TYPE => CI::Ext::Test::TEST_TYPE
37
66
  },
38
67
  service: configuration[:service_name]
39
68
  )
@@ -43,15 +72,17 @@ module Datadog
43
72
  test_span = CI.active_test
44
73
  return if test_span.nil?
45
74
 
46
- if event.result.skipped?
47
- test_span.skipped!
48
- elsif event.result.ok?
49
- test_span.passed!
50
- elsif event.result.failed?
51
- test_span.failed!
75
+ # We need to track overall test failures manually if we are using cucumber < 8.0 because
76
+ # TestRunFinished event does not have a success attribute before 8.0.
77
+ #
78
+ # To track whether test suite failed or passed we need to
79
+ # track the number of failed tests in the current test suite.
80
+ if event.result.failed?
81
+ @failed_tests_count += 1
82
+ @failed_tests_in_current_test_suite += 1
52
83
  end
53
84
 
54
- test_span.finish
85
+ finish_test(test_span, event.result)
55
86
  end
56
87
 
57
88
  def on_test_step_started(event)
@@ -62,18 +93,67 @@ module Datadog
62
93
  current_step_span = CI.active_span(Ext::STEP_SPAN_TYPE)
63
94
  return if current_step_span.nil?
64
95
 
65
- if event.result.skipped?
66
- current_step_span.skipped!
67
- elsif event.result.ok?
68
- current_step_span.passed!
69
- elsif event.result.failed?
70
- current_step_span.failed!(exception: event.result.exception)
96
+ finish_test(current_step_span, event.result)
97
+ end
98
+
99
+ private
100
+
101
+ def finish_test(span, result)
102
+ if result.skipped?
103
+ span.skipped!
104
+ elsif result.ok?
105
+ span.passed!
106
+ elsif result.failed?
107
+ span.failed!(exception: result.exception)
71
108
  end
109
+ span.finish
110
+ end
111
+
112
+ def finish_session(result)
113
+ finish_current_test_suite
114
+
115
+ test_session = CI.active_test_session
116
+ test_module = CI.active_test_module
117
+
118
+ return unless test_session && test_module
72
119
 
73
- current_step_span.finish
120
+ if result
121
+ test_module.passed!
122
+ test_session.passed!
123
+ else
124
+ test_module.failed!
125
+ test_session.failed!
126
+ end
127
+
128
+ test_module.finish
129
+ test_session.finish
74
130
  end
75
131
 
76
- private
132
+ def start_test_suite(test_suite_name)
133
+ finish_current_test_suite
134
+
135
+ @current_test_suite = CI.start_test_suite(test_suite_name)
136
+ end
137
+
138
+ def finish_current_test_suite
139
+ test_suite = @current_test_suite
140
+ return unless test_suite
141
+
142
+ if @failed_tests_in_current_test_suite.zero?
143
+ test_suite.passed!
144
+ else
145
+ test_suite.failed!
146
+ end
147
+ @failed_tests_in_current_test_suite = 0
148
+ test_suite.finish
149
+ end
150
+
151
+ def same_test_suite_as_current?(test_suite_name)
152
+ test_suite = @current_test_suite
153
+ return false unless test_suite
154
+
155
+ test_suite.name == test_suite_name
156
+ end
77
157
 
78
158
  def configuration
79
159
  Datadog.configuration.ci[:cucumber]
@@ -19,7 +19,7 @@ module Datadog
19
19
 
20
20
  option :service_name do |o|
21
21
  o.type :string
22
- o.default { Datadog.configuration.service_without_fallback || Ext::SERVICE_NAME }
22
+ o.default { Datadog.configuration.service_without_fallback || Ext::DEFAULT_SERVICE_NAME }
23
23
  end
24
24
 
25
25
  # @deprecated Will be removed in 1.0
@@ -7,13 +7,15 @@ module Datadog
7
7
  # Minitest integration constants
8
8
  # TODO: mark as `@public_api` when GA, to protect from resource and tag name changes.
9
9
  module Ext
10
- APP = "minitest"
11
10
  ENV_ENABLED = "DD_TRACE_MINITEST_ENABLED"
12
- ENV_OPERATION_NAME = "DD_TRACE_MINITEST_OPERATION_NAME"
11
+
13
12
  FRAMEWORK = "minitest"
13
+
14
+ DEFAULT_SERVICE_NAME = "minitest"
15
+
16
+ # TODO: remove in 1.0
17
+ ENV_OPERATION_NAME = "DD_TRACE_MINITEST_OPERATION_NAME"
14
18
  OPERATION_NAME = "minitest.test"
15
- SERVICE_NAME = "minitest"
16
- TEST_TYPE = "test"
17
19
  end
18
20
  end
19
21
  end
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Datadog
4
+ module CI
5
+ module Contrib
6
+ module Minitest
7
+ module Helpers
8
+ def self.test_suite_name(klass, method_name)
9
+ source_location, = klass.instance_method(method_name).source_location
10
+ source_file_path = Pathname.new(source_location.to_s).relative_path_from(Pathname.pwd).to_s
11
+
12
+ "#{klass.name} at #{source_file_path}"
13
+ end
14
+
15
+ def self.parallel?(klass)
16
+ klass.ancestors.include?(::Minitest::Parallel::Test)
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
@@ -2,6 +2,7 @@
2
2
 
3
3
  require_relative "../../ext/test"
4
4
  require_relative "ext"
5
+ require_relative "helpers"
5
6
 
6
7
  module Datadog
7
8
  module CI
@@ -11,22 +12,27 @@ module Datadog
11
12
  module Hooks
12
13
  def before_setup
13
14
  super
14
- return unless configuration[:enabled]
15
+ return unless datadog_configuration[:enabled]
15
16
 
16
17
  test_name = "#{class_name}##{name}"
17
18
 
18
- path, = method(name).source_location
19
- test_suite = Pathname.new(path.to_s).relative_path_from(Pathname.pwd).to_s
19
+ test_suite_name = Helpers.test_suite_name(self.class, name)
20
+ if Helpers.parallel?(self.class)
21
+ test_suite_name = "#{test_suite_name} (#{name} concurrently)"
22
+
23
+ # for parallel execution we need to start a new test suite for each test
24
+ CI.start_test_suite(test_suite_name)
25
+ end
20
26
 
21
27
  CI.start_test(
22
28
  test_name,
23
- test_suite,
29
+ test_suite_name,
24
30
  tags: {
25
31
  CI::Ext::Test::TAG_FRAMEWORK => Ext::FRAMEWORK,
26
32
  CI::Ext::Test::TAG_FRAMEWORK_VERSION => CI::Contrib::Minitest::Integration.version.to_s,
27
- CI::Ext::Test::TAG_TYPE => Ext::TEST_TYPE
33
+ CI::Ext::Test::TAG_TYPE => CI::Ext::Test::TEST_TYPE
28
34
  },
29
- service: configuration[:service_name]
35
+ service: datadog_configuration[:service_name]
30
36
  )
31
37
  end
32
38
 
@@ -34,24 +40,46 @@ module Datadog
34
40
  test_span = CI.active_test
35
41
  return super unless test_span
36
42
 
37
- case result_code
38
- when "."
39
- test_span.passed!
40
- when "E", "F"
41
- test_span.failed!(exception: failure)
42
- when "S"
43
- test_span.skipped!(reason: failure.message)
43
+ finish_test(test_span, result_code)
44
+ if Helpers.parallel?(self.class)
45
+ finish_test_suite(test_span.test_suite, result_code)
44
46
  end
45
47
 
46
- test_span.finish
47
-
48
48
  super
49
49
  end
50
50
 
51
51
  private
52
52
 
53
- def configuration
54
- ::Datadog.configuration.ci[:minitest]
53
+ def finish_test(test_span, result_code)
54
+ finish_with_result(test_span, result_code)
55
+
56
+ # mark test suite as failed if any test failed
57
+ if test_span.failed?
58
+ test_suite = test_span.test_suite
59
+ test_suite.failed! if test_suite
60
+ end
61
+ end
62
+
63
+ def finish_test_suite(test_suite, result_code)
64
+ return unless test_suite
65
+
66
+ finish_with_result(test_suite, result_code)
67
+ end
68
+
69
+ def finish_with_result(span, result_code)
70
+ case result_code
71
+ when "."
72
+ span.passed!
73
+ when "E", "F"
74
+ span.failed!(exception: failure)
75
+ when "S"
76
+ span.skipped!(reason: failure.message)
77
+ end
78
+ span.finish
79
+ end
80
+
81
+ def datadog_configuration
82
+ Datadog.configuration.ci[:minitest]
55
83
  end
56
84
  end
57
85
  end
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require_relative "hooks"
4
+ require_relative "runnable"
4
5
 
5
6
  module Datadog
6
7
  module CI
@@ -17,7 +18,13 @@ module Datadog
17
18
  end
18
19
 
19
20
  def patch
21
+ require_relative "plugin"
22
+
20
23
  ::Minitest::Test.include(Hooks)
24
+ ::Minitest.include(Plugin)
25
+ ::Minitest::Runnable.include(Runnable)
26
+
27
+ ::Minitest.extensions << "datadog_ci"
21
28
  end
22
29
  end
23
30
  end
@@ -0,0 +1,73 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "weakref"
4
+
5
+ require_relative "../../ext/test"
6
+ require_relative "ext"
7
+
8
+ module Datadog
9
+ module CI
10
+ module Contrib
11
+ module Minitest
12
+ module Plugin
13
+ def self.included(base)
14
+ base.extend(ClassMethods)
15
+ end
16
+
17
+ class DatadogReporter < ::Minitest::AbstractReporter
18
+ def initialize(minitest_reporter)
19
+ # This creates circular reference as minitest_reporter also holds reference to DatadogReporter.
20
+ # To make sure that minitest_reporter can be garbage collected, we use WeakRef.
21
+ @reporter = WeakRef.new(minitest_reporter)
22
+ end
23
+
24
+ def report
25
+ active_test_session = CI.active_test_session
26
+ active_test_module = CI.active_test_module
27
+
28
+ return unless @reporter.weakref_alive?
29
+ return if active_test_session.nil? || active_test_module.nil?
30
+
31
+ if @reporter.passed?
32
+ active_test_module.passed!
33
+ active_test_session.passed!
34
+ else
35
+ active_test_module.failed!
36
+ active_test_session.failed!
37
+ end
38
+
39
+ active_test_module.finish
40
+ active_test_session.finish
41
+
42
+ nil
43
+ end
44
+ end
45
+
46
+ module ClassMethods
47
+ def plugin_datadog_ci_init(*)
48
+ return unless datadog_configuration[:enabled]
49
+
50
+ test_session = CI.start_test_session(
51
+ tags: {
52
+ CI::Ext::Test::TAG_FRAMEWORK => Ext::FRAMEWORK,
53
+ CI::Ext::Test::TAG_FRAMEWORK_VERSION => CI::Contrib::Minitest::Integration.version.to_s,
54
+ CI::Ext::Test::TAG_TYPE => CI::Ext::Test::TEST_TYPE
55
+ },
56
+ service: datadog_configuration[:service_name]
57
+ )
58
+ CI.start_test_module(test_session.name)
59
+
60
+ reporter.reporters << DatadogReporter.new(reporter)
61
+ end
62
+
63
+ private
64
+
65
+ def datadog_configuration
66
+ Datadog.configuration.ci[:minitest]
67
+ end
68
+ end
69
+ end
70
+ end
71
+ end
72
+ end
73
+ end
@@ -0,0 +1,42 @@
1
+ require_relative "helpers"
2
+
3
+ module Datadog
4
+ module CI
5
+ module Contrib
6
+ module Minitest
7
+ module Runnable
8
+ def self.included(base)
9
+ base.singleton_class.prepend(ClassMethods)
10
+ end
11
+
12
+ module ClassMethods
13
+ def run(*)
14
+ return super unless datadog_configuration[:enabled]
15
+ return super if Helpers.parallel?(self)
16
+
17
+ method = runnable_methods.first
18
+ return super if method.nil?
19
+
20
+ test_suite_name = Helpers.test_suite_name(self, method)
21
+
22
+ test_suite = Datadog::CI.start_test_suite(test_suite_name)
23
+ test_suite.passed! # will be overridden if any test fails
24
+
25
+ results = super
26
+
27
+ test_suite.finish
28
+
29
+ results
30
+ end
31
+
32
+ private
33
+
34
+ def datadog_configuration
35
+ Datadog.configuration.ci[:minitest]
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
@@ -19,7 +19,7 @@ module Datadog
19
19
 
20
20
  option :service_name do |o|
21
21
  o.type :string
22
- o.default { Datadog.configuration.service_without_fallback || Ext::SERVICE_NAME }
22
+ o.default { Datadog.configuration.service_without_fallback || Ext::DEFAULT_SERVICE_NAME }
23
23
  end
24
24
 
25
25
  # @deprecated Will be removed in 1.0
@@ -26,11 +26,11 @@ module Datadog
26
26
 
27
27
  CI.trace_test(
28
28
  test_name,
29
- metadata[:example_group][:file_path],
29
+ metadata[:example_group][:rerun_file_path],
30
30
  tags: {
31
31
  CI::Ext::Test::TAG_FRAMEWORK => Ext::FRAMEWORK,
32
32
  CI::Ext::Test::TAG_FRAMEWORK_VERSION => CI::Contrib::RSpec::Integration.version.to_s,
33
- CI::Ext::Test::TAG_TYPE => Ext::TEST_TYPE
33
+ CI::Ext::Test::TAG_TYPE => CI::Ext::Test::TEST_TYPE
34
34
  },
35
35
  service: configuration[:service_name]
36
36
  ) do |test_span|
@@ -0,0 +1,46 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "../../ext/test"
4
+ require_relative "ext"
5
+
6
+ module Datadog
7
+ module CI
8
+ module Contrib
9
+ module RSpec
10
+ # Instrument RSpec::Core::Example
11
+ module ExampleGroup
12
+ def self.included(base)
13
+ base.singleton_class.prepend(ClassMethods)
14
+ end
15
+
16
+ # Instance methods for configuration
17
+ module ClassMethods
18
+ def run(reporter = ::RSpec::Core::NullReporter)
19
+ return super unless configuration[:enabled]
20
+ return super unless top_level?
21
+
22
+ test_suite = Datadog::CI.start_test_suite(file_path)
23
+
24
+ result = super
25
+
26
+ if result
27
+ test_suite.passed!
28
+ else
29
+ test_suite.failed!
30
+ end
31
+ test_suite.finish
32
+
33
+ result
34
+ end
35
+
36
+ private
37
+
38
+ def configuration
39
+ Datadog.configuration.ci[:rspec]
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
46
+ end
@@ -7,13 +7,14 @@ module Datadog
7
7
  # RSpec integration constants
8
8
  # TODO: mark as `@public_api` when GA, to protect from resource and tag name changes.
9
9
  module Ext
10
- APP = "rspec"
10
+ FRAMEWORK = "rspec"
11
+ DEFAULT_SERVICE_NAME = "rspec"
12
+
11
13
  ENV_ENABLED = "DD_TRACE_RSPEC_ENABLED"
14
+
15
+ # TODO: remove in 1.0
12
16
  ENV_OPERATION_NAME = "DD_TRACE_RSPEC_OPERATION_NAME"
13
- FRAMEWORK = "rspec"
14
17
  OPERATION_NAME = "rspec.example"
15
- SERVICE_NAME = "rspec"
16
- TEST_TYPE = "test"
17
18
  end
18
19
  end
19
20
  end
@@ -22,7 +22,7 @@ module Datadog
22
22
  end
23
23
 
24
24
  def self.loaded?
25
- !defined?(::RSpec).nil? && !defined?(::RSpec::Core).nil? && \
25
+ !defined?(::RSpec).nil? && !defined?(::RSpec::Core).nil? &&
26
26
  !defined?(::RSpec::Core::Example).nil?
27
27
  end
28
28