Testing and deployment

Verify stored data, preserved schema and repeat execution on the actual target engine.

Examples use Classic and Fluent tabs. Your choice follows you through the manual.

Test a migration lifecycle

Create a disposable database, apply the migration, check the schema and rows, run to the same target again, then downgrade and verify the intended reverse. Both authoring styles use the same runner. This fragment assumes an initialized runner whose migration set creates Users.

A host-level smoke check

Classic

runner.MigrateToLastVersion();
if (!provider.TableExists("Users")) throw new Exception("Users missing");
runner.MigrateToLastVersion();
runner.MigrateTo(0);
if (provider.TableExists("Users")) throw new Exception("Users was not removed");

Fluent

runner.MigrateToLastVersion();
if (!provider.TableExists("Users")) throw new Exception("Users missing");
runner.MigrateToLastVersion();
runner.MigrateTo(0);
if (provider.TableExists("Users")) throw new Exception("Users was not removed");

Shared host · both styles

What to assert

Test defaults by omitting a value, and nullability by explicitly sending NULL. Verify composite-key order, foreign-key actions and constraint names. After a SQLite rebuild check real rows, collations, supported indexes/triggers and identity high-water state. Test failure paths as well as successful SQL generation.

Use representative production-sized data to measure lock duration and backfill cost. A passing SQL-string assertion does not establish that a database accepts a command or preserves its semantics.

Repository checks

Build with dotnet build Migrator.slnx, then use .github/scripts/test.ps1 -Database Unit or SQLite for local suites. The live-engine guide gives the external database setup. Homepage CI results include commit provenance and skipped/missing-suite status.

Production rollout

Keep applied migrations immutable, review SQL and explicit reverse behavior, and serialize competing deploys. Validate against a restored database before making a breaking change. Plan application compatibility around expand/backfill/contract phases. Treat post-commit callback failures as durable migrations requiring follow-up handling.