Files
feedBack/tests/conftest.py
T
byrongamatosandClaude Opus 4.8 9093230320 test: reset enrichment worker state between tests (CodeRabbit)
lib/enrichment.py now owns the worker, and it stays imported for the whole
session while the `server` fixtures pop-and-reimport `server` — so the cancel
Event / status dict / caches would leak across tests, and a stale `_enrich_cancel`
could short-circuit a later direct `_background_enrich()`. An autouse conftest
fixture clears that process-global state before each test.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-11 11:22:31 +02:00

76 lines
2.5 KiB
Python

"""Shared pytest fixtures for the feedBack test suite."""
import logging
import pytest
import structlog
_LOGGING_NAMES = ("feedBack", "uvicorn", "uvicorn.error", "uvicorn.access")
@pytest.fixture(autouse=True)
def _reset_enrichment_state():
"""Reset the enrichment worker's process-global state between tests.
The `server` fixtures pop-and-reimport `server`, but `lib/enrichment.py`
(which now owns the worker) stays imported for the whole session, so its
module globals — the cancel Event, the status dict, the caches — would
otherwise leak across tests. A test that set `_enrich_cancel` (or a stale
`running` status) could silently short-circuit a later direct
`_background_enrich()` call. Clear it up front so each test starts clean.
"""
try:
import enrichment
except Exception:
yield
return
enrichment._enrich_cancel.clear()
enrichment._enrich_pending_pass = False
enrichment._enrich_status.update(
{"running": False, "processed": 0, "last_pass_at": None,
"total": 0, "matched": 0, "current": None})
enrichment._enrich_last_fetch = 0.0
enrichment._artist_alias_cache.clear()
enrichment._caa_index_locks.clear()
yield
@pytest.fixture()
def isolate_logging():
"""Restore feedBack / uvicorn logger state after each test.
Saves handlers, level, and propagate flag before the test runs and
restores all three on teardown. Import into any test module that calls
configure_logging() so mutations don't bleed across tests.
"""
saved = {}
for name in _LOGGING_NAMES:
lg = logging.getLogger(name)
saved[name] = (
list(lg.handlers), # snapshot the handler list
lg.level,
lg.propagate,
)
yield
for name in _LOGGING_NAMES:
lg = logging.getLogger(name)
original_handlers, original_level, original_propagate = saved[name]
# Close and remove any handlers that were added during the test.
for h in list(lg.handlers):
if h not in original_handlers:
lg.removeHandler(h)
h.close()
# Remove any original handlers that may have been removed during the test
# so we can add them back cleanly.
for h in list(lg.handlers):
lg.removeHandler(h)
# Reattach the original handlers.
for h in original_handlers:
lg.addHandler(h)
lg.setLevel(original_level)
lg.propagate = original_propagate
structlog.reset_defaults()