Lab: the five migration tests¶
The code behind the post: a four-revision Alembic history for a small shop, five variants of it with one bug each, and three test suites run against every variant. Needs Docker; PostgreSQL 17 runs in a container started by the test session.
uv venv --python 3.13 .venv
uv pip install --python .venv/bin/python "alembic-gauntlet[asyncio,testcontainers]==0.3.0" asyncpg
.venv/bin/python -m pytest -q # the clean history: 11 passed
VARIANT=drift .venv/bin/python -m pytest -q # one buggy history
.venv/bin/python run_matrix.py # every suite against every history
VARIANTS=clean,drift,drift_server_default,drift_check_missing,drift_enum_value,drift_index_missing,drift_extra_column \
.venv/bin/python run_matrix.py # the drift matrix
| Path | What it is |
|---|---|
shop/models.py |
the ORM side: two tables, one enum, the naming convention |
migrations/env.py |
the env.py contract: injected connection, injected schema, SET LOCAL search_path |
migrations/versions/clean/ |
the four revisions as autogenerate would have written them |
migrations/versions/<bug>/ |
the same four with one file changed; BUG.txt says which and how |
tests/test_plain_ci.py |
what most pipelines do: upgrade head on an empty database |
tests/test_by_hand.py |
the five checks written against Alembic's own API; plumbing in tests/helpers.py |
tests/test_gauntlet.py |
the same five inherited from alembic_gauntlet.MigrationTestBase, plus its check-constraint and enum checks, with server-default comparison turned on |
run_matrix.py |
runs the suite once per variant and prints the pass/fail matrix |
migrations/versions/drift_*/ |
six kinds of schema drift for the drift post: a column type, a server default, a missing index, an extra column, a missing check constraint, a changed enum |
tests/test_drift_extras.py |
the same three written by hand, from before the base class had them |
The VARIANT environment variable selects migrations/versions/<variant> through Alembic's
version_locations; clean is the default.