Skip to content

Commit

Permalink
add datadog ci plugin and reporter for minitest to track test session…
Browse files Browse the repository at this point in the history
… start/end events
  • Loading branch information
anmarchenko committed Dec 15, 2023
1 parent bfbdb51 commit 14eb7c2
Show file tree
Hide file tree
Showing 11 changed files with 201 additions and 14 deletions.
2 changes: 2 additions & 0 deletions .standard_todo.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,5 @@ ignore:
- Performance/UnfreezeString
- Appraisals:
- Style/Alias
- spec/datadog/ci/contrib/minitest/instrumentation_spec.rb:
- Lint/ConstantDefinitionInBlock
2 changes: 2 additions & 0 deletions Steepfile
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ target :lib do
check "lib"

ignore "lib/datadog/ci/configuration/settings.rb"
ignore "lib/datadog/ci/contrib/minitest/plugin.rb"

library "pathname"
library "json"
Expand All @@ -20,4 +21,5 @@ target :lib do
library "rspec"
library "cucumber"
library "msgpack"
library "weakref"
end
2 changes: 1 addition & 1 deletion lib/datadog/ci/contrib/minitest/configuration/settings.rb
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ class Settings < Datadog::CI::Contrib::Settings

option :service_name do |o|
o.type :string
o.default { Datadog.configuration.service_without_fallback || Ext::SERVICE_NAME }
o.default { Datadog.configuration.service_without_fallback || Ext::DEFAULT_SERVICE_NAME }
end

# @deprecated Will be removed in 1.0
Expand Down
10 changes: 6 additions & 4 deletions lib/datadog/ci/contrib/minitest/ext.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,15 @@ module Minitest
# Minitest integration constants
# TODO: mark as `@public_api` when GA, to protect from resource and tag name changes.
module Ext
APP = "minitest"
ENV_ENABLED = "DD_TRACE_MINITEST_ENABLED"
ENV_OPERATION_NAME = "DD_TRACE_MINITEST_OPERATION_NAME"

FRAMEWORK = "minitest"

DEFAULT_SERVICE_NAME = "minitest"

# TODO: remove in 1.0
ENV_OPERATION_NAME = "DD_TRACE_MINITEST_OPERATION_NAME"
OPERATION_NAME = "minitest.test"
SERVICE_NAME = "minitest"
TEST_TYPE = "test"
end
end
end
Expand Down
4 changes: 2 additions & 2 deletions lib/datadog/ci/contrib/minitest/hooks.rb
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ def before_setup
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_TYPE => Ext::TEST_TYPE
CI::Ext::Test::TAG_TYPE => CI::Ext::Test::TEST_TYPE
},
service: configuration[:service_name]
)
Expand All @@ -51,7 +51,7 @@ def after_teardown
private

def configuration
::Datadog.configuration.ci[:minitest]
Datadog.configuration.ci[:minitest]
end
end
end
Expand Down
4 changes: 4 additions & 0 deletions lib/datadog/ci/contrib/minitest/patcher.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# frozen_string_literal: true

require_relative "hooks"
require_relative "plugin"

module Datadog
module CI
Expand All @@ -18,6 +19,9 @@ def target_version

def patch
::Minitest::Test.include(Hooks)
::Minitest.include(Plugin)

::Minitest.extensions << "datadog_ci"
end
end
end
Expand Down
73 changes: 73 additions & 0 deletions lib/datadog/ci/contrib/minitest/plugin.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
# frozen_string_literal: true

require "weakref"

require_relative "../../ext/test"
require_relative "ext"

module Datadog
module CI
module Contrib
module Minitest
module Plugin
def self.included(base)
base.extend(ClassMethods)
end

module ClassMethods
def plugin_datadog_ci_init(*)
return unless datadog_configuration[:enabled]

test_session = CI.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_TYPE => CI::Ext::Test::TEST_TYPE
},
service: datadog_configuration[:service_name]
)
CI.start_test_module(test_session.name)

# we create dynamic class here to avoid referencing ::Minitest constant
# in datadog-ci class definitions because Minitest is not always available
datadog_reporter_klass = Class.new(::Minitest::AbstractReporter) do
def initialize(reporter)
# This creates circular reference as reporter holds reference to this reporter.
# To make sure that reporter can be garbage collected, we use WeakRef.
@reporter = WeakRef.new(reporter)
end

def report
active_test_session = CI.active_test_session
active_test_module = CI.active_test_module

return unless @reporter.weakref_alive?
return if active_test_session.nil? || active_test_module.nil?

if @reporter.passed?
active_test_module.passed!
active_test_session.passed!
else
active_test_module.failed!
active_test_session.failed!
end

active_test_module.finish
active_test_session.finish
end
end

reporter.reporters << datadog_reporter_klass.new(reporter)
end

private

def datadog_configuration
Datadog.configuration.ci[:minitest]
end
end
end
end
end
end
end
6 changes: 1 addition & 5 deletions sig/datadog/ci/contrib/minitest/ext.rbs
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,6 @@ module Datadog
module Contrib
module Minitest
module Ext
APP: String

ENV_ENABLED: String

ENV_OPERATION_NAME: String
Expand All @@ -13,9 +11,7 @@ module Datadog

OPERATION_NAME: String

SERVICE_NAME: String

TEST_TYPE: String
DEFAULT_SERVICE_NAME: String
end
end
end
Expand Down
26 changes: 26 additions & 0 deletions sig/datadog/ci/contrib/minitest/plugin.rbs
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
module Datadog
module CI
module Contrib
module Minitest
module Plugin
def self.included: (untyped base) -> untyped

module ClassMethods
attr_reader reporter: WeakRef
@reporter: WeakRef

