Skip to content

Commit

Permalink
Merge pull request #239 from DataDog/anmarchenko/source_location_for_…
Browse files Browse the repository at this point in the history
…test_suites

[SDTEST-301] add source location info to test suites
  • Loading branch information
anmarchenko authored Sep 24, 2024
2 parents 4871058 + c1fdf81 commit 17b2e4f
Show file tree
Hide file tree
Showing 16 changed files with 106 additions and 25 deletions.
28 changes: 25 additions & 3 deletions lib/datadog/ci/contrib/cucumber/formatter.rb
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,12 @@ def on_test_case_started(event)
tags[CI::Ext::Test::TAG_PARAMETERS] = Utils::TestRun.test_parameters(arguments: parameters)
end

start_test_suite(test_suite_name) unless same_test_suite_as_current?(test_suite_name)
unless same_test_suite_as_current?(test_suite_name)
start_test_suite(
test_suite_name,
tags: test_suite_source_file_tags(event.test_case)
)
end

test_span = test_visibility_component.trace_test(
event.test_case.name,
Expand Down Expand Up @@ -146,10 +151,10 @@ def finish_session(result)
test_session.finish
end

def start_test_suite(test_suite_name)
def start_test_suite(test_suite_name, tags: {})
finish_current_test_suite

@current_test_suite = test_visibility_component.start_test_suite(test_suite_name)
@current_test_suite = test_visibility_component.start_test_suite(test_suite_name, tags: tags)
end

def finish_current_test_suite
Expand Down Expand Up @@ -201,6 +206,23 @@ def configuration
def test_visibility_component
Datadog.send(:components).test_visibility
end

def test_suite_source_file_tags(test_case)
if test_case.respond_to?(:parent_locations)
# supported in cucumber >= 9.0
source_file = test_case.parent_locations.file
line_number = test_case.parent_locations.line.to_s
else
# fallback for cucumber < 9.0
source_file = test_case.location.file
line_number = "1"
end

{
CI::Ext::Test::TAG_SOURCE_FILE => Git::LocalRepository.relative_to_root(source_file),
CI::Ext::Test::TAG_SOURCE_START => line_number.to_s
}
end
end
end
end
Expand Down
8 changes: 4 additions & 4 deletions lib/datadog/ci/contrib/minitest/helpers.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ module Contrib
module Minitest
module Helpers
def self.test_suite_name(klass, method_name)
source_location = extract_source_location_from_class(klass)
source_location = extract_source_location_from_class(klass)&.first
# if we are in anonymous class, fallback to the method source location
if source_location.nil?
source_location, = klass.instance_method(method_name).source_location
Expand All @@ -23,11 +23,11 @@ def self.parallel?(klass)
end

def self.extract_source_location_from_class(klass)
return nil if klass.nil? || klass.name.nil?
return [] if klass.nil? || klass.name.nil?

klass.const_source_location(klass.name)&.first
klass.const_source_location(klass.name)
rescue
nil
[]
end
end
end
Expand Down
17 changes: 15 additions & 2 deletions lib/datadog/ci/contrib/minitest/runnable.rb
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,21 @@ def run(*args)
return super if method.nil?

test_suite_name = Helpers.test_suite_name(self, method)

test_suite = test_visibility_component.start_test_suite(test_suite_name)
source_file, line_number = Helpers.extract_source_location_from_class(self)

test_suite_tags = if source_file
{
CI::Ext::Test::TAG_SOURCE_FILE => (Git::LocalRepository.relative_to_root(source_file) if source_file),
CI::Ext::Test::TAG_SOURCE_START => line_number&.to_s
}
else
{}
end

test_suite = test_visibility_component.start_test_suite(
test_suite_name,
tags: test_suite_tags
)

results = super
return results unless test_suite
Expand Down
8 changes: 7 additions & 1 deletion lib/datadog/ci/contrib/rspec/example_group.rb
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,13 @@ def run(reporter = ::RSpec::Core::NullReporter)
return super unless top_level?

suite_name = "#{description} at #{file_path}"
test_suite = test_visibility_component.start_test_suite(suite_name)
test_suite = test_visibility_component.start_test_suite(
suite_name,
tags: {
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
}
)

success = super
return success unless test_suite
Expand Down
7 changes: 7 additions & 0 deletions lib/datadog/ci/span.rb
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,13 @@ def runtime_version
tracer_span.get_tag(Ext::Test::TAG_RUNTIME_VERSION)
end

# Source file path where the test or test suite defined (relative to git repository root).
# @return [String] the source file path of the test
# @return [nil] if the source file path is not found
def source_file
get_tag(Ext::Test::TAG_SOURCE_FILE)
end

def set_environment_runtime_tags
tracer_span.set_tag(Ext::Test::TAG_OS_ARCHITECTURE, ::RbConfig::CONFIG["host_cpu"])
tracer_span.set_tag(Ext::Test::TAG_OS_PLATFORM, ::RbConfig::CONFIG["host_os"])
Expand Down
7 changes: 0 additions & 7 deletions lib/datadog/ci/test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -57,13 +57,6 @@ def test_session_id
get_tag(Ext::Test::TAG_TEST_SESSION_ID)
end

# Source file path of the test relative to git repository root.
# @return [String] the source file path of the test
# @return [nil] if the source file path is not found
def source_file
get_tag(Ext::Test::TAG_SOURCE_FILE)
end

# Returns "true" if the test is skipped by the intelligent test runner.
# @return [Boolean] true if the test is skipped by the intelligent test runner, false otherwise.
def skipped_by_itr?
Expand Down
8 changes: 5 additions & 3 deletions lib/datadog/ci/test_visibility/component.rb
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,8 @@ def on_test_module_started(test_module)
end

def on_test_suite_started(test_suite)
set_codeowners(test_suite)

Telemetry.event_created(test_suite)
end

Expand Down Expand Up @@ -223,10 +225,10 @@ def subscribe_to_after_stop_event(tracer_span)
end
end

def set_codeowners(test)
source = test.source_file
def set_codeowners(span)
source = span.source_file
owners = @codeowners.list_owners(source) if source
test.set_tag(Ext::Test::TAG_CODEOWNERS, owners) unless owners.nil?
span.set_tag(Ext::Test::TAG_CODEOWNERS, owners) unless owners.nil?
end

def fix_test_suite!(test)
Expand Down
4 changes: 3 additions & 1 deletion sig/datadog/ci/contrib/cucumber/formatter.rbs
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ module Datadog

def test_suite_name: (untyped test_case) -> String

def start_test_suite: (String test_suite_name) -> void
def start_test_suite: (String test_suite_name, ?tags: Hash[String, String]) -> void

def finish_current_test_suite: () -> void

Expand All @@ -52,6 +52,8 @@ module Datadog
def configuration: () -> untyped

def test_visibility_component: () -> Datadog::CI::TestVisibility::Component

def test_suite_source_file_tags: (untyped test_case) -> Hash[String, String]
end
end
end
Expand Down
2 changes: 1 addition & 1 deletion sig/datadog/ci/contrib/minitest/helpers.rbs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ module Datadog

def self.parallel?: (untyped klass) -> bool

def self.extract_source_location_from_class: (untyped klass) -> String?
def self.extract_source_location_from_class: (untyped klass) -> Array[::String]
end
end
end
Expand Down
2 changes: 2 additions & 0 deletions sig/datadog/ci/span.rbs
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,8 @@ module Datadog

def runtime_version: () -> String?

def source_file: () -> String?

private

def test_visibility: () -> Datadog::CI::TestVisibility::Component
Expand Down
1 change: 0 additions & 1 deletion sig/datadog/ci/test.rbs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ module Datadog
def test_session_id: () -> String?
def skipped_by_itr?: () -> bool
def itr_unskippable!: () -> void
def source_file: () -> String?
def parameters: () -> String?
def is_retry?: () -> bool
def any_retry_passed?: () -> bool
Expand Down
2 changes: 1 addition & 1 deletion sig/datadog/ci/test_visibility/component.rbs
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ module Datadog

def fix_test_suite!: (Datadog::CI::Test test) -> void

def set_codeowners: (Datadog::CI::Test test) -> void
def set_codeowners: (Datadog::CI::Span span) -> void

def null_span: () -> Datadog::CI::Span

Expand Down
12 changes: 12 additions & 0 deletions spec/datadog/ci/contrib/cucumber/instrumentation_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,18 @@
:framework_version,
Datadog::CI::Contrib::Cucumber::Integration.version.to_s
)

