Measured on 0.2.2 against PostgreSQL 17. Six kinds of drift between the migrated schema and the models, each a one-file change to a clean four-revision history, run through test_migrations_up_to_date:
drift_type (String(100) in the migration, String(255) in the model) failed caught
drift_index_missing (idx_orders_user_id never created) failed caught
drift_extra_column (a column the model does not have) failed caught
drift_server_default (server_default false in the migration, true in the model) passed missed
drift_check_missing (the amount check never created) passed missed
drift_enum_value (order_status without 'shipped') passed missed
The three misses are Alembic's, not the test's: compare_metadata skips server defaults unless compare_server_default=True is in the context opts, never compares CHECK constraints, and never compares enum members. The test as written passes opts={"version_table_schema": ...} and nothing else, so a team that trusts "the diff is empty" is trusting it for half of what can drift, and the half it does not cover is the half that shows up as a production incident: a wrong default on insert, a check that is not there, a value the code writes and the type rejects.
Three checks close the gaps, written against the inspector and pg_enum; against the same six variants plus the clean history they catch the three misses and stay green on the clean one:
clean 3 passed
drift_server_default 1 failed, 2 passed (test_server_defaults_match)
drift_check_missing 1 failed, 2 passed (test_check_constraints_match)
drift_enum_value 1 failed, 2 passed (test_enum_values_match)
What I think it needs: a class attribute, say migration_diff_compare_server_default: ClassVar[bool] = False, that the up-to-date test passes through to compare_metadata (opt-in, because a default expressed two ways is a common false positive; the docs should say which spellings agree); and two new tests on MigrationConsistencyMixin, one comparing the CHECK constraints the metadata declares against get_check_constraints per table (by name, resolved through the metadata's naming convention the way the naming test already resolves rules), one comparing each Enum column's members against pg_enum in order. Both are PostgreSQL-only like the rest of the mixin. The hand-written versions are in the lab as tests/test_drift_extras.py; the enum one is a straight port, the check one needs the convention resolution done properly rather than my ad-hoc prefix guard.
Lab: https://github.com/bedrock-python/bedrock-python.github.io/tree/docs/production-python-series/docs/blog/lab/2026-09-07-five-alembic-migration-tests (migrations/versions/drift_*, tests/test_drift_extras.py, VARIANT=drift_enum_value python -m pytest tests/test_gauntlet.py tests/test_drift_extras.py).
Measured on 0.2.2 against PostgreSQL 17. Six kinds of drift between the migrated schema and the models, each a one-file change to a clean four-revision history, run through
test_migrations_up_to_date:The three misses are Alembic's, not the test's:
compare_metadataskips server defaults unlesscompare_server_default=Trueis in the context opts, never compares CHECK constraints, and never compares enum members. The test as written passesopts={"version_table_schema": ...}and nothing else, so a team that trusts "the diff is empty" is trusting it for half of what can drift, and the half it does not cover is the half that shows up as a production incident: a wrong default on insert, a check that is not there, a value the code writes and the type rejects.Three checks close the gaps, written against the inspector and
pg_enum; against the same six variants plus the clean history they catch the three misses and stay green on the clean one:What I think it needs: a class attribute, say
migration_diff_compare_server_default: ClassVar[bool] = False, that the up-to-date test passes through tocompare_metadata(opt-in, because a default expressed two ways is a common false positive; the docs should say which spellings agree); and two new tests onMigrationConsistencyMixin, one comparing the CHECK constraints the metadata declares againstget_check_constraintsper table (by name, resolved through the metadata's naming convention the way the naming test already resolves rules), one comparing eachEnumcolumn's members againstpg_enumin order. Both are PostgreSQL-only like the rest of the mixin. The hand-written versions are in the lab astests/test_drift_extras.py; the enum one is a straight port, the check one needs the convention resolution done properly rather than my ad-hoc prefix guard.Lab: https://github.com/bedrock-python/bedrock-python.github.io/tree/docs/production-python-series/docs/blog/lab/2026-09-07-five-alembic-migration-tests (
migrations/versions/drift_*,tests/test_drift_extras.py,VARIANT=drift_enum_value python -m pytest tests/test_gauntlet.py tests/test_drift_extras.py).