diff --git a/Rakefile b/Rakefile index f2633a77..b2106288 100644 --- a/Rakefile +++ b/Rakefile @@ -76,9 +76,6 @@ TEST_METADATA = { "knapsack_rspec" => { "knapsack_pro-7-rspec-3" => "✅ 2.7 / ✅ 3.0 / ✅ 3.1 / ✅ 3.2 / ✅ 3.3 / ✅ 3.4 / ❌ jruby" }, - "knapsack_rspec_go" => { - "knapsack_pro-7-rspec-3" => "✅ 2.7 / ✅ 3.0 / ✅ 3.1 / ✅ 3.2 / ✅ 3.3 / ✅ 3.4 / ❌ jruby" - }, "selenium" => { "selenium-4-capybara-3" => "❌ 2.7 / ✅ 3.0 / ✅ 3.1 / ✅ 3.2 / ✅ 3.3 / ❌ 3.4 / ✅ jruby" }, @@ -156,7 +153,6 @@ namespace :spec do ci_queue_minitest ci_queue_rspec knapsack_rspec - knapsack_rspec_go selenium timecop ].each do |contrib| desc "" # "Explicitly hiding from `rake -T`" diff --git a/lib/datadog/ci.rb b/lib/datadog/ci.rb index 7d1828fa..a3ddfd04 100644 --- a/lib/datadog/ci.rb +++ b/lib/datadog/ci.rb @@ -406,9 +406,16 @@ def test_optimisation end # Integrations + +# Test frameworks (manual instrumentation) require_relative "ci/contrib/cucumber/integration" -require_relative "ci/contrib/rspec/integration" require_relative "ci/contrib/minitest/integration" +require_relative "ci/contrib/rspec/integration" + +# Test runners (instrumented automatically when corresponding frameworks are instrumented) +require_relative "ci/contrib/knapsack/integration" + +# Additional test libraries (auto instrumented later on test session start) require_relative "ci/contrib/selenium/integration" require_relative "ci/contrib/simplecov/integration" diff --git a/lib/datadog/ci/configuration/settings.rb b/lib/datadog/ci/configuration/settings.rb index 8212913a..45188bc3 100644 --- a/lib/datadog/ci/configuration/settings.rb +++ b/lib/datadog/ci/configuration/settings.rb @@ -1,5 +1,6 @@ # frozen_string_literal: true +require_relative "../contrib/instrumentation" require_relative "../ext/settings" require_relative "../utils/bundle" @@ -8,8 +9,6 @@ module CI module Configuration # Adds CI behavior to ddtrace settings module Settings - InvalidIntegrationError = Class.new(StandardError) - def self.extended(base) base = base.singleton_class unless base.is_a?(Class) add_settings!(base) @@ -126,23 +125,11 @@ def self.add_settings!(base) define_method(:instrument) do |integration_name, options = {}, &block| return unless enabled - integration = fetch_integration(integration_name) - integration.configure(options, &block) - - return unless integration.enabled - - patch_results = integration.patch - next if patch_results == true - - error_message = <<-ERROR - Available?: #{patch_results[:available]}, Loaded?: #{patch_results[:loaded]}, - Compatible?: #{patch_results[:compatible]}, Patchable?: #{patch_results[:patchable]}" - ERROR - Datadog.logger.warn("Unable to patch #{integration_name} (#{error_message})") + Contrib::Instrumentation.instrument(integration_name, options, &block) end define_method(:[]) do |integration_name| - fetch_integration(integration_name).configuration + Contrib::Instrumentation.fetch_integration(integration_name).configuration end option :trace_flush @@ -151,11 +138,6 @@ def self.add_settings!(base) o.type :hash o.default({}) end - - define_method(:fetch_integration) do |name| - Datadog::CI::Contrib::Integration.registry[name] || - raise(InvalidIntegrationError, "'#{name}' is not a valid integration.") - end end end end diff --git a/lib/datadog/ci/contrib/contrib.rb b/lib/datadog/ci/contrib/contrib.rb deleted file mode 100644 index 457a7e74..00000000 --- a/lib/datadog/ci/contrib/contrib.rb +++ /dev/null @@ -1,31 +0,0 @@ -# frozen_string_literal: true - -require_relative "integration" - -module Datadog - module CI - module Contrib - # This method auto instruments all test libraries (ex: selenium-webdriver). - # It is intended to be called when test session starts to add additional capabilities to test visibility. - # - # This method does not automatically instrument test frameworks (ex: RSpec, Cucumber, etc), it requires - # test framework to be already instrumented. - def self.auto_instrument_on_session_start! - Datadog.logger.debug("Auto instrumenting all integrations...") - - Integration.registry.each do |name, integration| - next unless integration.auto_instrument? - - Datadog.logger.debug "#{name} is allowed to be auto instrumented" - - patch_results = integration.patch - if patch_results == true - Datadog.logger.debug("#{name} is patched") - else - Datadog.logger.debug("#{name} is not patched (#{patch_results})") - end - end - end - end - end -end diff --git a/lib/datadog/ci/contrib/cucumber/formatter.rb b/lib/datadog/ci/contrib/cucumber/formatter.rb index 95d7aa4d..456588a2 100644 --- a/lib/datadog/ci/contrib/cucumber/formatter.rb +++ b/lib/datadog/ci/contrib/cucumber/formatter.rb @@ -3,6 +3,7 @@ require_relative "../../ext/test" require_relative "../../git/local_repository" require_relative "../../utils/test_run" +require_relative "../instrumentation" require_relative "ext" module Datadog @@ -38,9 +39,9 @@ def on_test_run_started(event) test_visibility_component.start_test_session( tags: { CI::Ext::Test::TAG_FRAMEWORK => Ext::FRAMEWORK, - CI::Ext::Test::TAG_FRAMEWORK_VERSION => CI::Contrib::Cucumber::Integration.version.to_s + CI::Ext::Test::TAG_FRAMEWORK_VERSION => datadog_integration.version.to_s }, - service: configuration[:service_name] + service: datadog_configuration[:service_name] ) test_visibility_component.start_test_module(Ext::FRAMEWORK) end @@ -61,7 +62,7 @@ def on_test_case_started(event) # @type var tags: Hash[String, String] tags = { CI::Ext::Test::TAG_FRAMEWORK => Ext::FRAMEWORK, - CI::Ext::Test::TAG_FRAMEWORK_VERSION => CI::Contrib::Cucumber::Integration.version.to_s, + CI::Ext::Test::TAG_FRAMEWORK_VERSION => datadog_integration.version.to_s, CI::Ext::Test::TAG_SOURCE_FILE => Git::LocalRepository.relative_to_root(event.test_case.location.file), CI::Ext::Test::TAG_SOURCE_START => event.test_case.location.line.to_s } @@ -81,7 +82,7 @@ def on_test_case_started(event) event.test_case.name, test_suite_name, tags: tags, - service: configuration[:service_name] + service: datadog_configuration[:service_name] ) if event.test_case.match_tags?("@#{CI::Ext::Test::ITR_UNSKIPPABLE_OPTION}") test_span&.itr_unskippable! @@ -199,7 +200,11 @@ def ok?(result, strict) end end - def configuration + def datadog_integration + CI::Contrib::Instrumentation.fetch_integration(:cucumber) + end + + def datadog_configuration Datadog.configuration.ci[:cucumber] end diff --git a/lib/datadog/ci/contrib/cucumber/integration.rb b/lib/datadog/ci/contrib/cucumber/integration.rb index bbbcf82c..02d9b182 100644 --- a/lib/datadog/ci/contrib/cucumber/integration.rb +++ b/lib/datadog/ci/contrib/cucumber/integration.rb @@ -9,30 +9,21 @@ module CI module Contrib module Cucumber # Description of Cucumber integration - class Integration - include Datadog::CI::Contrib::Integration - + class Integration < Contrib::Integration MINIMUM_VERSION = Gem::Version.new("3.0.0") - register_as :cucumber - - def self.version + def version Gem.loaded_specs["cucumber"]&.version end - def self.loaded? + def loaded? !defined?(::Cucumber).nil? && !defined?(::Cucumber::Runtime).nil? end - def self.compatible? + def compatible? super && version >= MINIMUM_VERSION end - # test environments should not auto instrument test libraries - def auto_instrument? - false - end - def new_configuration Configuration::Settings.new end diff --git a/lib/datadog/ci/contrib/cucumber/patcher.rb b/lib/datadog/ci/contrib/cucumber/patcher.rb index af130550..eab97909 100644 --- a/lib/datadog/ci/contrib/cucumber/patcher.rb +++ b/lib/datadog/ci/contrib/cucumber/patcher.rb @@ -14,10 +14,6 @@ module Patcher module_function - def target_version - Integration.version - end - def patch ::Cucumber::Runtime.include(Instrumentation) end diff --git a/lib/datadog/ci/contrib/instrumentation.rb b/lib/datadog/ci/contrib/instrumentation.rb new file mode 100644 index 00000000..a283fe6c --- /dev/null +++ b/lib/datadog/ci/contrib/instrumentation.rb @@ -0,0 +1,88 @@ +# frozen_string_literal: true + +module Datadog + module CI + module Contrib + module Instrumentation + class InvalidIntegrationError < StandardError; end + + @registry = {} + + def self.registry + @registry + end + + def self.register_integration(integration_class) + @registry[integration_name(integration_class)] = integration_class.new + end + + # Manual instrumentation of a specific integration. + # + # This method is called when user has `c.ci.instrument :integration_name` in their code. + def self.instrument(integration_name, options = {}, &block) + integration = fetch_integration(integration_name) + integration.configure(options, &block) + + return unless integration.enabled + + patch_results = integration.patch + if patch_results[:ok] + # try to patch dependant integrations (for example knapsack that depends on rspec) + dependants = integration.dependants + .map { |name| fetch_integration(name) } + .filter { |integration| integration.patchable? } + + Datadog.logger.debug("Found dependent integrations for #{integration_name}: #{dependants}") + + dependants.each do |dependent_integration| + dependent_integration.patch + end + else + error_message = <<-ERROR + Available?: #{patch_results[:available]}, Loaded?: #{patch_results[:loaded]}, + Compatible?: #{patch_results[:compatible]}, Patchable?: #{patch_results[:patchable]}" + ERROR + Datadog.logger.warn("Unable to patch #{integration_name} (#{error_message})") + end + end + + # This method instruments all additional test libraries (ex: selenium-webdriver) that need to be instrumented + # later in the test suite run. + # + # It is intended to be called when test session starts to add additional capabilities to test visibility. + # + # This method does not automatically instrument test frameworks (ex: RSpec, Cucumber, etc), it requires + # test framework to be already instrumented. + def self.instrument_on_session_start + Datadog.logger.debug("Instrumenting all late instrumented integrations...") + + @registry.each do |name, integration| + next unless integration.late_instrument? + + Datadog.logger.debug "#{name} is allowed to be late instrumented" + + patch_results = integration.patch + if patch_results[:ok] + Datadog.logger.debug("#{name} is patched") + else + Datadog.logger.debug("#{name} is not patched (#{patch_results})") + end + end + end + + def self.fetch_integration(name) + @registry[name] || + raise(InvalidIntegrationError, "'#{name}' is not a valid integration.") + end + + # take the parent module name and downcase it + # for example for Datadog::CI::Contrib::RSpec::Integration it will be :rspec + def self.integration_name(subclass) + result = subclass.name&.split("::")&.[](-2)&.downcase&.to_sym + raise "Integration name could not be derived for #{subclass}" if result.nil? + result + end + end + end + end +end diff --git a/lib/datadog/ci/contrib/integration.rb b/lib/datadog/ci/contrib/integration.rb index 24021ae9..8bb09dd5 100644 --- a/lib/datadog/ci/contrib/integration.rb +++ b/lib/datadog/ci/contrib/integration.rb @@ -1,147 +1,129 @@ # frozen_string_literal: true require_relative "settings" +require_relative "instrumentation" module Datadog module CI module Contrib - module Integration - @registry = {} - - def self.included(base) - base.extend(ClassMethods) - base.include(InstanceMethods) + class Integration + def self.inherited(subclass) + Instrumentation.register_integration(subclass) end - def self.register(klass, name) - registry[name] = klass.new + # List of integrations names that depend on this integration. + # Specify when you might need to automatically instrument other integrations (like test runner for the + # test framework). + def dependants + [] end - def self.registry - @registry + # Version of the integration target code in the environment. + # + # This is the gem version, when the instrumentation target is a Ruby gem. + # + # If the target for instrumentation has concept of versioning, override {.version}, + # otherwise override {.available?} and implement a custom target presence check. + # @return [Object] the target version + def version + nil end - # Class-level methods for Integration - module ClassMethods - def register_as(name) - Integration.register(self, name) - end - - # Version of the integration target code in the environment. - # - # This is the gem version, when the instrumentation target is a Ruby gem. - # - # If the target for instrumentation has concept of versioning, override {.version}, - # otherwise override {.available?} and implement a custom target presence check. - # @return [Object] the target version - def version - nil - end - - # Is the target available to be instrumented? (e.g. gem installed?) - # - # The target doesn't have to be loaded (e.g. `require`) yet, but needs to be able - # to be loaded before instrumentation can commence. - # - # By default, {.available?} checks if {.version} returned a non-nil object. - # - # If the target for instrumentation has concept of versioning, override {.version}, - # otherwise override {.available?} and implement a custom target presence check. - # @return [Boolean] is the target available for instrumentation in this Ruby environment? - def available? - !version.nil? - end + # Is the target available to be instrumented? (e.g. gem installed?) + # + # The target doesn't have to be loaded (e.g. `require`) yet, but needs to be able + # to be loaded before instrumentation can commence. + # + # By default, {.available?} checks if {.version} returned a non-nil object. + # + # If the target for instrumentation has concept of versioning, override {.version}, + # otherwise override {.available?} and implement a custom target presence check. + # @return [Boolean] is the target available for instrumentation in this Ruby environment? + def available? + !version.nil? + end - # Is the target loaded into the application? (e.g. gem required? Constant defined?) - # - # The target's objects should be ready to be referenced by the instrumented when {.loaded} - # returns `true`. - # - # @return [Boolean] is the target ready to be referenced during instrumentation? - def loaded? - true - end + # Is the target loaded into the application? (e.g. gem required? Constant defined?) + # + # The target's objects should be ready to be referenced by the instrumented when {.loaded} + # returns `true`. + # + # @return [Boolean] is the target ready to be referenced during instrumentation? + def loaded? + true + end - # Is this instrumentation compatible with the available target? (e.g. minimum version met?) - # @return [Boolean] is the available target compatible with this instrumentation? - def compatible? - available? - end + # Is this instrumentation compatible with the available target? (e.g. minimum version met?) + # @return [Boolean] is the available target compatible with this instrumentation? + def compatible? + available? + end - # Can the patch for this integration be applied? - # - # By default, this is equivalent to {#available?}, {#loaded?}, and {#compatible?} - # all being truthy. - def patchable? - available? && loaded? && compatible? - end + # Can the patch for this integration be applied? + # + # By default, this is equivalent to {#available?}, {#loaded?}, and {#compatible?} + # all being truthy. + def patchable? + available? && loaded? && compatible? end - module InstanceMethods - # returns the configuration instance. - def configuration - @configuration ||= new_configuration - end + # returns the configuration instance. + def configuration + @configuration ||= new_configuration + end - def configure(options = {}, &block) - configuration.configure(options, &block) - configuration - end + def configure(options = {}, &block) + configuration.configure(options, &block) + configuration + end - # Resets all configuration options - def reset_configuration! - @configuration = nil - end + def enabled + configuration.enabled + end - def enabled - configuration.enabled - end + # The patcher module to inject instrumented objects into the instrumentation target. + # + # {Contrib::Patcher} includes the basic functionality of a patcher. `include`ing + # {Contrib::Patcher} into a new module is the recommend way to create a custom patcher. + # + # @return [Contrib::Patcher] a module that `include`s {Contrib::Patcher} + def patcher + nil + end - # The patcher module to inject instrumented objects into the instrumentation target. - # - # {Contrib::Patcher} includes the basic functionality of a patcher. `include`ing - # {Contrib::Patcher} into a new module is the recommend way to create a custom patcher. - # - # @return [Contrib::Patcher] a module that `include`s {Contrib::Patcher} - def patcher - nil + # @!visibility private + def patch + # @type var patcher_klass: untyped + patcher_klass = patcher + if !patchable? || patcher_klass.nil? + return { + ok: false, + available: available?, + loaded: loaded?, + compatible: compatible?, + patchable: patchable? + } end - # @!visibility private - def patch - # @type var patcher_klass: untyped - patcher_klass = patcher - if !self.class.patchable? || patcher_klass.nil? - return { - available: self.class.available?, - loaded: self.class.loaded?, - compatible: self.class.compatible?, - patchable: self.class.patchable? - } - end - - patcher_klass.patch - true - end + patcher_klass.patch + {ok: true} + end - # Can the patch for this integration be applied automatically? - # @return [Boolean] can the tracer activate this instrumentation without explicit user input? - def auto_instrument? - true - end + # Can the patch for this integration be applied automatically? + # @return [Boolean] can the tracer activate this instrumentation without explicit user input? + def late_instrument? + false + end - protected - - # Returns a new configuration object for this integration. - # - # This method normally needs to be overridden for each integration - # as their settings, defaults and environment variables are - # specific for each integration. - # - # @return [Datadog::CI::Contrib::Settings] a new, integration-specific settings object - def new_configuration - Datadog::CI::Contrib::Settings.new - end + # Returns a new configuration object for this integration. + # + # This method normally needs to be overridden for each integration + # as their settings, defaults and environment variables are + # specific for each integration. + # + # @return [Datadog::CI::Contrib::Settings] a new, integration-specific settings object + def new_configuration + Datadog::CI::Contrib::Settings.new end end end diff --git a/lib/datadog/ci/contrib/knapsack/extension.rb b/lib/datadog/ci/contrib/knapsack/extension.rb new file mode 100644 index 00000000..c3fb3b47 --- /dev/null +++ b/lib/datadog/ci/contrib/knapsack/extension.rb @@ -0,0 +1,27 @@ +# frozen_string_literal: true + +require "knapsack_pro/extensions/rspec_extension" + +require_relative "runner" + +module Datadog + module CI + module Contrib + module Knapsack + module Extension + def self.included(base) + base.singleton_class.prepend(ClassMethods) + end + + module ClassMethods + def setup! + super + + ::RSpec::Core::Runner.include(Datadog::CI::Contrib::Knapsack::Runner) + end + end + end + end + end + end +end diff --git a/lib/datadog/ci/contrib/knapsack/integration.rb b/lib/datadog/ci/contrib/knapsack/integration.rb new file mode 100644 index 00000000..5836a2db --- /dev/null +++ b/lib/datadog/ci/contrib/knapsack/integration.rb @@ -0,0 +1,36 @@ +# frozen_string_literal: true + +require_relative "../integration" +require_relative "patcher" + +module Datadog + module CI + module Contrib + module Knapsack + # Knapsack Pro test runner instrumentation + # https://github.com/KnapsackPro/knapsack_pro-ruby + class Integration < Contrib::Integration + MINIMUM_VERSION = Gem::Version.new("7.0.0") + + def version + Gem.loaded_specs["knapsack_pro"]&.version + end + + def loaded? + !defined?(::KnapsackPro).nil? && + !defined?(::KnapsackPro::Extensions::RSpecExtension).nil? && + !defined?(::KnapsackPro::Extensions::RSpecExtension::Runner).nil? + end + + def compatible? + super && version >= MINIMUM_VERSION + end + + def patcher + Patcher + end + end + end + end + end +end diff --git a/lib/datadog/ci/contrib/knapsack/patcher.rb b/lib/datadog/ci/contrib/knapsack/patcher.rb new file mode 100644 index 00000000..b8ba5db6 --- /dev/null +++ b/lib/datadog/ci/contrib/knapsack/patcher.rb @@ -0,0 +1,29 @@ +# frozen_string_literal: true + +require_relative "../patcher" + +module Datadog + module CI + module Contrib + module Knapsack + module Patcher + include Datadog::CI::Contrib::Patcher + + module_function + + def patch + if ::RSpec::Core::Runner.ancestors.include?(::KnapsackPro::Extensions::RSpecExtension::Runner) + # knapsack already patched rspec runner + require_relative "runner" + ::RSpec::Core::Runner.include(Datadog::CI::Contrib::Knapsack::Runner) + else + # knapsack didn't patch rspec runner yet + require_relative "extension" + ::KnapsackPro::Extensions::RSpecExtension.include(Datadog::CI::Contrib::Knapsack::Extension) + end + end + end + end + end + end +end diff --git a/lib/datadog/ci/contrib/knapsack/runner.rb b/lib/datadog/ci/contrib/knapsack/runner.rb new file mode 100644 index 00000000..aae5b604 --- /dev/null +++ b/lib/datadog/ci/contrib/knapsack/runner.rb @@ -0,0 +1,66 @@ +# frozen_string_literal: true + +require_relative "../../ext/test" +require_relative "../rspec/ext" +require_relative "../instrumentation" + +module Datadog + module CI + module Contrib + module Knapsack + module Runner + def self.included(base) + base.prepend(InstanceMethods) + end + + module InstanceMethods + # TODO: this is coupled to RSpec integration being present, not sure if it's bad or not at this point + def knapsack__run_specs(*args) + return super if ::RSpec.configuration.dry_run? && !datadog_configuration[:dry_run_enabled] + return super unless datadog_configuration[:enabled] + + test_session = test_visibility_component.start_test_session( + tags: { + CI::Ext::Test::TAG_FRAMEWORK => CI::Contrib::RSpec::Ext::FRAMEWORK, + CI::Ext::Test::TAG_FRAMEWORK_VERSION => datadog_integration.version.to_s + }, + service: datadog_configuration[:service_name] + ) + + test_module = test_visibility_component.start_test_module(CI::Contrib::RSpec::Ext::FRAMEWORK) + + result = super + return result unless test_module && test_session + + if result != 0 + test_module.failed! + test_session.failed! + else + test_module.passed! + test_session.passed! + end + test_module.finish + test_session.finish + + result + end + + private + + def datadog_integration + CI::Contrib::Instrumentation.fetch_integration(:rspec) + end + + def datadog_configuration + Datadog.configuration.ci[:rspec] + end + + def test_visibility_component + Datadog.send(:components).test_visibility + end + end + end + end + end + end +end diff --git a/lib/datadog/ci/contrib/minitest/integration.rb b/lib/datadog/ci/contrib/minitest/integration.rb index ce1cd89c..9a9f84ed 100644 --- a/lib/datadog/ci/contrib/minitest/integration.rb +++ b/lib/datadog/ci/contrib/minitest/integration.rb @@ -9,30 +9,21 @@ module CI module Contrib module Minitest # Description of Minitest integration - class Integration - include Datadog::CI::Contrib::Integration - + class Integration < Contrib::Integration MINIMUM_VERSION = Gem::Version.new("5.0.0") - register_as :minitest - - def self.version + def version Gem.loaded_specs["minitest"]&.version end - def self.loaded? + def loaded? !defined?(::Minitest).nil? end - def self.compatible? + def compatible? super && version >= MINIMUM_VERSION end - # test environments should not auto instrument test libraries - def auto_instrument? - false - end - def new_configuration Configuration::Settings.new end diff --git a/lib/datadog/ci/contrib/minitest/patcher.rb b/lib/datadog/ci/contrib/minitest/patcher.rb index de98d603..159409b0 100644 --- a/lib/datadog/ci/contrib/minitest/patcher.rb +++ b/lib/datadog/ci/contrib/minitest/patcher.rb @@ -15,10 +15,6 @@ module Patcher module_function - def target_version - Integration.version - end - def patch # test session start ::Minitest.include(Runner) diff --git a/lib/datadog/ci/contrib/minitest/runner.rb b/lib/datadog/ci/contrib/minitest/runner.rb index e8ecae2b..edc753d4 100644 --- a/lib/datadog/ci/contrib/minitest/runner.rb +++ b/lib/datadog/ci/contrib/minitest/runner.rb @@ -1,6 +1,7 @@ # frozen_string_literal: true require_relative "../../ext/test" +require_relative "../instrumentation" require_relative "ext" module Datadog @@ -25,7 +26,7 @@ def init_plugins(*args) test_visibility_component.start_test_session( tags: { CI::Ext::Test::TAG_FRAMEWORK => Ext::FRAMEWORK, - CI::Ext::Test::TAG_FRAMEWORK_VERSION => CI::Contrib::Minitest::Integration.version.to_s + CI::Ext::Test::TAG_FRAMEWORK_VERSION => datadog_integration.version.to_s }, service: datadog_configuration[:service_name], total_tests_count: (DD_ESTIMATED_TESTS_PER_SUITE * ::Minitest::Runnable.runnables.size).to_i @@ -47,6 +48,10 @@ def run_one_method(klass, method_name) private + def datadog_integration + CI::Contrib::Instrumentation.fetch_integration(:minitest) + end + def datadog_configuration Datadog.configuration.ci[:minitest] end diff --git a/lib/datadog/ci/contrib/minitest/test.rb b/lib/datadog/ci/contrib/minitest/test.rb index 213825bb..3fb59496 100644 --- a/lib/datadog/ci/contrib/minitest/test.rb +++ b/lib/datadog/ci/contrib/minitest/test.rb @@ -2,6 +2,7 @@ require_relative "../../ext/test" require_relative "../../git/local_repository" +require_relative "../instrumentation" require_relative "ext" require_relative "helpers" @@ -36,7 +37,7 @@ def before_setup test_suite_name, tags: { CI::Ext::Test::TAG_FRAMEWORK => Ext::FRAMEWORK, - CI::Ext::Test::TAG_FRAMEWORK_VERSION => CI::Contrib::Minitest::Integration.version.to_s, + CI::Ext::Test::TAG_FRAMEWORK_VERSION => datadog_integration.version.to_s, CI::Ext::Test::TAG_SOURCE_FILE => Git::LocalRepository.relative_to_root(source_file), CI::Ext::Test::TAG_SOURCE_START => line_number.to_s }, @@ -79,6 +80,10 @@ def finish_with_result(span, result_code) span.finish end + def datadog_integration + CI::Contrib::Instrumentation.fetch_integration(:minitest) + end + def datadog_configuration Datadog.configuration.ci[:minitest] end diff --git a/lib/datadog/ci/contrib/rspec/example.rb b/lib/datadog/ci/contrib/rspec/example.rb index e7a2ac2e..b060f549 100644 --- a/lib/datadog/ci/contrib/rspec/example.rb +++ b/lib/datadog/ci/contrib/rspec/example.rb @@ -3,6 +3,7 @@ require_relative "../../ext/test" require_relative "../../git/local_repository" require_relative "../../utils/test_run" +require_relative "../instrumentation" require_relative "ext" module Datadog @@ -46,7 +47,7 @@ def run(*args) suite_name, tags: { CI::Ext::Test::TAG_FRAMEWORK => Ext::FRAMEWORK, - CI::Ext::Test::TAG_FRAMEWORK_VERSION => CI::Contrib::RSpec::Integration.version.to_s, + CI::Ext::Test::TAG_FRAMEWORK_VERSION => datadog_integration.version.to_s, CI::Ext::Test::TAG_SOURCE_FILE => Git::LocalRepository.relative_to_root(metadata[:file_path]), CI::Ext::Test::TAG_SOURCE_START => metadata[:line_number].to_s, CI::Ext::Test::TAG_PARAMETERS => Utils::TestRun.test_parameters( @@ -120,6 +121,10 @@ def fetch_top_level_example_group res end + def datadog_integration + CI::Contrib::Instrumentation.fetch_integration(:rspec) + end + def datadog_configuration Datadog.configuration.ci[:rspec] end diff --git a/lib/datadog/ci/contrib/rspec/integration.rb b/lib/datadog/ci/contrib/rspec/integration.rb index c0279c79..6403e5c4 100644 --- a/lib/datadog/ci/contrib/rspec/integration.rb +++ b/lib/datadog/ci/contrib/rspec/integration.rb @@ -9,31 +9,26 @@ module CI module Contrib module RSpec # Description of RSpec integration - class Integration - include Datadog::CI::Contrib::Integration - + class Integration < Contrib::Integration MINIMUM_VERSION = Gem::Version.new("3.0.0") - register_as :rspec + def dependants + %i[knapsack] + end - def self.version + def version Gem.loaded_specs["rspec-core"]&.version end - def self.loaded? + def loaded? !defined?(::RSpec).nil? && !defined?(::RSpec::Core).nil? && !defined?(::RSpec::Core::Example).nil? end - def self.compatible? + def compatible? super && version >= MINIMUM_VERSION end - # test environments should not auto instrument test libraries - def auto_instrument? - false - end - def new_configuration Configuration::Settings.new end diff --git a/lib/datadog/ci/contrib/rspec/knapsack_pro/extension.rb b/lib/datadog/ci/contrib/rspec/knapsack_pro/extension.rb deleted file mode 100644 index f7fe2dcd..00000000 --- a/lib/datadog/ci/contrib/rspec/knapsack_pro/extension.rb +++ /dev/null @@ -1,29 +0,0 @@ -# frozen_string_literal: true - -require "knapsack_pro/extensions/rspec_extension" - -require_relative "runner" - -module Datadog - module CI - module Contrib - module RSpec - module KnapsackPro - module Extension - def self.included(base) - base.singleton_class.prepend(ClassMethods) - end - - module ClassMethods - def setup! - super - - ::RSpec::Core::Runner.include(Datadog::CI::Contrib::RSpec::KnapsackPro::Runner) - end - end - end - end - end - end - end -end diff --git a/lib/datadog/ci/contrib/rspec/knapsack_pro/patcher.rb b/lib/datadog/ci/contrib/rspec/knapsack_pro/patcher.rb deleted file mode 100644 index 3346f6da..00000000 --- a/lib/datadog/ci/contrib/rspec/knapsack_pro/patcher.rb +++ /dev/null @@ -1,26 +0,0 @@ -# frozen_string_literal: true - -module Datadog - module CI - module Contrib - module RSpec - module KnapsackPro - module Patcher - def self.patch - if defined?(::KnapsackPro::Extensions::RSpecExtension::Runner) && - ::RSpec::Core::Runner.ancestors.include?(::KnapsackPro::Extensions::RSpecExtension::Runner) - # knapsack already patched rspec runner - require_relative "runner" - ::RSpec::Core::Runner.include(KnapsackPro::Runner) - else - # knapsack didn't patch rspec runner yet - require_relative "extension" - ::KnapsackPro::Extensions::RSpecExtension.include(KnapsackPro::Extension) - end - end - end - end - end - end - end -end diff --git a/lib/datadog/ci/contrib/rspec/knapsack_pro/runner.rb b/lib/datadog/ci/contrib/rspec/knapsack_pro/runner.rb deleted file mode 100644 index c4a386f1..00000000 --- a/lib/datadog/ci/contrib/rspec/knapsack_pro/runner.rb +++ /dev/null @@ -1,62 +0,0 @@ -# frozen_string_literal: true - -require_relative "../../../ext/test" -require_relative "../ext" - -module Datadog - module CI - module Contrib - module RSpec - module KnapsackPro - module Runner - def self.included(base) - base.prepend(InstanceMethods) - end - - module InstanceMethods - def knapsack__run_specs(*args) - return super if ::RSpec.configuration.dry_run? && !datadog_configuration[:dry_run_enabled] - return super unless datadog_configuration[:enabled] - - test_session = test_visibility_component.start_test_session( - tags: { - CI::Ext::Test::TAG_FRAMEWORK => Ext::FRAMEWORK, - CI::Ext::Test::TAG_FRAMEWORK_VERSION => CI::Contrib::RSpec::Integration.version.to_s - }, - service: datadog_configuration[:service_name] - ) - - test_module = test_visibility_component.start_test_module(Ext::FRAMEWORK) - - result = super - return result unless test_module && test_session - - if result != 0 - test_module.failed! - test_session.failed! - else - test_module.passed! - test_session.passed! - end - test_module.finish - test_session.finish - - result - end - - private - - def datadog_configuration - Datadog.configuration.ci[:rspec] - end - - def test_visibility_component - Datadog.send(:components).test_visibility - end - end - end - end - end - end - end -end diff --git a/lib/datadog/ci/contrib/rspec/patcher.rb b/lib/datadog/ci/contrib/rspec/patcher.rb index 145ed035..116d2040 100644 --- a/lib/datadog/ci/contrib/rspec/patcher.rb +++ b/lib/datadog/ci/contrib/rspec/patcher.rb @@ -16,24 +16,14 @@ module Patcher module_function - def target_version - Integration.version - end - def patch # ci-queue test runner instrumentation + # TODO: to be extracted in the next PR # https://github.com/Shopify/ci-queue if ci_queue? ::RSpec::Queue::Runner.include(Runner) end - if knapsack_pro? - # Knapsack Pro test runner instrumentation - # https://github.com/KnapsackPro/knapsack_pro-ruby - require_relative "knapsack_pro/patcher" - Datadog::CI::Contrib::RSpec::KnapsackPro::Patcher.patch - end - # default rspec test runner instrumentation ::RSpec::Core::Runner.include(Runner) @@ -44,14 +34,6 @@ def patch def ci_queue? !!defined?(::RSpec::Queue::Runner) end - - def knapsack_pro? - knapsack_version = Gem.loaded_specs["knapsack_pro"]&.version - - # additional instrumentation is needed for KnapsackPro version 7 and later - !!defined?(::KnapsackPro) && - !knapsack_version.nil? && knapsack_version >= Gem::Version.new("7") - end end end end diff --git a/lib/datadog/ci/contrib/rspec/runner.rb b/lib/datadog/ci/contrib/rspec/runner.rb index 49a88a10..a9505978 100644 --- a/lib/datadog/ci/contrib/rspec/runner.rb +++ b/lib/datadog/ci/contrib/rspec/runner.rb @@ -1,6 +1,7 @@ # frozen_string_literal: true require_relative "../../ext/test" +require_relative "../instrumentation" require_relative "ext" module Datadog @@ -21,7 +22,7 @@ def run_specs(*args) test_session = test_visibility_component.start_test_session( tags: { CI::Ext::Test::TAG_FRAMEWORK => Ext::FRAMEWORK, - CI::Ext::Test::TAG_FRAMEWORK_VERSION => CI::Contrib::RSpec::Integration.version.to_s + CI::Ext::Test::TAG_FRAMEWORK_VERSION => datadog_integration.version.to_s }, service: datadog_configuration[:service_name], total_tests_count: ::RSpec.world.example_count @@ -47,6 +48,10 @@ def run_specs(*args) private + def datadog_integration + CI::Contrib::Instrumentation.fetch_integration(:rspec) + end + def datadog_configuration Datadog.configuration.ci[:rspec] end diff --git a/lib/datadog/ci/contrib/selenium/integration.rb b/lib/datadog/ci/contrib/selenium/integration.rb index 6d3e9bec..6dcb3ba8 100644 --- a/lib/datadog/ci/contrib/selenium/integration.rb +++ b/lib/datadog/ci/contrib/selenium/integration.rb @@ -9,28 +9,24 @@ module CI module Contrib module Selenium # Description of Selenium integration - class Integration - include Datadog::CI::Contrib::Integration - + class Integration < Contrib::Integration MINIMUM_VERSION = Gem::Version.new("4.0.0") - register_as :selenium - - def self.version + def version Gem.loaded_specs["selenium-webdriver"]&.version end - def self.loaded? + def loaded? !defined?(::Selenium).nil? && !defined?(::Selenium::WebDriver).nil? && !defined?(::Selenium::WebDriver::Driver).nil? end - def self.compatible? + def compatible? super && version >= MINIMUM_VERSION end - # additional instrumentations for test helpers are auto instrumented on test session start - def auto_instrument? + # additional instrumentations for test libraries are late instrumented on test session start + def late_instrument? true end diff --git a/lib/datadog/ci/contrib/selenium/navigation.rb b/lib/datadog/ci/contrib/selenium/navigation.rb index 04151798..dd76b92f 100644 --- a/lib/datadog/ci/contrib/selenium/navigation.rb +++ b/lib/datadog/ci/contrib/selenium/navigation.rb @@ -43,7 +43,7 @@ def to(url) active_test.set_tag(CI::Ext::Test::TAG_BROWSER_DRIVER, "selenium") active_test.set_tag( CI::Ext::Test::TAG_BROWSER_DRIVER_VERSION, - Integration.version + datadog_integration.version ) active_test.set_tag( CI::Ext::Test::TAG_BROWSER_NAME, @@ -63,6 +63,10 @@ def to(url) private + def datadog_integration + CI::Contrib::Instrumentation.fetch_integration(:selenium) + end + def datadog_configuration Datadog.configuration.ci[:selenium] end diff --git a/lib/datadog/ci/contrib/selenium/patcher.rb b/lib/datadog/ci/contrib/selenium/patcher.rb index b4640c9c..9cf071b4 100644 --- a/lib/datadog/ci/contrib/selenium/patcher.rb +++ b/lib/datadog/ci/contrib/selenium/patcher.rb @@ -16,10 +16,6 @@ module Patcher module_function - def target_version - Integration.version - end - def patch ::Selenium::WebDriver::Driver.include(Driver) ::Selenium::WebDriver::Navigation.include(Navigation) diff --git a/lib/datadog/ci/contrib/simplecov/integration.rb b/lib/datadog/ci/contrib/simplecov/integration.rb index 6d7da3af..7381c625 100644 --- a/lib/datadog/ci/contrib/simplecov/integration.rb +++ b/lib/datadog/ci/contrib/simplecov/integration.rb @@ -9,27 +9,23 @@ module CI module Contrib module Simplecov # Description of Simplecov integration - class Integration - include Datadog::CI::Contrib::Integration - + class Integration < Contrib::Integration MINIMUM_VERSION = Gem::Version.new("0.18.0") - register_as :simplecov - - def self.version + def version Gem.loaded_specs["simplecov"]&.version end - def self.loaded? + def loaded? !defined?(::SimpleCov).nil? end - def self.compatible? + def compatible? super && version >= MINIMUM_VERSION end - # additional instrumentations for test helpers are auto instrumented on test session start - def auto_instrument? + # additional instrumentations for test libraries are late instrumented on test session start + def late_instrument? true end diff --git a/lib/datadog/ci/contrib/simplecov/patcher.rb b/lib/datadog/ci/contrib/simplecov/patcher.rb index f200d894..39046c0c 100644 --- a/lib/datadog/ci/contrib/simplecov/patcher.rb +++ b/lib/datadog/ci/contrib/simplecov/patcher.rb @@ -14,10 +14,6 @@ module Patcher module_function - def target_version - Integration.version - end - def patch ::SimpleCov.include(ResultExtractor) end diff --git a/lib/datadog/ci/test_visibility/component.rb b/lib/datadog/ci/test_visibility/component.rb index 2c6b9332..588041dd 100644 --- a/lib/datadog/ci/test_visibility/component.rb +++ b/lib/datadog/ci/test_visibility/component.rb @@ -7,7 +7,7 @@ require_relative "total_coverage" require_relative "../codeowners/parser" -require_relative "../contrib/contrib" +require_relative "../contrib/instrumentation" require_relative "../ext/test" require_relative "../git/local_repository" @@ -149,7 +149,7 @@ def on_test_session_started(test_session) git_tree_upload_worker.perform(test_session.git_repository_url) # finds and instruments additional test libraries that we support (ex: selenium-webdriver) - Contrib.auto_instrument_on_session_start! + Contrib::Instrumentation.instrument_on_session_start # sends internal telemetry events Telemetry.test_session_started(test_session) diff --git a/sig/datadog/ci/contrib/contrib.rbs b/sig/datadog/ci/contrib/contrib.rbs deleted file mode 100644 index 9c44f9a9..00000000 --- a/sig/datadog/ci/contrib/contrib.rbs +++ /dev/null @@ -1,7 +0,0 @@ -module Datadog - module CI - module Contrib - def self.auto_instrument_on_session_start!: () -> void - end - end -end diff --git a/sig/datadog/ci/contrib/cucumber/formatter.rbs b/sig/datadog/ci/contrib/cucumber/formatter.rbs index 5fce73fe..5805f4e9 100644 --- a/sig/datadog/ci/contrib/cucumber/formatter.rbs +++ b/sig/datadog/ci/contrib/cucumber/formatter.rbs @@ -49,7 +49,9 @@ module Datadog def ok?: (Cucumber::Core::Test::Result result, untyped strict) -> bool - def configuration: () -> untyped + def datadog_integration: () -> Datadog::CI::Contrib::Integration + + def datadog_configuration: () -> untyped def test_visibility_component: () -> Datadog::CI::TestVisibility::Component diff --git a/sig/datadog/ci/contrib/cucumber/integration.rbs b/sig/datadog/ci/contrib/cucumber/integration.rbs index 9aeee479..ec705c7c 100644 --- a/sig/datadog/ci/contrib/cucumber/integration.rbs +++ b/sig/datadog/ci/contrib/cucumber/integration.rbs @@ -2,19 +2,16 @@ module Datadog module CI module Contrib module Cucumber - class Integration - extend Datadog::CI::Contrib::Integration::ClassMethods - include Datadog::CI::Contrib::Integration::InstanceMethods - + class Integration < Datadog::CI::Contrib::Integration MINIMUM_VERSION: Gem::Version - def self.version: () -> untyped + def version: () -> untyped - def self.loaded?: () -> bool + def loaded?: () -> bool - def self.compatible?: () -> bool + def compatible?: () -> bool - def auto_instrument?: () -> false + def late_instrument?: () -> false def new_configuration: () -> untyped diff --git a/sig/datadog/ci/contrib/cucumber/patcher.rbs b/sig/datadog/ci/contrib/cucumber/patcher.rbs index ed30da67..c19daeb2 100644 --- a/sig/datadog/ci/contrib/cucumber/patcher.rbs +++ b/sig/datadog/ci/contrib/cucumber/patcher.rbs @@ -5,8 +5,6 @@ module Datadog module Patcher include Datadog::CI::Contrib::Patcher - def self?.target_version: () -> untyped - def self?.patch: () -> untyped end end diff --git a/sig/datadog/ci/contrib/instrumentation.rbs b/sig/datadog/ci/contrib/instrumentation.rbs new file mode 100644 index 00000000..a10222fd --- /dev/null +++ b/sig/datadog/ci/contrib/instrumentation.rbs @@ -0,0 +1,24 @@ +module Datadog + module CI + module Contrib + module Instrumentation + class InvalidIntegrationError < StandardError + end + + self.@registry: Hash[Symbol, untyped] + + def self.registry: () -> Hash[Symbol, untyped] + + def self.instrument: (Symbol integration_name, ?::Hash[untyped, untyped] options) { (?) -> untyped } -> void + + def self.fetch_integration: (Symbol name) -> untyped + + def self.integration_name: (Class) -> Symbol + + def self.register_integration: (Class integration) -> void + + def self.instrument_on_session_start: () -> void + end + end + end +end diff --git a/sig/datadog/ci/contrib/integration.rbs b/sig/datadog/ci/contrib/integration.rbs index a7be702a..96be033b 100644 --- a/sig/datadog/ci/contrib/integration.rbs +++ b/sig/datadog/ci/contrib/integration.rbs @@ -1,43 +1,32 @@ module Datadog module CI module Contrib - module Integration - self.@registry: Hash[Symbol, untyped] + class Integration + def self.inherited: (untyped) -> void - def self.included: (Module base) -> void + def version: () -> untyped - def self.register: (untyped integration, Symbol name) -> void + def available?: () -> bool - def self.registry: () -> Hash[Symbol, untyped] + def loaded?: () -> bool - module ClassMethods - def register_as: (Symbol name) -> void + def compatible?: () -> bool - def version: () -> Gem::Version? + def patchable?: () -> bool - def available?: () -> bool + def configuration: () -> Datadog::CI::Contrib::Settings - def loaded?: () -> bool + def configure: (?::Hash[Symbol, untyped] options) ?{ (Datadog::CI::Contrib::Settings) -> Datadog::CI::Contrib::Settings } -> Datadog::CI::Contrib::Settings - def compatible?: () -> bool + def enabled: () -> bool - def patchable?: () -> bool - end + def patcher: () -> Datadog::Tracing::Contrib::Patcher? - module InstanceMethods - extend ClassMethods - @configuration: Datadog::CI::Contrib::Settings? + def patch: () -> Hash[Symbol, bool] - def configuration: () -> Datadog::CI::Contrib::Settings + def late_instrument?: () -> bool - def configure: (?::Hash[Symbol, untyped] options) ?{ (Datadog::CI::Contrib::Settings) -> Datadog::CI::Contrib::Settings } -> Datadog::CI::Contrib::Settings - - def reset_configuration!: () -> void - - def patcher: () -> Datadog::Tracing::Contrib::Patcher? - - def new_configuration: () -> Datadog::CI::Contrib::Settings - end + def new_configuration: () -> Datadog::CI::Contrib::Settings end end end diff --git a/sig/datadog/ci/contrib/knapsack/extension.rbs b/sig/datadog/ci/contrib/knapsack/extension.rbs new file mode 100644 index 00000000..92576fec --- /dev/null +++ b/sig/datadog/ci/contrib/knapsack/extension.rbs @@ -0,0 +1,17 @@ +module Datadog + module CI + module Contrib + module Knapsack + module Extension + def self.included: (untyped base) -> untyped + + module ClassMethods + include ::KnapsackPro::Extensions::RSpecExtension + + def setup!: () -> void + end + end + end + end + end +end diff --git a/sig/datadog/ci/contrib/knapsack/integration.rbs b/sig/datadog/ci/contrib/knapsack/integration.rbs new file mode 100644 index 00000000..f14b97af --- /dev/null +++ b/sig/datadog/ci/contrib/knapsack/integration.rbs @@ -0,0 +1,23 @@ +module Datadog + module CI + module Contrib + module Knapsack + class Integration < Datadog::CI::Contrib::Integration + MINIMUM_VERSION: Gem::Version + + def version: () -> untyped + + def loaded?: () -> bool + + def compatible?: () -> bool + + def late_instrument?: () -> bool + + def new_configuration: () -> Datadog::CI::Contrib::Settings + + def patcher: () -> singleton(Patcher) + end + end + end + end +end diff --git a/sig/datadog/ci/contrib/knapsack/patcher.rbs b/sig/datadog/ci/contrib/knapsack/patcher.rbs new file mode 100644 index 00000000..48ef1611 --- /dev/null +++ b/sig/datadog/ci/contrib/knapsack/patcher.rbs @@ -0,0 +1,11 @@ +module Datadog + module CI + module Contrib + module Knapsack + module Patcher + def self.patch: () -> void + end + end + end + end +end diff --git a/sig/datadog/ci/contrib/knapsack/runner.rbs b/sig/datadog/ci/contrib/knapsack/runner.rbs new file mode 100644 index 00000000..a8179ac6 --- /dev/null +++ b/sig/datadog/ci/contrib/knapsack/runner.rbs @@ -0,0 +1,25 @@ +module Datadog + module CI + module Contrib + module Knapsack + module Runner + def self.included: (untyped base) -> untyped + + module InstanceMethods + include ::KnapsackPro::Runners::Queue::RSpecRunner + + def knapsack__run_specs: (untyped args) -> untyped + + private + + def datadog_integration: () -> Datadog::CI::Contrib::Integration + + def datadog_configuration: () -> untyped + + def test_visibility_component: () -> Datadog::CI::TestVisibility::Component + end + end + end + end + end +end diff --git a/sig/datadog/ci/contrib/minitest/integration.rbs b/sig/datadog/ci/contrib/minitest/integration.rbs index ce86c736..0c006af7 100644 --- a/sig/datadog/ci/contrib/minitest/integration.rbs +++ b/sig/datadog/ci/contrib/minitest/integration.rbs @@ -2,19 +2,16 @@ module Datadog module CI module Contrib module Minitest - class Integration - extend Datadog::CI::Contrib::Integration::ClassMethods - include Datadog::CI::Contrib::Integration::InstanceMethods - + class Integration < Datadog::CI::Contrib::Integration MINIMUM_VERSION: Gem::Version - def self.version: () -> untyped + def version: () -> untyped - def self.loaded?: () -> bool + def loaded?: () -> bool def compatible?: () -> bool - def auto_instrument?: () -> false + def late_instrument?: () -> false def new_configuration: () -> untyped diff --git a/sig/datadog/ci/contrib/minitest/patcher.rbs b/sig/datadog/ci/contrib/minitest/patcher.rbs index ab494098..c9012086 100644 --- a/sig/datadog/ci/contrib/minitest/patcher.rbs +++ b/sig/datadog/ci/contrib/minitest/patcher.rbs @@ -5,8 +5,6 @@ module Datadog module Patcher include Datadog::CI::Contrib::Patcher - def self?.target_version: () -> untyped - def self?.patch: () -> untyped end end diff --git a/sig/datadog/ci/contrib/minitest/runner.rbs b/sig/datadog/ci/contrib/minitest/runner.rbs index 80100aac..381b3368 100644 --- a/sig/datadog/ci/contrib/minitest/runner.rbs +++ b/sig/datadog/ci/contrib/minitest/runner.rbs @@ -16,6 +16,8 @@ module Datadog private + def datadog_integration: () -> Datadog::CI::Contrib::Integration + def datadog_configuration: () -> untyped def test_visibility_component: () -> Datadog::CI::TestVisibility::Component diff --git a/sig/datadog/ci/contrib/minitest/test.rbs b/sig/datadog/ci/contrib/minitest/test.rbs index 5d6e3d9e..310047c6 100644 --- a/sig/datadog/ci/contrib/minitest/test.rbs +++ b/sig/datadog/ci/contrib/minitest/test.rbs @@ -22,6 +22,8 @@ module Datadog private + def datadog_integration: () -> Datadog::CI::Contrib::Integration + def datadog_configuration: () -> untyped def test_visibility_component: () -> Datadog::CI::TestVisibility::Component diff --git a/sig/datadog/ci/contrib/patcher.rbs b/sig/datadog/ci/contrib/patcher.rbs index f63fd48c..1a37bcf0 100644 --- a/sig/datadog/ci/contrib/patcher.rbs +++ b/sig/datadog/ci/contrib/patcher.rbs @@ -2,12 +2,12 @@ module Datadog module CI module Contrib module Patcher - def self.included: (untyped base) -> untyped + def self.included: (Class base) -> void module CommonMethods - attr_accessor patch_error_result: untyped + attr_accessor patch_error_result: Hash[Symbol, untyped] - attr_accessor patch_successful: untyped + attr_accessor patch_successful: bool def patch_name: () -> String? @@ -17,13 +17,11 @@ module Datadog def patch: () -> void - def on_patch_error: (untyped e) -> untyped - - def default_tags: () -> untyped + def on_patch_error: (StandardError e) -> Hash[Symbol, untyped] private - def patch_only_once: () -> untyped + def patch_only_once: () -> Datadog::Core::Utils::OnlyOnce @patch_only_once: Datadog::Core::Utils::OnlyOnce end diff --git a/sig/datadog/ci/contrib/rspec/example.rbs b/sig/datadog/ci/contrib/rspec/example.rbs index a374c150..d324d9bd 100644 --- a/sig/datadog/ci/contrib/rspec/example.rbs +++ b/sig/datadog/ci/contrib/rspec/example.rbs @@ -12,6 +12,7 @@ module Datadog private def fetch_top_level_example_group: () -> Hash[Symbol, untyped] + def datadog_integration: () -> Datadog::CI::Contrib::Integration def datadog_configuration: () -> untyped def test_visibility_component: () -> Datadog::CI::TestVisibility::Component def test_retries_component: () -> Datadog::CI::TestRetries::Component diff --git a/sig/datadog/ci/contrib/rspec/integration.rbs b/sig/datadog/ci/contrib/rspec/integration.rbs index c56a528f..636ffd76 100644 --- a/sig/datadog/ci/contrib/rspec/integration.rbs +++ b/sig/datadog/ci/contrib/rspec/integration.rbs @@ -2,19 +2,16 @@ module Datadog module CI module Contrib module RSpec - class Integration - extend Datadog::CI::Contrib::Integration::ClassMethods - include Datadog::CI::Contrib::Integration::InstanceMethods - + class Integration < Datadog::CI::Contrib::Integration MINIMUM_VERSION: Gem::Version - def self.version: () -> untyped + def version: () -> untyped - def self.loaded?: () -> untyped + def loaded?: () -> untyped def compatible?: () -> bool - def auto_instrument?: () -> false + def late_instrument?: () -> false def new_configuration: () -> untyped diff --git a/sig/datadog/ci/contrib/rspec/knapsack_pro/extension.rbs b/sig/datadog/ci/contrib/rspec/knapsack_pro/extension.rbs deleted file mode 100644 index f0aa363c..00000000 --- a/sig/datadog/ci/contrib/rspec/knapsack_pro/extension.rbs +++ /dev/null @@ -1,19 +0,0 @@ -module Datadog - module CI - module Contrib - module RSpec - module KnapsackPro - module Extension - def self.included: (untyped base) -> untyped - - module ClassMethods - include ::KnapsackPro::Extensions::RSpecExtension - - def setup!: () -> void - end - end - end - end - end - end -end diff --git a/sig/datadog/ci/contrib/rspec/knapsack_pro/patcher.rbs b/sig/datadog/ci/contrib/rspec/knapsack_pro/patcher.rbs deleted file mode 100644 index 11d34d86..00000000 --- a/sig/datadog/ci/contrib/rspec/knapsack_pro/patcher.rbs +++ /dev/null @@ -1,13 +0,0 @@ -module Datadog - module CI - module Contrib - module RSpec - module KnapsackPro - module Patcher - def self.patch: () -> void - end - end - end - end - end -end diff --git a/sig/datadog/ci/contrib/rspec/knapsack_pro/runner.rbs b/sig/datadog/ci/contrib/rspec/knapsack_pro/runner.rbs deleted file mode 100644 index f850b66e..00000000 --- a/sig/datadog/ci/contrib/rspec/knapsack_pro/runner.rbs +++ /dev/null @@ -1,25 +0,0 @@ -module Datadog - module CI - module Contrib - module RSpec - module KnapsackPro - module Runner - def self.included: (untyped base) -> untyped - - module InstanceMethods - include ::KnapsackPro::Runners::Queue::RSpecRunner - - def knapsack__run_specs: (untyped args) -> untyped - - private - - def datadog_configuration: () -> untyped - - def test_visibility_component: () -> Datadog::CI::TestVisibility::Component - end - end - end - end - end - end -end diff --git a/sig/datadog/ci/contrib/rspec/patcher.rbs b/sig/datadog/ci/contrib/rspec/patcher.rbs index d3e26b75..3e89d310 100644 --- a/sig/datadog/ci/contrib/rspec/patcher.rbs +++ b/sig/datadog/ci/contrib/rspec/patcher.rbs @@ -5,8 +5,6 @@ module Datadog module Patcher include Datadog::CI::Contrib::Patcher - def self?.target_version: () -> String - def self?.patch: () -> void def self?.ci_queue?: () -> bool diff --git a/sig/datadog/ci/contrib/rspec/runner.rbs b/sig/datadog/ci/contrib/rspec/runner.rbs index b0b9c96a..f4e5729d 100644 --- a/sig/datadog/ci/contrib/rspec/runner.rbs +++ b/sig/datadog/ci/contrib/rspec/runner.rbs @@ -10,6 +10,8 @@ module Datadog private + def datadog_integration: () -> Datadog::CI::Contrib::Integration + def datadog_configuration: () -> untyped def test_visibility_component: () -> Datadog::CI::TestVisibility::Component diff --git a/sig/datadog/ci/contrib/selenium/integration.rbs b/sig/datadog/ci/contrib/selenium/integration.rbs index 15a9b87a..38ca7c28 100644 --- a/sig/datadog/ci/contrib/selenium/integration.rbs +++ b/sig/datadog/ci/contrib/selenium/integration.rbs @@ -2,19 +2,16 @@ module Datadog module CI module Contrib module Selenium - class Integration - extend Datadog::CI::Contrib::Integration::ClassMethods - include Datadog::CI::Contrib::Integration::InstanceMethods - + class Integration < Datadog::CI::Contrib::Integration MINIMUM_VERSION: Gem::Version - def self.version: () -> untyped + def version: () -> untyped - def self.loaded?: () -> bool + def loaded?: () -> bool - def self.compatible?: () -> bool + def compatible?: () -> bool - def auto_instrument?: () -> true + def late_instrument?: () -> true def new_configuration: () -> untyped diff --git a/sig/datadog/ci/contrib/selenium/navigation.rbs b/sig/datadog/ci/contrib/selenium/navigation.rbs index a6d03044..5b0607a6 100644 --- a/sig/datadog/ci/contrib/selenium/navigation.rbs +++ b/sig/datadog/ci/contrib/selenium/navigation.rbs @@ -8,6 +8,8 @@ module Datadog module InstanceMethods : ::Selenium::WebDriver::Navigation def to: (String url) -> void + def datadog_integration: () -> Datadog::CI::Contrib::Integration + def datadog_configuration: () -> untyped end end diff --git a/sig/datadog/ci/contrib/selenium/patcher.rbs b/sig/datadog/ci/contrib/selenium/patcher.rbs index 83295b0b..06455eeb 100644 --- a/sig/datadog/ci/contrib/selenium/patcher.rbs +++ b/sig/datadog/ci/contrib/selenium/patcher.rbs @@ -5,8 +5,6 @@ module Datadog module Patcher include Datadog::CI::Contrib::Patcher - def self?.target_version: () -> untyped - def self?.patch: () -> untyped end end diff --git a/sig/datadog/ci/contrib/simplecov/integration.rbs b/sig/datadog/ci/contrib/simplecov/integration.rbs index 679df849..76976377 100644 --- a/sig/datadog/ci/contrib/simplecov/integration.rbs +++ b/sig/datadog/ci/contrib/simplecov/integration.rbs @@ -2,19 +2,16 @@ module Datadog module CI module Contrib module Simplecov - class Integration - extend Datadog::CI::Contrib::Integration::ClassMethods - include Datadog::CI::Contrib::Integration::InstanceMethods - + class Integration < Datadog::CI::Contrib::Integration MINIMUM_VERSION: Gem::Version - def self.version: () -> untyped + def version: () -> untyped - def self.loaded?: () -> bool + def loaded?: () -> bool - def self.compatible?: () -> bool + def compatible?: () -> bool - def auto_instrument?: () -> bool + def late_instrument?: () -> bool def new_configuration: () -> untyped diff --git a/sig/datadog/ci/contrib/simplecov/patcher.rbs b/sig/datadog/ci/contrib/simplecov/patcher.rbs index 65cb472f..c887a181 100644 --- a/sig/datadog/ci/contrib/simplecov/patcher.rbs +++ b/sig/datadog/ci/contrib/simplecov/patcher.rbs @@ -5,8 +5,6 @@ module Datadog module Patcher include Datadog::CI::Contrib::Patcher - def self?.target_version: () -> untyped - def self?.patch: () -> untyped end end diff --git a/spec/datadog/ci/configuration/settings_spec.rb b/spec/datadog/ci/configuration/settings_spec.rb index 9a8fe759..1d7951a3 100644 --- a/spec/datadog/ci/configuration/settings_spec.rb +++ b/spec/datadog/ci/configuration/settings_spec.rb @@ -1,45 +1,43 @@ # frozen_string_literal: true # Dummy Integration -class FakeIntegration - include Datadog::CI::Contrib::Integration +module Fake + class Integration < Datadog::CI::Contrib::Integration + module Patcher + module_function - register_as :fake + def patched? + @patched + end - module Patcher - module_function + def patch + @patched = true + end - def patched? - @patched + def reset + @patched = nil + end end - def patch - @patched = true + def version + "0.1" end - def reset - @patched = nil + def loaded? + true end - end - def self.version - "0.1" - end - - def self.loaded? - true - end - - def self.compatible? - true - end + def compatible? + true + end - def self.auto_instrument? - false - end + def late_instrument? + false + end - def patcher - Patcher + def patcher + Patcher + end end end @@ -580,7 +578,6 @@ def patcher describe "#instrument" do let(:integration_name) { :fake } - let(:integration) { FakeIntegration.new } let(:enabled) { true } subject(:instrument) { settings.ci.instrument(integration_name, enabled: enabled) } @@ -590,7 +587,7 @@ def patcher end after do - FakeIntegration::Patcher.reset + Fake::Integration::Patcher.reset end context "ci enabled" do @@ -598,14 +595,14 @@ def patcher context "when integration exists" do it "patches the integration" do - expect(FakeIntegration::Patcher).to receive(:patch) + expect(Fake::Integration::Patcher).to receive(:patch) instrument end context "when called multiple times" do it "does not patch the integration multiple times" do - expect(FakeIntegration::Patcher).to receive(:patch).and_call_original.once + expect(Fake::Integration::Patcher).to receive(:patch).and_call_original.once instrument instrument @@ -613,30 +610,30 @@ def patcher end context "when not loaded" do - before { allow(FakeIntegration).to receive(:loaded?).and_return(false) } + before { allow_any_instance_of(Fake::Integration).to receive(:loaded?).and_return(false) } it "does not patch the integration" do - expect(FakeIntegration::Patcher).to_not receive(:patch) + expect(Fake::Integration::Patcher).to_not receive(:patch) instrument end end context "when not available" do - before { allow(FakeIntegration).to receive(:available?).and_return(false) } + before { allow_any_instance_of(Fake::Integration).to receive(:available?).and_return(false) } it "does not patch the integration" do - expect(FakeIntegration::Patcher).to_not receive(:patch) + expect(Fake::Integration::Patcher).to_not receive(:patch) instrument end end context "when not compatible" do - before { allow(FakeIntegration).to receive(:compatible?).and_return(false) } + before { allow_any_instance_of(Fake::Integration).to receive(:compatible?).and_return(false) } it "does not patch the integration" do - expect(FakeIntegration::Patcher).to_not receive(:patch) + expect(Fake::Integration::Patcher).to_not receive(:patch) instrument end @@ -646,7 +643,7 @@ def patcher let(:enabled) { false } it "does not patch the integration" do - expect(FakeIntegration::Patcher).to_not receive(:patch) + expect(Fake::Integration::Patcher).to_not receive(:patch) instrument end @@ -657,7 +654,7 @@ def patcher let(:integration_name) { :not_existing } it "does not patch the integration" do - expect { instrument }.to raise_error(Datadog::CI::Configuration::Settings::InvalidIntegrationError) + expect { instrument }.to raise_error(Datadog::CI::Contrib::Instrumentation::InvalidIntegrationError) end end @@ -665,7 +662,7 @@ def patcher let(:ci_enabled) { false } it "does not patch the integration" do - expect(FakeIntegration::Patcher).to_not receive(:patch) + expect(Fake::Integration::Patcher).to_not receive(:patch) instrument end end diff --git a/spec/datadog/ci/contrib/cucumber/instrumentation_spec.rb b/spec/datadog/ci/contrib/cucumber/instrumentation_spec.rb index e775fd4e..e923435b 100644 --- a/spec/datadog/ci/contrib/cucumber/instrumentation_spec.rb +++ b/spec/datadog/ci/contrib/cucumber/instrumentation_spec.rb @@ -4,6 +4,7 @@ require "securerandom" RSpec.describe "Cucumber instrumentation" do + let(:integration) { Datadog::CI::Contrib::Instrumentation.fetch_integration(:cucumber) } let(:cucumber_features_root) { File.join(__dir__, "features") } let(:enable_retries_failed) { false } let(:single_test_retries_count) { 5 } @@ -34,9 +35,9 @@ let(:bundle_path) { "step_definitions/helpers" } end - let(:cucumber_9_or_above) { Gem::Version.new("9.0.0") <= Datadog::CI::Contrib::Cucumber::Integration.version } - let(:cucumber_8_or_above) { Gem::Version.new("8.0.0") <= Datadog::CI::Contrib::Cucumber::Integration.version } - let(:cucumber_4_or_above) { Gem::Version.new("4.0.0") <= Datadog::CI::Contrib::Cucumber::Integration.version } + let(:cucumber_9_or_above) { Gem::Version.new("9.0.0") <= integration.version } + let(:cucumber_8_or_above) { Gem::Version.new("8.0.0") <= integration.version } + let(:cucumber_4_or_above) { Gem::Version.new("4.0.0") <= integration.version } let(:run_id) { SecureRandom.random_number(2**64 - 1) } let(:steps_file_definition_path) { "spec/datadog/ci/contrib/cucumber/features/step_definitions/steps.rb" } @@ -121,10 +122,7 @@ expect(scenario_span).to have_test_tag(:type, "test") expect(scenario_span).to have_test_tag(:framework, "cucumber") - expect(scenario_span).to have_test_tag( - :framework_version, - Datadog::CI::Contrib::Cucumber::Integration.version.to_s - ) + expect(scenario_span).to have_test_tag(:framework_version, integration.version.to_s) expect(scenario_span).to have_pass_status @@ -174,10 +172,7 @@ expect(test_session_span.service).to eq("jalapenos") expect(test_session_span).to have_test_tag(:span_kind, "test") expect(test_session_span).to have_test_tag(:framework, "cucumber") - expect(test_session_span).to have_test_tag( - :framework_version, - Datadog::CI::Contrib::Cucumber::Integration.version.to_s - ) + expect(test_session_span).to have_test_tag(:framework_version, integration.version.to_s) expect(test_session_span).to have_pass_status # ITR @@ -198,7 +193,7 @@ expect(test_module_span).to have_test_tag(:framework, "cucumber") expect(test_module_span).to have_test_tag( :framework_version, - Datadog::CI::Contrib::Cucumber::Integration.version.to_s + integration.version.to_s ) expect(test_module_span).to have_pass_status end @@ -211,7 +206,7 @@ expect(first_test_suite_span).to have_test_tag(:framework, "cucumber") expect(first_test_suite_span).to have_test_tag( :framework_version, - Datadog::CI::Contrib::Cucumber::Integration.version.to_s + integration.version.to_s ) expect(first_test_suite_span).to have_test_tag( diff --git a/spec/datadog/ci/contrib/cucumber/integration_spec.rb b/spec/datadog/ci/contrib/cucumber/integration_spec.rb index de70ee02..267fe0fd 100644 --- a/spec/datadog/ci/contrib/cucumber/integration_spec.rb +++ b/spec/datadog/ci/contrib/cucumber/integration_spec.rb @@ -4,7 +4,7 @@ let(:integration) { described_class.new } describe ".version" do - subject(:version) { described_class.version } + subject(:version) { integration.version } context 'when the "cucumber" gem is loaded' do include_context "loaded gems", "cucumber" => described_class::MINIMUM_VERSION @@ -18,7 +18,7 @@ end describe ".loaded?" do - subject(:loaded?) { described_class.loaded? } + subject(:loaded?) { integration.loaded? } context "when Cucumber::Runtime is defined" do before { stub_const("Cucumber::Runtime", Class.new) } @@ -34,7 +34,7 @@ end describe ".compatible?" do - subject(:compatible?) { described_class.compatible? } + subject(:compatible?) { integration.compatible? } context 'when "cucumber" gem is loaded with a version' do context "that is less than the minimum" do @@ -54,8 +54,8 @@ end end - describe "#auto_instrument?" do - subject(:auto_instrument?) { integration.auto_instrument? } + describe "#late_instrument?" do + subject(:late_instrument?) { integration.late_instrument? } it { is_expected.to be(false) } end diff --git a/spec/datadog/ci/contrib/knapsack_rspec/instrumentation_spec.rb b/spec/datadog/ci/contrib/knapsack_rspec/instrumentation_spec.rb index 65486f8d..4f56c886 100644 --- a/spec/datadog/ci/contrib/knapsack_rspec/instrumentation_spec.rb +++ b/spec/datadog/ci/contrib/knapsack_rspec/instrumentation_spec.rb @@ -1,7 +1,9 @@ require "knapsack_pro" require "fileutils" -RSpec.describe "RSpec instrumentation with Knapsack Pro runner in queue mode" do +RSpec.describe "Knapsack Pro runner when Datadog::CI is configured during the knapsack run like in rspec_go rake task" do + let(:integration) { Datadog::CI::Contrib::Instrumentation.fetch_integration(:rspec) } + before do # expect that public manual API isn't used expect(Datadog::CI).to receive(:start_test_session).never @@ -10,15 +12,20 @@ expect(Datadog::CI).to receive(:start_test).never end - include_context "CI mode activated" do - let(:integration_name) { :rspec } - end + include_context "CI mode activated" before do + allow_any_instance_of(Datadog::Core::Remote::Negotiation).to( + receive(:endpoint?).with("/evp_proxy/v4/").and_return(true) + ) + + allow(Datadog::CI::Utils::TestRun).to receive(:command).and_return("knapsack:queue:rspec") + allow_any_instance_of(KnapsackPro::Runners::Queue::RSpecRunner).to receive(:test_file_paths).and_return( ["./spec/datadog/ci/contrib/knapsack_rspec/suite_under_test/some_test_rspec.rb"], [] ) + # raise to prevent Knapsack from running Kernel.exit(0) allow(KnapsackPro::Report).to receive(:save_node_queue_to_api).and_raise(ArgumentError) end @@ -26,12 +33,13 @@ it "instruments this rspec session" do with_new_rspec_environment do ClimateControl.modify( - "KNAPSACK_PRO_CI_NODE_BUILD_ID" => "142", + "KNAPSACK_PRO_CI_NODE_BUILD_ID" => "144", "KNAPSACK_PRO_TEST_SUITE_TOKEN_RSPEC" => "example_token", - "KNAPSACK_PRO_FIXED_QUEUE_SPLIT" => "true" + "KNAPSACK_PRO_FIXED_QUEUE_SPLIT" => "true", + "KNAPSACK_PRO_QUEUE_ID" => nil ) do KnapsackPro::Adapters::RSpecAdapter.bind - KnapsackPro::Runners::Queue::RSpecRunner.run("", devnull, devnull) + KnapsackPro::Runners::Queue::RSpecRunner.run("--require knapsack_helper", devnull, devnull) rescue ArgumentError # suppress invalid API key error end @@ -39,6 +47,9 @@ # test session and module traced expect(test_session_span).not_to be_nil + expect(test_session_span).to have_test_tag(:framework, "rspec") + expect(test_session_span).to have_test_tag(:framework_version, integration.version.to_s) + expect(test_module_span).not_to be_nil # test session and module are failed diff --git a/spec/datadog/ci/contrib/knapsack_rspec_go/instrumentation_spec.rb b/spec/datadog/ci/contrib/knapsack_rspec_go/instrumentation_spec.rb deleted file mode 100644 index 43606d14..00000000 --- a/spec/datadog/ci/contrib/knapsack_rspec_go/instrumentation_spec.rb +++ /dev/null @@ -1,76 +0,0 @@ -require "knapsack_pro" -require "fileutils" - -RSpec.describe "Knapsack Pro runner when Datadog::CI is configured during the knapsack run like in rspec_go rake task" do - before do - # expect that public manual API isn't used - expect(Datadog::CI).to receive(:start_test_session).never - expect(Datadog::CI).to receive(:start_test_module).never - expect(Datadog::CI).to receive(:start_test_suite).never - expect(Datadog::CI).to receive(:start_test).never - end - - include_context "CI mode activated" do - let(:integration_name) { :rspec } - end - - before do - allow_any_instance_of(Datadog::Core::Remote::Negotiation).to( - receive(:endpoint?).with("/evp_proxy/v4/").and_return(true) - ) - - allow(Datadog::CI::Utils::TestRun).to receive(:command).and_return("knapsack:queue:rspec") - - allow_any_instance_of(KnapsackPro::Runners::Queue::RSpecRunner).to receive(:test_file_paths).and_return( - ["./spec/datadog/ci/contrib/knapsack_rspec_go/suite_under_test/some_test_rspec.rb"], - [] - ) - - # raise to prevent Knapsack from running Kernel.exit(0) - allow(KnapsackPro::Report).to receive(:save_node_queue_to_api).and_raise(ArgumentError) - end - - it "instruments this rspec session" do - with_new_rspec_environment do - ClimateControl.modify( - "KNAPSACK_PRO_CI_NODE_BUILD_ID" => "144", - "KNAPSACK_PRO_TEST_SUITE_TOKEN_RSPEC" => "example_token", - "KNAPSACK_PRO_FIXED_QUEUE_SPLIT" => "true", - "KNAPSACK_PRO_QUEUE_ID" => nil - ) do - KnapsackPro::Adapters::RSpecAdapter.bind - KnapsackPro::Runners::Queue::RSpecRunner.run("--require knapsack_helper", devnull, devnull) - rescue ArgumentError - # suppress invalid API key error - end - end - - # test session and module traced - expect(test_session_span).not_to be_nil - expect(test_module_span).not_to be_nil - - # test session and module are failed - expect([test_session_span, test_module_span]).to all have_fail_status - - # single test suite span - expect(test_suite_spans).to have(1).item - expect(test_suite_spans.first).to have_test_tag(:status, Datadog::CI::Ext::Test::Status::FAIL) - expect(test_suite_spans.first).to have_test_tag( - :suite, - "SomeTest at ./spec/datadog/ci/contrib/knapsack_rspec_go/suite_under_test/some_test_rspec.rb" - ) - - # there is test span for every test case - expect(test_spans).to have(2).items - # test spans belong to a single test suite - expect(test_spans).to have_unique_tag_values_count(:test_suite_id, 1) - expect(test_spans).to have_tag_values_no_order( - :status, - [Datadog::CI::Ext::Test::Status::FAIL, Datadog::CI::Ext::Test::Status::PASS] - ) - - # every test span is connected to test module and test session - expect(test_spans).to all have_test_tag(:test_module_id) - expect(test_spans).to all have_test_tag(:test_session_id) - end -end diff --git a/spec/datadog/ci/contrib/knapsack_rspec_go/suite_under_test/some_test_rspec.rb b/spec/datadog/ci/contrib/knapsack_rspec_go/suite_under_test/some_test_rspec.rb deleted file mode 100644 index 7b775cb9..00000000 --- a/spec/datadog/ci/contrib/knapsack_rspec_go/suite_under_test/some_test_rspec.rb +++ /dev/null @@ -1,13 +0,0 @@ -require "rspec" - -RSpec.describe "SomeTest" do - context "nested" do - it "foo" do - # DO NOTHING - end - - it "fails" do - expect(1).to eq(2) - end - end -end diff --git a/spec/datadog/ci/contrib/minitest/instrumentation_spec.rb b/spec/datadog/ci/contrib/minitest/instrumentation_spec.rb index 942089dc..89b45d81 100644 --- a/spec/datadog/ci/contrib/minitest/instrumentation_spec.rb +++ b/spec/datadog/ci/contrib/minitest/instrumentation_spec.rb @@ -10,6 +10,8 @@ module Kernel end RSpec.describe "Minitest instrumentation" do + let(:integration) { Datadog::CI::Contrib::Instrumentation.fetch_integration(:minitest) } + before do # expect that public manual API isn't used expect(Datadog::CI).to receive(:start_test_session).never @@ -77,7 +79,7 @@ def test_foo expect(span).to have_test_tag(:framework, "minitest") expect(span).to have_test_tag( :framework_version, - Datadog::CI::Contrib::Minitest::Integration.version.to_s + integration.version.to_s ) expect(span).to have_pass_status @@ -86,7 +88,7 @@ def test_foo :source_file, "spec/datadog/ci/contrib/minitest/instrumentation_spec.rb" ) - expect(span).to have_test_tag(:source_start, "59") + expect(span).to have_test_tag(:source_start, "61") expect(span).to have_test_tag( :codeowners, "[\"@DataDog/ruby-guild\", \"@DataDog/ci-app-libraries\"]" @@ -437,7 +439,7 @@ def test_pass_other expect(test_session_span).to have_test_tag(:framework, "minitest") expect(test_session_span).to have_test_tag( :framework_version, - Datadog::CI::Contrib::Minitest::Integration.version.to_s + integration.version.to_s ) # ITR @@ -462,7 +464,7 @@ def test_pass_other expect(test_module_span).to have_test_tag(:framework, "minitest") expect(test_module_span).to have_test_tag( :framework_version, - Datadog::CI::Contrib::Minitest::Integration.version.to_s + integration.version.to_s ) expect(test_module_span).to have_pass_status end @@ -477,14 +479,14 @@ def test_pass_other expect(first_test_suite_span).to have_test_tag(:framework, "minitest") expect(first_test_suite_span).to have_test_tag( :framework_version, - Datadog::CI::Contrib::Minitest::Integration.version.to_s + integration.version.to_s ) expect(first_test_suite_span).to have_test_tag( :source_file, "spec/datadog/ci/contrib/minitest/instrumentation_spec.rb" ) - expect(first_test_suite_span).to have_test_tag(:source_start, "415") + expect(first_test_suite_span).to have_test_tag(:source_start, "417") expect(first_test_suite_span).to have_test_tag( :codeowners, "[\"@DataDog/ruby-guild\", \"@DataDog/ci-app-libraries\"]" @@ -507,7 +509,7 @@ def test_pass_other expect(first_test_span).to have_test_tag(:framework, "minitest") expect(first_test_span).to have_test_tag( :framework_version, - Datadog::CI::Contrib::Minitest::Integration.version.to_s + integration.version.to_s ) expect(first_test_span).to have_pass_status diff --git a/spec/datadog/ci/contrib/minitest/integration_spec.rb b/spec/datadog/ci/contrib/minitest/integration_spec.rb index 105f17da..d7655f16 100644 --- a/spec/datadog/ci/contrib/minitest/integration_spec.rb +++ b/spec/datadog/ci/contrib/minitest/integration_spec.rb @@ -4,7 +4,7 @@ let(:integration) { described_class.new } describe ".version" do - subject(:version) { described_class.version } + subject(:version) { integration.version } context 'when the "minitest" gem is loaded' do include_context "loaded gems", "minitest" => described_class::MINIMUM_VERSION @@ -18,7 +18,7 @@ end describe ".loaded?" do - subject(:loaded?) { described_class.loaded? } + subject(:loaded?) { integration.loaded? } context "when Minitest is defined" do it { is_expected.to be true } @@ -26,7 +26,7 @@ end describe ".compatible?" do - subject(:compatible?) { described_class.compatible? } + subject(:compatible?) { integration.compatible? } context 'when "minitest" gem is loaded with a version' do context "that is less than the minimum" do @@ -46,8 +46,8 @@ end end - describe "#auto_instrument?" do - subject(:auto_instrument?) { integration.auto_instrument? } + describe "#late_instrument?" do + subject(:late_instrument?) { integration.late_instrument? } it { is_expected.to be(false) } end diff --git a/spec/datadog/ci/contrib/rspec/instrumentation_spec.rb b/spec/datadog/ci/contrib/rspec/instrumentation_spec.rb index 7d71a6b9..22e2c1ae 100644 --- a/spec/datadog/ci/contrib/rspec/instrumentation_spec.rb +++ b/spec/datadog/ci/contrib/rspec/instrumentation_spec.rb @@ -1,6 +1,8 @@ require "time" -RSpec.describe "RSpec hooks" do +RSpec.describe "RSpec instrumentation" do + let(:integration) { Datadog::CI::Contrib::Instrumentation.fetch_integration(:rspec) } + before do # expect that public manual API isn't used expect(Datadog::CI).to receive(:start_test_session).never @@ -139,7 +141,7 @@ def rspec_session_run( expect(first_test_span).to have_test_tag(:framework, "rspec") expect(first_test_span).to have_test_tag( :framework_version, - Datadog::CI::Contrib::RSpec::Integration.version.to_s + integration.version.to_s ) expect(first_test_span).to have_pass_status @@ -148,7 +150,7 @@ def rspec_session_run( :source_file, "spec/datadog/ci/contrib/rspec/instrumentation_spec.rb" ) - expect(first_test_span).to have_test_tag(:source_start, "121") + expect(first_test_span).to have_test_tag(:source_start, "123") expect(first_test_span).to have_test_tag( :codeowners, "[\"@DataDog/ruby-guild\", \"@DataDog/ci-app-libraries\"]" @@ -525,7 +527,7 @@ def expect_failure expect(test_session_span).to have_test_tag(:framework, "rspec") expect(test_session_span).to have_test_tag( :framework_version, - Datadog::CI::Contrib::RSpec::Integration.version.to_s + integration.version.to_s ) expect(test_session_span).not_to have_test_tag(:code_coverage_enabled) @@ -554,7 +556,7 @@ def expect_failure expect(test_module_span).to have_test_tag(:framework, "rspec") expect(test_module_span).to have_test_tag( :framework_version, - Datadog::CI::Contrib::RSpec::Integration.version.to_s + integration.version.to_s ) expect(test_module_span).to have_pass_status end @@ -571,14 +573,14 @@ def expect_failure expect(first_test_suite_span).to have_test_tag(:framework, "rspec") expect(first_test_suite_span).to have_test_tag( :framework_version, - Datadog::CI::Contrib::RSpec::Integration.version.to_s + integration.version.to_s ) expect(first_test_suite_span).to have_test_tag( :source_file, "spec/datadog/ci/contrib/rspec/instrumentation_spec.rb" ) - expect(first_test_suite_span).to have_test_tag(:source_start, "39") + expect(first_test_suite_span).to have_test_tag(:source_start, "41") expect(first_test_suite_span).to have_test_tag( :codeowners, "[\"@DataDog/ruby-guild\", \"@DataDog/ci-app-libraries\"]" diff --git a/spec/datadog/ci/contrib/rspec/integration_spec.rb b/spec/datadog/ci/contrib/rspec/integration_spec.rb index b387a13a..a2f482d6 100644 --- a/spec/datadog/ci/contrib/rspec/integration_spec.rb +++ b/spec/datadog/ci/contrib/rspec/integration_spec.rb @@ -4,7 +4,7 @@ let(:integration) { described_class.new } describe ".version" do - subject(:version) { described_class.version } + subject(:version) { integration.version } context 'when the "rspec-core" gem is loaded' do include_context "loaded gems", "rspec-core" => described_class::MINIMUM_VERSION @@ -18,7 +18,7 @@ end describe ".loaded?" do - subject(:loaded?) { described_class.loaded? } + subject(:loaded?) { integration.loaded? } context "when RSpec is defined" do it { is_expected.to be true } @@ -26,7 +26,7 @@ end describe ".compatible?" do - subject(:compatible?) { described_class.compatible? } + subject(:compatible?) { integration.compatible? } context 'when "rspec-core" gem is loaded with a version' do context "that is less than the minimum" do @@ -46,8 +46,8 @@ end end - describe "#auto_instrument?" do - subject(:auto_instrument?) { integration.auto_instrument? } + describe "#late_instrument?" do + subject(:late_instrument?) { integration.late_instrument? } it { is_expected.to be(false) } end