Skip to content

Commit db4affb

Browse files
authored
fix: show config errors once at session start instead of per-test (#55)
* docs: update pre-commit section with args example, fix stale v1.3.0 refs - pre-commit section: add args example for Alembic and Django, note on pre-commit autoupdate, update rev from v1.3.0 to v1.2.0 - Remove (v1.3.0) version labels from section headers for unreleased features - Update 'What's new' section to reflect v1.2.0 accurately Closes #35 * fix: improve mrt init UX — fix db_url quoting bug, clearer prompts and next steps Three issues fixed: 1. db_url quoting bug: when a user typed a literal URL (e.g. sqlite:///test.db), it was written as db_url=sqlite:///test.db without quotes — invalid Python. Now correctly written as db_url="sqlite:///test.db". 2. Confusing default prompt: the old default was the raw Python expression os.environ.get("TEST_DATABASE_URL", "sqlite:///test.db") which is unclear for first-time users. Default is now simply sqlite:///test.db with a tip explaining the env var pattern for CI. 3. Weak next steps: the completion message now shows numbered steps, static analysis command, and a docs link — so users know exactly what to do next. Also removes unnecessary 'import os' from generated conftest when a literal URL is used (os is only imported when the url expr references os.environ). * fix: show config errors once at session start instead of per-test Before this change, a missing alembic.ini produced the same error message for every collected test (typically 7 times), each with a double traceback due to pytest.fail() being called inside an except block. Changes: - Add pytest_sessionstart hook that validates MRTConfig once and calls pytest.exit() on fatal config errors -- one clear message, no tests run - Break exception chain in mrt fixture (capture error string before calling pytest.fail) to eliminate "During handling of the above exception" noise - Simplify MRTConfigError message in MRTFixture.__init__: Django hint is now only shown via pytest_sessionstart, not duplicated - Update test assertion to match revised error message text
1 parent 30fc010 commit db4affb

2 files changed

Lines changed: 45 additions & 10 deletions

File tree

pytest_mrt/plugin.py

Lines changed: 43 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -83,13 +83,9 @@ def __init__(self, config: MRTConfig):
8383

8484
if not _Path(config.alembic_ini).exists():
8585
raise MRTConfigError(
86-
f"\n\n alembic.ini not found: '{config.alembic_ini}'\n\n"
87-
" If you are using Django migrations (not Alembic), use:\n\n"
88-
" config._mrt_config = MRTConfig(\n"
89-
" db_url=os.environ['TEST_DATABASE_URL'],\n"
90-
" django_settings='myproject.settings_test',\n"
91-
" )\n\n"
92-
" See: https://croc100.github.io/pytest-mrt/quickstart/#django"
86+
f"alembic.ini not found: '{config.alembic_ini}'\n\n"
87+
"Check the path and update MRTConfig(alembic_ini=...) in your conftest.py.\n"
88+
"See: https://croc100.github.io/pytest-mrt/quickstart/"
9389
)
9490

9591
self._runner = MigrationRunner(config.alembic_ini, config.db_url)
@@ -301,6 +297,39 @@ def pytest_configure(config: pytest.Config) -> None:
301297
config.addinivalue_line("markers", "mrt: migration rollback test")
302298

303299

300+
def pytest_sessionstart(session: pytest.Session) -> None:
301+
"""Validate MRTConfig once at session start.
302+
303+
Catches obvious setup errors (missing alembic.ini, etc.) before any test
304+
runs, so the user sees one clear error instead of the same message repeated
305+
for every collected test.
306+
"""
307+
cfg: MRTConfig | None = getattr(session.config, "_mrt_config", None)
308+
if cfg is None:
309+
return
310+
311+
cfg = _auto_detect_django(cfg)
312+
313+
# Django mode — no alembic.ini needed
314+
if cfg.django_settings is not None:
315+
return
316+
317+
from pathlib import Path
318+
319+
if not Path(cfg.alembic_ini).exists():
320+
msg = (
321+
f"alembic.ini not found: '{cfg.alembic_ini}'\n\n"
322+
"Check the path and update MRTConfig(alembic_ini=...) in your conftest.py.\n\n"
323+
"If you are using Django migrations (not Alembic), set django_settings instead:\n\n"
324+
" config._mrt_config = MRTConfig(\n"
325+
" db_url=os.environ['TEST_DATABASE_URL'],\n"
326+
" django_settings='myproject.settings_test',\n"
327+
" )\n\n"
328+
"See: https://croc100.github.io/pytest-mrt/quickstart/"
329+
)
330+
pytest.exit(msg, returncode=4)
331+
332+
304333
def pytest_collection_modifyitems(
305334
session: pytest.Session,
306335
config: pytest.Config,
@@ -336,9 +365,15 @@ def pytest_collection_modifyitems(
336365
@pytest.fixture
337366
def mrt(request: pytest.FixtureRequest) -> Iterator[MRTFixture]:
338367
cfg: MRTConfig = getattr(request.config, "_mrt_config", None) or MRTConfig()
368+
# Capture error outside the except block to avoid "During handling of the
369+
# above exception, another exception occurred" in the traceback output.
370+
config_error: str | None = None
339371
try:
340372
fixture = MRTFixture(cfg)
341373
except MRTConfigError as e:
342-
pytest.fail(str(e), pytrace=False)
374+
config_error = str(e)
375+
if config_error is not None:
376+
pytest.fail(config_error, pytrace=False)
377+
return # unreachable; keeps type checkers happy
343378
yield fixture
344379
fixture.reset()

tests/test_plugin.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -665,13 +665,13 @@ def test_auto_detect_django_no_switch_when_explicit_django_settings(tmp_path, mo
665665

666666

667667
def test_mrt_fixture_raises_on_missing_alembic_ini(tmp_path, monkeypatch):
668-
"""MRTFixture raises MRTConfigError with a Django hint when alembic.ini is missing."""
668+
"""MRTFixture raises MRTConfigError when alembic.ini is missing."""
669669
from pytest_mrt.exceptions import MRTConfigError
670670

671671
monkeypatch.delenv("DJANGO_SETTINGS_MODULE", raising=False)
672672

673673
cfg = MRTConfig(alembic_ini=str(tmp_path / "nonexistent.ini"), db_url="sqlite:///test.db")
674-
with pytest.raises(MRTConfigError, match="django_settings"):
674+
with pytest.raises(MRTConfigError, match="alembic.ini not found"):
675675
MRTFixture(cfg)
676676

677677

0 commit comments

Comments
 (0)