Database test commands
Ptah has two native declarative test commands:
ptah migrations test [flags]ptah schema test [flags]Both load *.yaml and *.yml files from --dir, execute cases in file order,
render a report, and return a non-zero status when any case fails.
Command flags
Section titled “Command flags”| Flag | Migrations test | Schema test | Default |
|---|---|---|---|
--dir |
Yes | Yes | ./tests |
--migrations-dir |
Yes | No | ./migrations |
--root-dir |
Go annotation directory used by apply_schema |
Desired-schema source: a SQL, YAML, HCL, or DBML file, a Go annotation directory, or a live database URL | ./models |
--seed-dir |
Default for seed steps | Default for seed steps | No default |
--dir-format |
auto, ptah, or atlas |
No | ptah |
--db-url |
Optional explicit throwaway database | Optional explicit throwaway database | Ephemeral SQLite |
--schema |
No | Repeatable desired-schema allow-list; database-wide extensions remain regardless of installation placement | All schemas |
--var |
No | Repeatable name=value override for an HCL desired-schema file |
No overrides |
--run |
Go regular expression matched against case names | Go regular expression matched against case names | All cases |
--report |
text, json, or html |
text, json, or html |
text |
YAML model
Section titled “YAML model”Each file contains cases, each case contains name and steps, and each step
sets exactly one action:
| Action | Value | Scope |
|---|---|---|
migrate_to |
Non-negative integer version, latest, or 0 |
Migration tests |
apply_schema |
true |
Additively converge the selected desired schema using the live target |
seed |
Mapping with required env; optional dir overrides --seed-dir |
Both |
exec |
SQL string | Both |
assert |
Mapping with query and one condition |
Both |
Assertion conditions are row_count (a non-negative integer), scalar, and
error_contains. Unknown fields, unnamed cases, empty step lists, and steps
with zero or multiple actions are errors. Every seed step must either set dir
or receive a run-level --seed-dir.
Isolation
Section titled “Isolation”Without --db-url, every case gets a separate ephemeral SQLite database. With
--db-url, all cases share the explicit caller-owned database and the caller
must isolate and clean it. The explicit target must be disposable because test
steps mutate schema and data. Reusing it is supported for idempotent cases, but
concurrent runners are not serialized and arbitrary SQL is not rolled back.
apply_schema preserves unrelated objects, uses live dialect capabilities and
identifier semantics, and can repair supported drift. Roles and grants are
rejected because their effects can escape the database-local test lifecycle.
schema test names its desired schema with one selector: --root-dir for a
directory of Go annotations, --schema-file for a .sql, .yaml, .yml,
.hcl, or .dbml file, and --source-db-url for a database whose live schema
is introspected. Naming two is refused before the throwaway database is
provisioned. --root-dir also accepts a file or a database URL, which is what
it did before the other two selectors existed; such a run reports on standard
error which selector names that source exactly. HCL files also accept repeatable
--var name=value overrides.
Exit contract
Section titled “Exit contract”| Exit | Meaning |
|---|---|
0 |
Every case passed. |
1 |
The runner completed and at least one case failed. |
2 |
Usage, input, connection, interruption, setup, or report failure. |
For examples and CI guidance, see Test migrations and schemas. For the embeddable runner contract, see Public Go API.