From dc1131b6df4f1fc5bdf3c656fd064b11b923145e Mon Sep 17 00:00:00 2001 From: melooooooo <35089726+melooooooo@users.noreply.github.com> Date: Thu, 9 Jul 2026 16:33:28 +0800 Subject: [PATCH] refactor(tests): replace logger mocks with caplog in trace provider tests (#38569) Co-authored-by: Cursor --- .../aliyun_trace/test_aliyun_trace.py | 11 ++-- .../unit_tests/tencent_trace/test_client.py | 57 ++++++++++--------- 2 files changed, 37 insertions(+), 31 deletions(-) diff --git a/api/providers/trace/trace-aliyun/tests/unit_tests/aliyun_trace/test_aliyun_trace.py b/api/providers/trace/trace-aliyun/tests/unit_tests/aliyun_trace/test_aliyun_trace.py index fa00829653a..06bdb61b4d1 100644 --- a/api/providers/trace/trace-aliyun/tests/unit_tests/aliyun_trace/test_aliyun_trace.py +++ b/api/providers/trace/trace-aliyun/tests/unit_tests/aliyun_trace/test_aliyun_trace.py @@ -1,5 +1,6 @@ from __future__ import annotations +import logging from datetime import UTC, datetime from types import SimpleNamespace from typing import cast @@ -259,14 +260,16 @@ def test_get_project_url_success(trace_instance: AliyunDataTrace): assert trace_instance.get_project_url() == "project-url" -def test_get_project_url_error(trace_instance: AliyunDataTrace, monkeypatch: pytest.MonkeyPatch): +def test_get_project_url_error( + trace_instance: AliyunDataTrace, monkeypatch: pytest.MonkeyPatch, caplog: pytest.LogCaptureFixture +): monkeypatch.setattr(trace_instance.trace_client, "get_project_url", MagicMock(side_effect=Exception("boom"))) - logger_mock = MagicMock() - monkeypatch.setattr(aliyun_trace_module, "logger", logger_mock) + caplog.set_level(logging.INFO, logger=aliyun_trace_module.logger.name) with pytest.raises(ValueError, match=r"Aliyun get project url failed: boom"): trace_instance.get_project_url() - logger_mock.info.assert_called() + + assert "Aliyun get project url failed: boom" in caplog.text def test_workflow_trace_adds_workflow_and_node_spans(trace_instance: AliyunDataTrace, monkeypatch: pytest.MonkeyPatch): diff --git a/api/providers/trace/trace-tencent/tests/unit_tests/tencent_trace/test_client.py b/api/providers/trace/trace-tencent/tests/unit_tests/tencent_trace/test_client.py index b6bc5b86060..98f829d1b7d 100644 --- a/api/providers/trace/trace-tencent/tests/unit_tests/tencent_trace/test_client.py +++ b/api/providers/trace/trace-tencent/tests/unit_tests/tencent_trace/test_client.py @@ -2,6 +2,7 @@ from __future__ import annotations +import logging import sys import types from types import SimpleNamespace @@ -87,7 +88,6 @@ class PatchedCoreComponents(TypedDict): tracer: MagicMock span: MagicMock tracer_provider: MagicMock - logger: MagicMock trace_api: Any @@ -148,9 +148,6 @@ def patch_core_components(monkeypatch: pytest.MonkeyPatch) -> PatchedCoreCompone resource = MagicMock(name="resource") monkeypatch.setattr(client_module, "Resource", MagicMock(return_value=resource)) - logger_mock = MagicMock(name="tencent_logger") - monkeypatch.setattr(client_module, "logger", logger_mock) - trace_api_stub = SimpleNamespace( set_span_in_context=MagicMock(name="set_span_in_context", return_value="trace-context"), NonRecordingSpan=MagicMock(name="non_recording_span", side_effect=lambda ctx: f"non-{ctx}"), @@ -174,7 +171,6 @@ def patch_core_components(monkeypatch: pytest.MonkeyPatch) -> PatchedCoreCompone "tracer": tracer, "span": span, "tracer_provider": tracer_provider, - "logger": logger_mock, "trace_api": trace_api_stub, } @@ -268,14 +264,15 @@ def test_record_methods_skip_when_histogram_missing() -> None: client.record_trace_duration(0.5) -def test_record_llm_duration_handles_exceptions(patch_core_components: PatchedCoreComponents) -> None: +def test_record_llm_duration_handles_exceptions(caplog: pytest.LogCaptureFixture) -> None: client = _build_client() client.hist_llm_duration = MagicMock(name="hist_llm_duration") client.hist_llm_duration.record.side_effect = RuntimeError("boom") + caplog.set_level(logging.DEBUG, logger=client_module.logger.name) client.record_llm_duration(0.2) - logger = patch_core_components["logger"] - logger.debug.assert_called() + + assert "[Tencent APM] Failed to record LLM duration" in caplog.text def test_create_and_export_span_sets_attributes(patch_core_components: PatchedCoreComponents) -> None: @@ -328,12 +325,15 @@ def test_create_and_export_span_uses_parent_context(patch_core_components: Patch trace_api.set_span_in_context.assert_called_once() -def test_create_and_export_span_exception_logs_error(patch_core_components: PatchedCoreComponents) -> None: +def test_create_and_export_span_exception_logs_error( + patch_core_components: PatchedCoreComponents, caplog: pytest.LogCaptureFixture +) -> None: client = _build_client() span = patch_core_components["span"] span.get_span_context.return_value = _make_span_context(span_id=2) client.tracer.start_span.side_effect = RuntimeError("boom") + caplog.set_level(logging.DEBUG, logger=client_module.logger.name) client._create_and_export_span( SpanData( trace_id=1, @@ -346,8 +346,10 @@ def test_create_and_export_span_exception_logs_error(patch_core_components: Patc end_time=1, ) ) - logger = patch_core_components["logger"] - logger.exception.assert_called_once() + + error_records = [record for record in caplog.records if record.levelno == logging.ERROR] + assert len(error_records) == 1 + assert error_records[0].getMessage() == "[Tencent APM] Error creating span: span" def test_api_check_connects_successfully(monkeypatch: pytest.MonkeyPatch) -> None: @@ -423,23 +425,18 @@ def test_shutdown_flushes_all_components(patch_core_components: PatchedCoreCompo metric_reader.shutdown.assert_called_once() -def test_shutdown_logs_when_meter_provider_fails(patch_core_components: PatchedCoreComponents) -> None: +def test_shutdown_logs_when_meter_provider_fails(caplog: pytest.LogCaptureFixture) -> None: client = _build_client() meter_provider = meter_provider_instances[-1] meter_provider.shutdown.side_effect = RuntimeError("boom") assert client.metric_reader is not None client.metric_reader.shutdown.side_effect = RuntimeError("boom") + caplog.set_level(logging.DEBUG, logger=client_module.logger.name) client.shutdown() - logger = patch_core_components["logger"] - logger.debug.assert_any_call( - "[Tencent APM] Error shutting down meter provider", - exc_info=True, - ) - logger.debug.assert_any_call( - "[Tencent APM] Error shutting down metric reader", - exc_info=True, - ) + + assert "[Tencent APM] Error shutting down meter provider" in caplog.text + assert "[Tencent APM] Error shutting down metric reader" in caplog.text def test_metrics_initialization_failure_sets_histogram_attributes(monkeypatch: pytest.MonkeyPatch) -> None: @@ -456,10 +453,11 @@ def test_metrics_initialization_failure_sets_histogram_attributes(monkeypatch: p assert client.metric_reader is None -def test_add_span_logs_exception(monkeypatch: pytest.MonkeyPatch, patch_core_components: PatchedCoreComponents) -> None: +def test_add_span_logs_exception(monkeypatch: pytest.MonkeyPatch, caplog: pytest.LogCaptureFixture) -> None: client = _build_client() monkeypatch.setattr(client, "_create_and_export_span", MagicMock(side_effect=RuntimeError("boom"))) + caplog.set_level(logging.DEBUG, logger=client_module.logger.name) client.add_span( SpanData( trace_id=1, @@ -473,8 +471,9 @@ def test_add_span_logs_exception(monkeypatch: pytest.MonkeyPatch, patch_core_com ) ) - logger = patch_core_components["logger"] - logger.exception.assert_called_once() + error_records = [record for record in caplog.records if record.levelno == logging.ERROR] + assert len(error_records) == 1 + assert error_records[0].getMessage() == "[Tencent APM] Failed to create span: span" def test_create_and_export_span_converts_attribute_types(patch_core_components: PatchedCoreComponents) -> None: @@ -535,16 +534,20 @@ def test_record_trace_duration_converts_attributes() -> None: ], ) def test_record_methods_handle_exceptions( - method: str, attr_name: str, args: tuple[object, ...], patch_core_components: PatchedCoreComponents + method: str, attr_name: str, args: tuple[object, ...], caplog: pytest.LogCaptureFixture ) -> None: client = _build_client() hist_mock = MagicMock(name=attr_name) hist_mock.record.side_effect = RuntimeError("boom") setattr(client, attr_name, hist_mock) + caplog.set_level(logging.DEBUG, logger=client_module.logger.name) getattr(client, method)(*args) - logger = patch_core_components["logger"] - logger.debug.assert_called() + + assert any( + record.levelno == logging.DEBUG and record.getMessage().startswith("[Tencent APM] Failed to record") + for record in caplog.records + ) def test_metrics_initializes_grpc_metric_exporter() -> None: