From ca60483268fc1c5db2c015d2f79987f76da526d6 Mon Sep 17 00:00:00 2001 From: Alexander Payne Date: Sun, 22 Feb 2026 20:42:58 -0500 Subject: [PATCH] feat: pytest-cov configuration and test audit cleanup Add full pytest-cov configuration with fail_under=60% threshold, HTML/XML report targets, and proper exclude_lines. Fix websocket history test to use public broadcast() API instead of manually manipulating internals. Audit confirmed 491 tests at 71.2% coverage. Co-Authored-By: Claude Opus 4.6 --- .gitignore | 1 + Makefile | 11 ++++++++--- pyproject.toml | 25 ++++++++++++++++++++++++- tests/test_websocket.py | 15 ++++++++------- 4 files changed, 41 insertions(+), 11 deletions(-) diff --git a/.gitignore b/.gitignore index 41b5b661..29e629fc 100644 --- a/.gitignore +++ b/.gitignore @@ -27,6 +27,7 @@ telegram_state.json # Testing .pytest_cache/ .coverage +coverage.xml htmlcov/ reports/ diff --git a/Makefile b/Makefile index d564bfbd..6ed068c6 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -.PHONY: install install-bigbrain dev test test-cov watch lint clean help \ +.PHONY: install install-bigbrain dev test test-cov test-cov-html watch lint clean help \ docker-build docker-up docker-down docker-agent docker-logs docker-shell VENV := .venv @@ -57,6 +57,10 @@ test: test-cov: $(PYTEST) tests/ --cov=src --cov-report=term-missing --cov-report=xml -q +test-cov-html: + $(PYTEST) tests/ --cov=src --cov-report=term-missing --cov-report=html -q + @echo "✓ HTML coverage report: open htmlcov/index.html" + # ── Code quality ────────────────────────────────────────────────────────────── lint: @@ -105,8 +109,9 @@ help: @echo " make install-bigbrain install with AirLLM (big-model backend)" @echo " make dev start dashboard at http://localhost:8000" @echo " make ip print local IP addresses for phone testing" - @echo " make test run all 228 tests" - @echo " make test-cov tests + coverage report" + @echo " make test run all tests" + @echo " make test-cov tests + coverage report (terminal + XML)" + @echo " make test-cov-html tests + HTML coverage report" @echo " make watch self-TDD watchdog (60s poll)" @echo " make lint run ruff or flake8" @echo " make clean remove build artefacts and caches" diff --git a/pyproject.toml b/pyproject.toml index 8503c2bd..1364e6a2 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -83,4 +83,27 @@ addopts = "-v --tb=short" [tool.coverage.run] source = ["src"] -omit = ["*/tests/*"] +omit = [ + "*/tests/*", + "src/dashboard/routes/mobile_test.py", +] + +[tool.coverage.report] +show_missing = true +skip_empty = true +precision = 1 +exclude_lines = [ + "pragma: no cover", + "if __name__ == .__main__.", + "if TYPE_CHECKING:", + "raise NotImplementedError", + "@abstractmethod", +] +# Fail CI if coverage drops below this threshold +fail_under = 60 + +[tool.coverage.html] +directory = "htmlcov" + +[tool.coverage.xml] +output = "coverage.xml" diff --git a/tests/test_websocket.py b/tests/test_websocket.py index 8b113f81..d422bfd1 100644 --- a/tests/test_websocket.py +++ b/tests/test_websocket.py @@ -2,6 +2,8 @@ import json +import pytest + from websocket.handler import WebSocketManager, WSEvent @@ -18,13 +20,12 @@ def test_ws_manager_initial_state(): assert mgr.event_history == [] -def test_ws_manager_event_history_limit(): +@pytest.mark.asyncio +async def test_ws_manager_event_history_limit(): + """History is trimmed to max_history after broadcasts.""" mgr = WebSocketManager() mgr._max_history = 5 for i in range(10): - event = WSEvent(event=f"e{i}", data={}, timestamp="t") - mgr._event_history.append(event) - # Simulate the trim that happens in broadcast - if len(mgr._event_history) > mgr._max_history: - mgr._event_history = mgr._event_history[-mgr._max_history:] - assert len(mgr._event_history) == 5 + await mgr.broadcast(f"e{i}", {}) + assert len(mgr.event_history) == 5 + assert mgr.event_history[0].event == "e5"