"""性能分析器测试""" import pytest import time from src.factors.engine.performance_profiler import PerformanceProfiler, ProfileRecord class TestProfileRecord: """测试 ProfileRecord 数据类""" def test_profile_record_creation(self): """测试创建 ProfileRecord""" record = ProfileRecord(time_ms=1.5) assert record.time_ms == 1.5 class TestPerformanceProfiler: """测试 PerformanceProfiler 类""" def test_profiler_disabled_by_default(self): """测试默认情况下禁用""" profiler = PerformanceProfiler() assert profiler.enabled is False def test_profiler_enabled(self): """测试启用性能分析器""" profiler = PerformanceProfiler(enabled=True) assert profiler.enabled is True def test_measure_context_manager_disabled(self): """测试禁用时 measure 上下文管理器""" profiler = PerformanceProfiler(enabled=False) with profiler.measure("test_task"): time.sleep(0.001) # 禁用时不会记录数据 assert len(profiler.records) == 0 def test_measure_context_manager_enabled(self): """测试启用时 measure 上下文管理器""" profiler = PerformanceProfiler(enabled=True) with profiler.measure("test_task"): time.sleep(0.01) # 10ms assert "test_task" in profiler.records assert profiler.records["test_task"].time_ms >= 0.01 def test_measure_multiple_calls_accumulate(self): """测试多次调用同名任务会累加时间""" profiler = PerformanceProfiler(enabled=True) # 第一次调用 with profiler.measure("task"): time.sleep(0.01) first_time = profiler.records["task"].time_ms # 第二次调用 with profiler.measure("task"): time.sleep(0.01) # 时间应该累加 assert profiler.records["task"].time_ms > first_time def test_measure_exception_handling(self): """测试异常发生时计时器正常闭合""" profiler = PerformanceProfiler(enabled=True) try: with profiler.measure("failing_task"): time.sleep(0.01) raise ValueError("Test error") except ValueError: pass # 异常发生时仍然记录了时间 assert "failing_task" in profiler.records assert profiler.records["failing_task"].time_ms >= 0.01 def test_get_report_empty(self): """测试空记录时的报告""" profiler = PerformanceProfiler(enabled=True) report = profiler.get_report() assert report == {} def test_get_report_with_data(self): """测试有数据时的报告""" profiler = PerformanceProfiler(enabled=True) with profiler.measure("task1"): time.sleep(0.02) with profiler.measure("task2"): time.sleep(0.01) report = profiler.get_report() assert report["enabled"] is True assert report["factor_count"] == 2 assert report["total_time_ms"] > 0 assert report["avg_time_ms"] > 0 assert len(report["slowest_factors"]) <= 2 assert "all_records" in report def test_get_report_sorts_by_time(self): """测试报告按时间排序""" profiler = PerformanceProfiler(enabled=True) # task1 耗时更长 with profiler.measure("task1"): time.sleep(0.02) with profiler.measure("task2"): time.sleep(0.01) report = profiler.get_report() slowest = report["slowest_factors"] assert slowest[0][0] == "task1" # 最慢的应该是 task1 def test_reset_clears_data(self): """测试重置清除数据""" profiler = PerformanceProfiler(enabled=True) with profiler.measure("task"): time.sleep(0.01) assert len(profiler.records) == 1 profiler.reset() assert len(profiler.records) == 0 assert len(profiler._context_stack) == 0 def test_print_report_disabled(self): """测试禁用时打印报告""" profiler = PerformanceProfiler(enabled=False) # 应该正常执行不报错 profiler.print_report() def test_print_report_empty(self, capsys): """测试空数据时打印报告""" profiler = PerformanceProfiler(enabled=True) profiler.print_report() captured = capsys.readouterr() assert "无性能数据" in captured.out def test_print_report_with_data(self, capsys): """测试有数据时打印报告""" profiler = PerformanceProfiler(enabled=True) with profiler.measure("slow_task"): time.sleep(0.02) with profiler.measure("fast_task"): time.sleep(0.01) profiler.print_report() captured = capsys.readouterr() assert "Factor Engine 性能报告" in captured.out assert "slow_task" in captured.out assert "fast_task" in captured.out def test_get_factor_time(self): """测试获取单个因子的计算时间""" profiler = PerformanceProfiler(enabled=True) with profiler.measure("task"): time.sleep(0.01) time_val = profiler.get_factor_time("task") assert time_val is not None assert time_val >= 0.01 # 不存在的因子返回 None assert profiler.get_factor_time("nonexistent") is None def test_nested_measure(self): """测试嵌套计时""" profiler = PerformanceProfiler(enabled=True) with profiler.measure("outer"): time.sleep(0.01) with profiler.measure("inner"): time.sleep(0.01) assert "outer" in profiler.records assert "inner" in profiler.records # 嵌套计时应该分别记录 assert profiler.records["outer"].time_ms >= 0.01 assert profiler.records["inner"].time_ms >= 0.01