From 0f1eb844d1dfd8b9888145c507d0459de994fd1d Mon Sep 17 00:00:00 2001 From: Tony Redondo Date: Tue, 3 Nov 2026 16:10:53 +0100 Subject: [PATCH] fix(ci_visibility): add test.module to pytest test suite events Test suite events from the pytest plugin carry test_module_id but not the test.module and test.module_path tags that test and module events have. Datadog keys suite durations by the suite event's test.module, so every Python suite was stored under an empty module: ddtest, which looks durations up by module and suite, matched none, and suites with the same file name in different directories overwrote each other. serialize_suite now sets both tags from the suite's module, as serialize_test_run does. --- ddtrace/testing/internal/writer.py | 5 +++++ .../ci-visibility-suite-test-module-14f316ae5b509668.yaml | 5 +++++ tests/testing/internal/test_writer.py | 3 +++ 3 files changed, 13 insertions(+) create mode 100644 releasenotes/notes/ci-visibility-suite-test-module-14f316ae5b509668.yaml diff --git a/ddtrace/testing/internal/writer.py b/ddtrace/testing/internal/writer.py index 4b7d57a7b74..ff5b29c9fc9 100644 --- a/ddtrace/testing/internal/writer.py +++ b/ddtrace/testing/internal/writer.py @@ -616,6 +616,9 @@ def serialize_test_run(test_run: TestRun) -> Event: def serialize_suite(suite: TestSuite) -> Event: + # The plugin sets a module's path when it discovers the module; a module built without one still serializes. + module_path = getattr(suite.module, "module_path", None) + module_path_tag = {"test.module_path": module_path} if module_path is not None else {} content = { "service": suite.service, "resource": suite.name, @@ -625,6 +628,8 @@ def serialize_suite(suite: TestSuite) -> Event: "duration": suite.duration_ns, "meta": { "span.kind": "test", + "test.module": suite.module.name, + **module_path_tag, "test.suite": suite.name, "test.status": suite.get_status().value, "type": "test_suite_end", diff --git a/releasenotes/notes/ci-visibility-suite-test-module-14f316ae5b509668.yaml b/releasenotes/notes/ci-visibility-suite-test-module-14f316ae5b509668.yaml new file mode 100644 index 00000000000..48bf701b619 --- /dev/null +++ b/releasenotes/notes/ci-visibility-suite-test-module-14f316ae5b509668.yaml @@ -0,0 +1,5 @@ +--- +fixes: + - | + CI Visibility: Fixes test suite events from the ``pytest`` plugin missing the ``test.module`` and + ``test.module_path`` tags, which kept Datadog from recording test suite durations per module. diff --git a/tests/testing/internal/test_writer.py b/tests/testing/internal/test_writer.py index d488c010a9d..ea21f394314 100644 --- a/tests/testing/internal/test_writer.py +++ b/tests/testing/internal/test_writer.py @@ -908,6 +908,7 @@ def create_mock_test_suite(self) -> TestSuite: suite.name = "TestSuite" suite.session.item_id = 666 suite.module.item_id = 777 + suite.module.module_path = "/path/to/test_module" suite.item_id = 888 suite.tags = {"suite.custom": "suite_value"} suite.metrics = {"suite.metric": 100} @@ -932,6 +933,8 @@ def test_serialize_suite(self) -> None: # Check metadata meta = event["content"]["meta"] assert meta["span.kind"] == "test" + assert meta["test.module"] == "test_module" + assert meta["test.module_path"] == "/path/to/test_module" assert meta["test.suite"] == "TestSuite" assert meta["test.status"] == "pass" assert meta["type"] == "test_suite_end"