Complete reference for all public classes, methods, and CLI commands.
from pytest_mrt import MRTConfigConfiguration object passed to pytest_configure to set up migration rollback testing.
| Parameter | Type | Default | Description |
|---|---|---|---|
alembic_ini |
str |
"alembic.ini" |
Path to your alembic.ini file |
db_url |
str |
"" |
SQLAlchemy database URL for the test database |
seed_rows |
int |
3 |
Number of rows to seed per table during rollback verification |
skip |
dict[str, str] |
{} |
Revisions to skip, with documented reasons |
severity_overrides |
dict[str, str] |
{} |
Override severity of specific risk patterns |
custom_seeds |
dict[str, Callable] |
{} |
Custom seed functions per table |
custom_checks |
list[Callable] |
[] |
Additional static analysis check functions |
migration_timeout |
int | None |
None |
Per-migration timeout in seconds (None = no limit) |
# conftest.py
import os
from pytest_mrt import MRTConfig
def pytest_configure(config):
config._mrt_config = MRTConfig(
alembic_ini="alembic.ini",
db_url=os.environ["TEST_DATABASE_URL"],
seed_rows=5,
skip={
"abc123": "Intentional one-way data migration. Reviewed 2025-01-15. See ADR-007."
},
severity_overrides={
"INDEX without CONCURRENTLY": "error",
},
custom_seeds={
"users": lambda: [{"id": 1, "name": "Alice", "email": "alice@example.com"}],
},
)Documents why a specific revision is exempt from rollback testing. Skipped revisions appear in reports as "skipped" (not failed).
skip={
"1a2b3c4d": "RunPython data migration — irreversible by design. ADR-12.",
"5e6f7a8b": "Adds NOT NULL column to 500M-row table — zero-downtime handled externally.",
}Promotes warnings to errors (or demotes errors to warnings) for specific risk pattern names. Pattern names match the pattern field in the JSON output of mrt check.
severity_overrides={
"INDEX without CONCURRENTLY": "error", # treat as error in your org
"noop downgrade": "warning", # already handled by your deploy process
}Each function receives a MigrationAST and returns a list of RiskWarning objects. Custom checks run in addition to the built-in checks.
from pytest_mrt.core.ast_analyzer import MigrationAST
from pytest_mrt.core.detector import RiskWarning
def check_no_truncate(m: MigrationAST) -> list[RiskWarning]:
if "TRUNCATE" in m.source.upper():
return [RiskWarning(
revision=m.revision,
file=m.filename,
pattern="TRUNCATE in migration",
message="TRUNCATE destroys all rows. Use DELETE with a WHERE clause instead.",
severity="error",
)]
return []
config = MRTConfig(custom_checks=[check_no_truncate])The mrt pytest fixture. Obtained via the mrt fixture parameter — do not instantiate directly.
def test_migrations(mrt):
mrt.assert_all_reversible()Run alembic upgrade to the given revision.
mrt.upgrade("head") # upgrade to latest
mrt.upgrade("001abc") # upgrade to a specific revisionRun alembic downgrade by one step (or to a specific revision).
mrt.downgrade() # roll back one step
mrt.downgrade("base") # roll back to empty schemaRun static analysis on migration files. Returns all detected risk warnings.
| Parameter | Default | Description |
|---|---|---|
versions_dir |
None |
Path to Alembic versions directory. Defaults to the path from alembic.ini. |
warnings = mrt.check_static()
errors = [w for w in warnings if w.severity == "error"]Fail the test if static analysis finds any error-severity risks.
def test_no_unsafe_migrations(mrt):
mrt.assert_no_static_errors()Test a single revision for safe reversibility. The database must be at the state just before this revision when called.
Returns a RevisionResult (see below).
mrt.upgrade("001abc")
result = mrt.check_revision("002def")
assert result.passedTest every migration in the chain. Internally runs in O(n) upgrade operations.
results = mrt.check_all()
failed = [r for r in results if not r.passed]Assert that a single revision is safely reversible. Fails the test if not.
def test_latest_migration(mrt):
mrt.assert_reversible()Assert every migration in the chain is safely reversible. Prints a summary table and fails if any migration fails.
def test_all_migrations(mrt):
mrt.assert_all_reversible()Manually seed rows into a table (currently open schema).
mrt.upgrade("001abc")
mrt.seed("users", [{"id": 1, "name": "Alice"}])Assert that all previously seeded rows still exist and have their original values.
mrt.upgrade("head")
mrt.downgrade()
mrt.assert_data_intact()Clear the internal seed state. Called automatically at fixture teardown.
Return type of mrt.check_revision() and elements of mrt.check_all().
| Attribute | Type | Description |
|---|---|---|
revision |
str |
The Alembic revision ID |
passed |
bool |
True if rollback was safe |
skipped |
bool |
True if this revision is in MRTConfig.skip |
skip_reason |
str |
The documented reason for skipping |
failures |
list[str] |
Human-readable failure messages |
risk_score |
int |
0–100 risk score (25 per failure, capped at 100) |
Returns a formatted string of all failure messages.
result = mrt.check_revision("001abc")
if not result.passed:
print(result.failure_summary())Returned by mrt.check_static() and by custom_checks functions.
| Attribute | Type | Description |
|---|---|---|
revision |
str |
Revision ID or filename stem |
file |
str |
Migration filename |
pattern |
str |
Short pattern name (e.g. "DROP COLUMN") |
message |
str |
Human-readable explanation |
severity |
str |
"error" or "warning" |
line |
int | None |
Line number in the migration file |
Statically analyze migration files for rollback risks.
mrt check alembic/versions/
mrt check alembic/versions/ --strict
mrt check alembic/versions/ --format json
| Option | Default | Description |
|---|---|---|
--strict |
False |
Exit 1 on warnings as well as errors |
--format / -f |
table |
Output format: table or json |
Exit codes: 0 = safe, 1 = errors found (or warnings with --strict)
JSON output schema:
[
{
"revision": "001abc",
"file": "001_create_users.py",
"pattern": "DROP COLUMN",
"severity": "error",
"message": "op.drop_column('users', 'email') — data permanently lost...",
"line": 12
}
]Suggest or apply a missing/broken downgrade() function.
mrt fix alembic/versions/001_create_users.py
mrt fix alembic/versions/001_create_users.py --apply
| Option | Default | Description |
|---|---|---|
--apply |
False |
Write the suggested fix to the file |
Generate an HTML safety report for all migrations.
mrt report alembic/versions/
mrt report alembic/versions/ --output report.html
| Option | Default | Description |
|---|---|---|
--output / -o |
migration_report.html |
Output file path |
Scaffold conftest.py and test_migrations.py for your project. Auto-detects alembic.ini.
mrt init
Explain a migration in plain English using Claude AI.
mrt explain alembic/versions/001_create_users.py
Requires: pip install pytest-mrt[ai] and ANTHROPIC_API_KEY environment variable.
Print the installed version.
mrt version