expect(first_test_suite_span).to have_test_tag(
:source_file,
"passing.feature"
)
expect(first_test_suite_span).to have_test_tag(:source_start, "1")

expect(first_test_suite_span).to have_test_tag(
:codeowners,
"[\"@test-owner\"]"
)

expect(first_test_suite_span).to have_pass_status
end

Expand Down
11 changes: 11 additions & 0 deletions spec/datadog/ci/contrib/minitest/instrumentation_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -475,6 +475,17 @@ def test_pass_other
:framework_version,
Datadog::CI::Contrib::Minitest::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(
:codeowners,
"[\"@DataDog/ruby-guild\", \"@DataDog/ci-app-libraries\"]"
)

expect(first_test_suite_span).to have_pass_status
end

Expand Down
13 changes: 12 additions & 1 deletion spec/datadog/ci/contrib/rspec/instrumentation_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -506,7 +506,7 @@ def expect_failure

context "with git root changed" do
before do
expect(Datadog::CI::Git::LocalRepository).to receive(:root).and_return("#{Dir.pwd}/spec")
allow(Datadog::CI::Git::LocalRepository).to receive(:root).and_return("#{Dir.pwd}/spec")
end

it "provides source file path relative to git root" do
Expand Down Expand Up @@ -588,6 +588,17 @@ def expect_failure
:framework_version,
Datadog::CI::Contrib::RSpec::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, "57")
expect(first_test_suite_span).to have_test_tag(
:codeowners,
"[\"@DataDog/ruby-guild\", \"@DataDog/ci-app-libraries\"]"
)

expect(first_test_suite_span).to have_pass_status
end

Expand Down
1 change: 1 addition & 0 deletions vendor/rbs/rspec/0/rspec.rbs
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ module RSpec::Core::ExampleGroup
def top_level?: () -> bool
def file_path: () -> String
def description: () -> String
def metadata: () -> untyped
end
end

Expand Down

0 comments on commit 17b2e4f

Please sign in to comment.