Skip to content

Commit a6cb74d

Browse files
authored
refactor: introduce MRTConfigError and decouple MRTFixture from pytest (#24)
* chore: bump version to 1.0.1 * refactor: introduce MRTConfigError and decouple MRTFixture from pytest - Add pytest_mrt/exceptions.py with MRTException base and MRTConfigError - MRTFixture.__init__ now raises MRTConfigError instead of calling pytest.fail() directly — core logic no longer depends on pytest - mrt fixture wrapper catches MRTConfigError and converts to pytest.fail() keeping clean test output while preserving layer separation * fix: sort imports in plugin.py to satisfy ruff
1 parent e061167 commit a6cb74d

3 files changed

Lines changed: 24 additions & 5 deletions

File tree

pytest_mrt/exceptions.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
"""
2+
Custom exceptions for pytest-mrt.
3+
4+
Core logic raises these; framework layers (pytest fixture, CLI) catch and
5+
convert them to framework-appropriate errors (pytest.fail, typer.Exit).
6+
"""
7+
8+
9+
class MRTException(Exception):
10+
"""Base exception for all MRT errors."""
11+
12+
13+
class MRTConfigError(MRTException):
14+
"""Configuration validation error (missing file, invalid path, etc.)."""

pytest_mrt/plugin.py

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
from .core.schema import SchemaSnapshot
1111
from .core.seeder import SmartSeeder
1212
from .core.verifier import RevisionResult, RollbackVerifier
13+
from .exceptions import MRTConfigError
1314

1415

1516
def _auto_detect_django(config: MRTConfig) -> MRTConfig:
@@ -80,7 +81,7 @@ def __init__(self, config: MRTConfig):
8081
from pathlib import Path as _Path
8182

8283
if not _Path(config.alembic_ini).exists():
83-
_hint = (
84+
raise MRTConfigError(
8485
f"\n\n alembic.ini not found: '{config.alembic_ini}'\n\n"
8586
" If you are using Django migrations (not Alembic), use:\n\n"
8687
" config._mrt_config = MRTConfig(\n"
@@ -89,7 +90,6 @@ def __init__(self, config: MRTConfig):
8990
" )\n\n"
9091
" See: https://croc100.github.io/pytest-mrt/quickstart/#django"
9192
)
92-
pytest.fail(_hint, pytrace=False)
9393

9494
self._runner = MigrationRunner(config.alembic_ini, config.db_url)
9595
self._seeder = SmartSeeder(self._runner.engine)
@@ -237,6 +237,9 @@ def pytest_configure(config: pytest.Config) -> None:
237237
@pytest.fixture
238238
def mrt(request: pytest.FixtureRequest) -> Iterator[MRTFixture]:
239239
cfg: MRTConfig = getattr(request.config, "_mrt_config", None) or MRTConfig()
240-
fixture = MRTFixture(cfg)
240+
try:
241+
fixture = MRTFixture(cfg)
242+
except MRTConfigError as e:
243+
pytest.fail(str(e), pytrace=False)
241244
yield fixture
242245
fixture.reset()

tests/test_plugin.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -614,11 +614,13 @@ def test_auto_detect_django_no_switch_when_explicit_django_settings(tmp_path, mo
614614
# ── MRTFixture missing alembic.ini ─────────────────────────────────────
615615

616616
def test_mrt_fixture_raises_on_missing_alembic_ini(tmp_path, monkeypatch):
617-
"""MRTFixture calls pytest.fail with a Django hint when alembic.ini is missing."""
617+
"""MRTFixture raises MRTConfigError with a Django hint when alembic.ini is missing."""
618+
from pytest_mrt.exceptions import MRTConfigError
619+
618620
monkeypatch.delenv("DJANGO_SETTINGS_MODULE", raising=False)
619621

620622
cfg = MRTConfig(alembic_ini=str(tmp_path / "nonexistent.ini"), db_url="sqlite:///test.db")
621-
with pytest.raises(pytest.fail.Exception, match="django_settings"):
623+
with pytest.raises(MRTConfigError, match="django_settings"):
622624
MRTFixture(cfg)
623625

624626

0 commit comments

Comments
 (0)