def plugin_datadog_ci_init: (*untyped) -> (nil | untyped)

def initialize: (untyped reporter) -> void

def report: () -> (nil | untyped)

private

def datadog_configuration: () -> untyped
end
end
end
end
end
end
80 changes: 78 additions & 2 deletions spec/datadog/ci/contrib/minitest/instrumentation_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
require "minitest"
require "minitest/spec"

RSpec.describe "Minitest hooks" do
RSpec.describe "Minitest instrumentation" do
include_context "CI mode activated" do
let(:integration_name) { :minitest }
let(:integration_options) { {service_name: "ltest"} }
Expand Down Expand Up @@ -34,7 +34,7 @@ def test_foo
"spec/datadog/ci/contrib/minitest/instrumentation_spec.rb"
)
expect(span.get_tag(Datadog::CI::Ext::Test::TAG_SPAN_KIND)).to eq(Datadog::CI::Ext::AppTypes::TYPE_TEST)
expect(span.get_tag(Datadog::CI::Ext::Test::TAG_TYPE)).to eq(Datadog::CI::Contrib::Minitest::Ext::TEST_TYPE)
expect(span.get_tag(Datadog::CI::Ext::Test::TAG_TYPE)).to eq(Datadog::CI::Ext::Test::TEST_TYPE)
expect(span.get_tag(Datadog::CI::Ext::Test::TAG_FRAMEWORK)).to eq(Datadog::CI::Contrib::Minitest::Ext::FRAMEWORK)
expect(span.get_tag(Datadog::CI::Ext::Test::TAG_FRAMEWORK_VERSION)).to eq(
Datadog::CI::Contrib::Minitest::Integration.version.to_s
Expand Down Expand Up @@ -352,4 +352,80 @@ def test_foo
expect_skip
end
end

context "run minitest suite" do
before(:context) do
Minitest::Runnable.reset

class SomeTest < Minitest::Test
def test_pass
assert true
end
end
end

before do
Minitest.run([])
end

it "creates a test session span" do
expect(test_session_span).not_to be_nil
expect(test_session_span.span_type).to eq(Datadog::CI::Ext::AppTypes::TYPE_TEST_SESSION)
expect(test_session_span.get_tag(Datadog::CI::Ext::Test::TAG_SPAN_KIND)).to eq(
Datadog::CI::Ext::AppTypes::TYPE_TEST
)
expect(test_session_span.get_tag(Datadog::CI::Ext::Test::TAG_TYPE)).to eq(
Datadog::CI::Ext::Test::TEST_TYPE
)
expect(test_session_span.get_tag(Datadog::CI::Ext::Test::TAG_FRAMEWORK)).to eq(
Datadog::CI::Contrib::Minitest::Ext::FRAMEWORK
)
expect(test_session_span.get_tag(Datadog::CI::Ext::Test::TAG_FRAMEWORK_VERSION)).to eq(
Datadog::CI::Contrib::Minitest::Integration.version.to_s
)
expect(test_session_span.get_tag(Datadog::CI::Ext::Test::TAG_STATUS)).to eq(
Datadog::CI::Ext::Test::Status::PASS
)
end

it "creates a test module span" do
expect(test_module_span).not_to be_nil

expect(test_module_span.span_type).to eq(Datadog::CI::Ext::AppTypes::TYPE_TEST_MODULE)
expect(test_module_span.name).to eq(test_command)

expect(test_module_span.get_tag(Datadog::CI::Ext::Test::TAG_SPAN_KIND)).to eq(
Datadog::CI::Ext::AppTypes::TYPE_TEST
)
expect(test_module_span.get_tag(Datadog::CI::Ext::Test::TAG_TYPE)).to eq(
Datadog::CI::Ext::Test::TEST_TYPE
)
expect(test_module_span.get_tag(Datadog::CI::Ext::Test::TAG_FRAMEWORK)).to eq(
Datadog::CI::Contrib::Minitest::Ext::FRAMEWORK
)
expect(test_module_span.get_tag(Datadog::CI::Ext::Test::TAG_FRAMEWORK_VERSION)).to eq(
Datadog::CI::Contrib::Minitest::Integration.version.to_s
)
expect(test_module_span.get_tag(Datadog::CI::Ext::Test::TAG_STATUS)).to eq(
Datadog::CI::Ext::Test::Status::PASS
)
end

it "creates test span and connects it to the session and module" do
expect(test_spans.count).to eq(1)

expect(first_test_span.get_tag(Datadog::CI::Ext::Test::TAG_FRAMEWORK)).to eq(
Datadog::CI::Contrib::Minitest::Ext::FRAMEWORK
)
expect(first_test_span.get_tag(Datadog::CI::Ext::Test::TAG_FRAMEWORK_VERSION)).to eq(
Datadog::CI::Contrib::Minitest::Integration.version.to_s
)
expect(first_test_span.get_tag(Datadog::CI::Ext::Test::TAG_STATUS)).to eq(
Datadog::CI::Ext::Test::Status::PASS
)

expect(first_test_span.get_tag(Datadog::CI::Ext::Test::TAG_TEST_SESSION_ID)).to eq(test_session_span.id.to_s)
expect(first_test_span.get_tag(Datadog::CI::Ext::Test::TAG_TEST_MODULE_ID)).to eq(test_module_span.id.to_s)
end
end
end
6 changes: 6 additions & 0 deletions vendor/rbs/weakref/0/weakref.rbs
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# as rbs misses delegator support, we make WeakRef a subclass of CompositeReporter
# for our current use case
class WeakRef < Minitest::CompositeReporter
def initialize: (untyped obj) -> untyped
def weakref_alive?: () -> bool
end

0 comments on commit 14eb7c2

Please sign in to comment.