Files
ProStock/tests/test_performance_profiler.py

194 lines
5.9 KiB
Python
Raw Normal View History

"""性能分析器测试"""
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