Files
interactive-story/backend/tests/conftest.py
parththakkar106andClaude Opus 5 32cd7c1077 Give the tests one setup instead of thirty-five
Every test module carried the same eight-line prologue redirecting the
database to a temp file. Only the first one to be imported ever took
effect: `app.database` reads `AIDND_DB_PATH` at import and builds `engine`
from it once, so by the time the second module ran the engine already
existed. The other 34 copies created a temp file that nothing opened and
nothing deleted, and leaked one per module per run.

`conftest.py` now does it once, which is early enough because pytest
imports conftest before any test module. It also deletes the file when the
run ends. The tests still share one database, exactly as they already did:
each `client` fixture calls `create_all` on setup and `drop_all` on
teardown, so no test sees another test's rows.

`tests/fakes.py` holds the one `ScriptedProvider`. Nine modules each had a
copy, and the copies had drifted into four feature sets, so a test that
needed to raise a provider error had to be written in one of the files
whose copy supported that. The shared one is the superset. The two
`FakeProvider` copies were the same class with a fixed reply, so they use
it too. `test_chat.py` keeps its own, which implements `chat` rather than
`generate` and records what it was constructed with.

An autouse fixture resets the fake's class state between tests, so a stale
reply list can no longer reach the next test.

435 lines out of the suite. 549 tests pass. Verified live by sabotage:
breaking the shared fake fails 13 tests across four modules.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014Dix4oGV3njgWRdu7P9t6r
2026-08-29 00:47:46 +05:30

58 lines
2.2 KiB
Python

"""Shared setup for the test suite.
pytest imports this file before it imports any test module, which is the only
reason the database redirection below works. `app.database` reads
`AIDND_DB_PATH` at import and builds `engine` from it once, so the variable has
to be set before the first `from app...` line anywhere in the suite.
Every test module used to carry its own copy of that redirection. Only the first
one to be imported ever took effect, because the engine already existed by the
time the second one ran. The other copies created a temp file that nothing
opened and nothing deleted. One copy here does the job, and it cleans up after
itself.
The tests share one database. That is not new: they already did. Each `client`
fixture calls `Base.metadata.create_all` on setup and `drop_all` on teardown, so
no test sees another test's rows.
"""
import os
import tempfile
_tmp = tempfile.NamedTemporaryFile(suffix=".db", delete=False)
_tmp.close()
os.environ["AIDND_DB_PATH"] = _tmp.name
# A real `AIDND_DATABASE_URL` or `DATABASE_URL` in the developer's shell points
# at Postgres, and `app.database` prefers either over the SQLite path above.
# Clear both, so running the suite never touches a server database.
os.environ.pop("AIDND_DATABASE_URL", None)
os.environ.pop("DATABASE_URL", None)
import pytest # noqa: E402 Import order is load-bearing; see above.
from fakes import ScriptedProvider # noqa: E402
@pytest.fixture(autouse=True)
def reset_scripted_provider():
"""Clears the fake provider's state between tests.
`ScriptedProvider` keeps its replies and its call count on the class, because
the code under test constructs the provider itself and a test cannot reach
the instance. Class state outlives a test, so reset it here rather than
trusting every fixture to remember.
"""
ScriptedProvider.replies = []
ScriptedProvider.calls = 0
ScriptedProvider.prompts = []
yield
def pytest_sessionfinish(session, exitstatus):
"""Deletes the temporary database once the run ends."""
try:
os.unlink(_tmp.name)
except OSError:
# The file is already gone, or Windows still holds a handle on it. It is
# in the temp directory either way, so leaving it costs nothing.
pass