79 lines
3.0 KiB
Python
79 lines
3.0 KiB
Python
"""
|
|
ANTI-SIMPLIFICATION: These tests verify that the GUI maintains a strict performance baseline.
|
|
They MUST NOT be simplified. Removing assertions or adding arbitrary skips when metrics fail to collect defeats the purpose of the test.
|
|
If the GUI cannot sustain 30 FPS, it indicates a critical performance regression in the render loop.
|
|
"""
|
|
import pytest
|
|
import time
|
|
import sys
|
|
import os
|
|
|
|
# Ensure project root is in path
|
|
sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), "..")))
|
|
sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), "..", "src")))
|
|
|
|
from src.api_hook_client import ApiHookClient
|
|
|
|
# Session-wide storage for comparing metrics
|
|
_shared_metrics = {}
|
|
|
|
def test_performance_benchmarking(live_gui: tuple) -> None:
|
|
"""
|
|
Collects performance metrics for the current GUI script over a 5-second window.
|
|
Ensures the application does not lock up and can report its internal state.
|
|
"""
|
|
process, gui_script = live_gui
|
|
client = ApiHookClient()
|
|
# Wait for app to stabilize and render some frames
|
|
time.sleep(3.0)
|
|
# Collect metrics over 5 seconds
|
|
fps_values = []
|
|
cpu_values = []
|
|
frame_time_values = []
|
|
start_time = time.time()
|
|
while time.time() - start_time < 5:
|
|
try:
|
|
perf_data = client.get_performance()
|
|
metrics = perf_data.get('performance', {})
|
|
if metrics:
|
|
fps = metrics.get('fps', 0.0)
|
|
cpu = metrics.get('cpu_percent', 0.0)
|
|
ft = metrics.get('last_frame_time_ms', 0.0)
|
|
if fps > 0:
|
|
fps_values.append(fps)
|
|
cpu_values.append(cpu)
|
|
frame_time_values.append(ft)
|
|
time.sleep(0.1)
|
|
except Exception:
|
|
break
|
|
avg_fps = sum(fps_values) / len(fps_values) if fps_values else 0
|
|
avg_cpu = sum(cpu_values) / len(cpu_values) if cpu_values else 0
|
|
avg_ft = sum(frame_time_values) / len(frame_time_values) if frame_time_values else 0
|
|
_shared_metrics[gui_script] = {
|
|
"avg_fps": avg_fps,
|
|
"avg_cpu": avg_cpu,
|
|
"avg_ft": avg_ft
|
|
}
|
|
print(f"\n[Test] Results for {gui_script}: FPS={avg_fps:.2f}, CPU={avg_cpu:.2f}%, FT={avg_ft:.2f}ms")
|
|
# Absolute minimum requirements
|
|
if avg_fps > 0:
|
|
# ANTI-SIMPLIFICATION: 30 FPS threshold ensures the app remains interactive.
|
|
assert avg_fps >= 30, f"{gui_script} FPS {avg_fps:.2f} is below 30 FPS threshold"
|
|
assert avg_ft <= 33.3, f"{gui_script} Frame time {avg_ft:.2f}ms is above 33.3ms threshold"
|
|
|
|
def test_performance_baseline_check() -> None:
|
|
"""
|
|
Verifies that we have successfully collected performance metrics for sloppy.py
|
|
and that they meet the minimum 30 FPS baseline.
|
|
"""
|
|
# Key is full path, find it by basename
|
|
gui_key = next((k for k in _shared_metrics if "sloppy.py" in k), None)
|
|
if not gui_key:
|
|
pytest.skip("Metrics for sloppy.py not yet collected.")
|
|
gui2_m = _shared_metrics[gui_key]
|
|
# ANTI-SIMPLIFICATION: If avg_fps is 0, the test MUST fail, not skip.
|
|
# A 0 FPS indicates the render loop is completely frozen or the API hook is dead.
|
|
assert gui2_m["avg_fps"] > 0, "No performance metrics collected - GUI may be frozen"
|
|
assert gui2_m["avg_fps"] >= 30
|
|
assert gui2_m["avg_ft"] <= 33.3
|