Skip to content

Commit f62e785

Browse files
eeeebbbbrrrrclaude
andauthored
Improve cargo pgrx regress UX: add --add, --dry-run, auto-detect workspace crate (pgcentralfoundation#2259)
Replace the interactive "Accept [Y, n]?" prompt with a deterministic `--add <name>` flag that bootstraps new regression tests non-interactively. Tests without expected output are now skipped (instead of prompting),with a clear message directing users to `--add`. Also adds `--dry-run` to preview what would happen, `--test-filter` as a proper named flag (`-t`), inline regression diff output with `-v`, and auto-detection of the pgrx extension crate in virtual workspaces (eliminating the need for `--package` when there's only one extension). Updates README to match the new workflow. One behavior change here is that `--auto` no longer generates expected output for tests that don't have them. They're skipped now. User will need to explicitly `--add` new tests now. --- This may be pgrx' first PR fully written by an AI bot in order to make the AI bot's life easier when working with `cargo pgrx` in general and `cargo pgrx regress` in particular. I think the changes are good for humans too. The things being addressed here have tripped me up numerous times too. --------- Co-authored-by: Claude Opus 4.6 (1M context) <[email protected]>
1 parent 8568a1f commit f62e785

4 files changed

Lines changed: 560 additions & 297 deletions

File tree

cargo-pgrx/README.md

Lines changed: 43 additions & 129 deletions
Original file line numberDiff line numberDiff line change
@@ -529,37 +529,21 @@ Options:
529529

530530
pgrx supports a regression test system very similar to the one prescribed by Postgres' `pg_regress` tool. In fact, pgrx uses `pg_regress` to run the regression tests.
531531

532-
`cargo pgrx regress` is used to run the regression tests. It has a number of options similar to `cargo pgrx test`:
533-
534-
```console
535-
$ cargo pgrx regress --help
536-
Run the regression test suite for this crate
537-
538-
Usage: cargo pgrx regress [OPTIONS] [PG_VERSION] [TEST_FILTER]
539-
540-
Arguments:
541-
[PG_VERSION] Do you want to run against pg13, pg14, pg15, pg16, pg17? [env: PG_VERSION=]
542-
[TEST_FILTER] If specified, only run tests containing this string in their names
543-
544-
Options:
545-
--dbname <DBNAME> If specified, use this database name instead of the auto-generated version of `$extname_regress`
546-
--resetdb Recreate the test database, even if it already exists
547-
-v, --verbose... Enable info logs, -vv for debug, -vvv for trace
548-
-p, --package <PACKAGE> Package to build (see `cargo help pkgid`)
549-
--manifest-path <MANIFEST_PATH> Path to Cargo.toml
550-
-r, --release compile for release mode (default is debug)
551-
--profile <PROFILE> Specific profile to use (conflicts with `--release`)
552-
-n, --no-schema Don't regenerate the schema
553-
--runas <USER> Use `sudo` to initialize and run the Postgres test instance as this system user
554-
--pgdata <DIR> Initialize the test database cluster here, instead of the default location. If used with `--runas`, then it must be writable by the user
555-
--all-features Activate all available features
556-
--no-default-features Do not activate the `default` feature
557-
-F, --features <FEATURES> Space-separated list of features to activate
558-
--postgresql-conf <POSTGRESQL_CONF> Custom `postgresql.conf` settings in the form of `key=value`, ie `log_min_messages=debug1`
559-
-a, --auto Automatically accept output for new tests *and* overwrite output for existing-but-failed tests
560-
-h, --help Print help
561-
-V, --version Print version
562-
```
532+
`cargo pgrx regress` is used to run the regression tests. It has a number of options similar to `cargo pgrx test`.
533+
534+
Key flags:
535+
536+
| Flag | Purpose |
537+
|------|----------------------------------------------------------------------------------------------|
538+
| `--resetdb` | Drop and recreate the test database (recommended for reproducible runs) |
539+
| `--add <name>` | Bootstrap a new test — implies `--resetdb`, runs `setup.sql`, promotes output to `expected/` |
540+
| `-t` / `--test-filter <string>` | Only run tests whose names contain this string |
541+
| `-a` / `--auto` | Overwrite expected output for failed tests with actual output |
542+
| `-v` / `--verbose` | Print regression diffs to stderr on failure |
543+
| `--dry-run` | Print what would happen without doing it |
544+
| `--repeat <N>` | Run the entire configuration N times (default: 1) |
545+
| `-p` / `--package <name>` | Package to build (auto-detected in workspaces with a single pgrx extension) |
546+
| `[PG_VERSION]` | Postgres version (e.g., `pg18`). Optional — defaults to Cargo.toml's default feature |
563547

564548
Regression tests are split into `*.sql` files and `*.out` files. The files themselves are organized into separate directories rooted at `./tests/pg_regress`.
565549

@@ -590,75 +574,51 @@ $ tree
590574

591575
`setup.sql` is a special test in that it's run first, by itself, whenever the test database is first created, or reset using the `--resetdb` argument.
592576

593-
When creating a new test, first make the `.sql` file in `./tests/pg_regress/sql/` and then run `cargo pgrx regress`. pgrx will detect that the file is new and interactively prompt you to add its output, automatically adding it to git (if the directory is managed by git).
594-
595-
For example,
577+
When creating a new test, first make the `.sql` file in `./tests/pg_regress/sql/` and then use `--add` to bootstrap it:
596578

597579
```console
598580
$ echo "SELECT 1;" > ./tests/pg_regress/sql/example.sql
599-
$ cargo pgrx regress
600-
Using DefaultFeature("pg13") and `pg_config` from ~/.pgrx/13.20/pgrx-install/bin/pg_config
601-
Stopping Postgres v13
602-
Building extension with features pg13
603-
Running command " ~/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/bin/cargo" "build" "--lib" "--features" "pg13" "--no-default-features" "--message-format=json-render-diagnostics"
604-
Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.04s
605-
Installing extension
606-
Copying control file to ~/.pgrx/13.20/pgrx-install/share/postgresql/extension/range.control
607-
Copying shared library to ~/.pgrx/13.20/pgrx-install/lib/postgresql/range.so
608-
Discovered 9 SQL entities: 0 schemas (0 unique), 9 functions, 0 types, 0 enums, 0 sqls, 0 ords, 0 hashes, 0 aggregates, 0 triggers
609-
Rebuilding pgrx_embed, in debug mode, for SQL generation with features pg13
610-
Compiling range v0.0.0 ( ~/_work/pgrx/tests/pgrx-examples/range)
611-
Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.70s
612-
Writing SQL entities to ~/.pgrx/13.20/pgrx-install/share/postgresql/extension/range--0.1.0.sql
613-
Finished installing range
614-
Starting Postgres v13 on port 28813
615-
Re-using existing database range_regress
616-
Found 1 new tests, running each individually to create output
617-
Running command cd " ~/_work/pgrx/tests/pgrx-examples/range/pg_regress" && env -u PGDATABASE -u PGHOST -u PGPORT -u PGUSER " ~/.pgrx/13.20/pgrx-install/lib/postgresql/pgxs/src/test/regress/pg_regress" "--host" "localhost" "--port" "28813" "--use-existing" "--dbname=range_regress" "--inputdir= ~/_work/pgrx/tests/pgrx-examples/range/pg_regress" "--outputdir= ~/_work/pgrx/tests/pgrx-examples/range/pg_regress" "example" "--launcher=/tmp/pgrx-pg_regress-runner-2940893.sh"
618-
-----------
619-
SELECT 1;
620-
?column?
621-
----------
622-
1
623-
(1 row)
581+
$ cargo pgrx regress --add example
582+
```
624583

584+
This will:
585+
1. Drop and recreate the test database (`--add` implies `--resetdb`)
586+
2. Run `setup.sql` to establish schema/data
587+
3. Run the new test
588+
4. Copy its output to `./tests/pg_regress/expected/example.out`
589+
5. `git add` the new expected output file
625590

626-
test `example` generated the above output:
627-
Accept [Y, n]?
591+
After bootstrapping, verify the test passes by running the full suite:
592+
593+
```console
594+
$ cargo pgrx regress --resetdb
628595
```
629596

630-
Typing `Y` (or just pressing return) will copy the test output to the proper location, `./tests/pg_regress/expected/example.out` and then run the entire test suite:
597+
Tests without expected output are **skipped** by default during normal runs. If you use `--test-filter` to target a test that hasn't been bootstrapped yet, you'll get a clear error directing you to use `--add` first.
598+
599+
#### Updating expected output after code changes
600+
601+
When code changes alter query output or EXPLAIN plans, use `--auto` to accept the new output:
631602

632603
```console
633-
...
634-
test `example` generated the above output:
635-
Accept [Y, n]? y
636-
Copying test output to ~/_work/pgrx/tests/pgrx-examples/range/tests/pg_regress/expected/example.out
637-
Running command cd " ~/_work/pgrx/tests/pgrx-examples/range/pg_regress" && env -u PGDATABASE -u PGHOST -u PGPORT -u PGUSER " ~/.pgrx/13.20/pgrx-install/lib/postgresql/pgxs/src/test/regress/pg_regress" "--host" "localhost" "--port" "28813" "--use-existing" "--dbname=range_regress" "--inputdir= ~/_work/pgrx/tests/pgrx-examples/range/pg_regress" "--outputdir= ~/_work/pgrx/tests/pgrx-examples/range/pg_regress" "example" "make_range" "store_ranges" "--launcher=/tmp/pgrx-pg_regress-runner-2940893.sh"
638-
(using postmaster on localhost, port 28813)
639-
============== running regression test queries ==============
640-
test example ... ok 6 ms
641-
test make_range ... ok 18 ms
642-
test store_ranges ... ok 20 ms
643-
644-
=====================
645-
All 3 tests passed.
646-
=====================
604+
$ cargo pgrx regress --auto --resetdb
647605
```
648606

649-
Alternatively, you can run `cargo pgrx regress --auto` (or `-a`) to **automatically** accept the output generated by a new test.
607+
`--auto` overwrites expected output for **failed** tests with their actual output. Review the changes with `git diff` to verify they match the intended behavioral change. **Never manually edit `.out` files** — always let `--auto` generate them.
650608

651-
`--auto` will **also** copy the output of **failed** tests to the `./tests/pg_regress/expected/` directory, overwriting the existing expected test output. This is an automated version of blindly accepting different test output as the new, expected output.
609+
When tests fail, the path to the `regression.diffs` file is always shown. Use `-v` to also print the full diff content inline.
652610

653611
### Things to Know
654612

655-
- `setup.sql` is only executed when tests are run for the first time, or the `--resetdb` argument is used
613+
- `setup.sql` is only executed when tests are run for the first time, or the `--resetdb` argument is used. This includes when running a single test with `--resetdb``setup.sql` will always run first to establish the database schema and data before the filtered test executes.
656614
- The point of `setup.sql` is to perform some heavy-weight database object creation/data-loading _only_ when the test regression database is created.
657615
- tests are executed in alphabetical order
616+
- `.sql` files without a corresponding `expected/*.out` file are **skipped** during normal runs — use `--add <name>` to bootstrap new tests
658617
- pgrx creates a database named `$extname_regress` unless `--dbname` is used
659618
- Postgres' documentation for `pg_regress` [begins here](https://www.postgresql.org/docs/current/regress.html). While pgrx does not support every knob and dial, its organization is largely compatible (PRs welcome to enhance features)
660-
- to regenerate the expected test output, delete the `./tests/pg_regress/expected/TEST_NAME.out` file and run `cargo pgrx regress`. You'll be prompted to accept the new output and it'll automatically be run through `git add`
661-
- `pg_regress` uses `psql` to run each test and literally diffs the output against the expected output file. pgrx does two things to help eliminate noise in the test output. The first is it sets `client_min_messages=warning` when starting the Postgres instance and it also passes `-v VERBOSITY=terse` through to `psql`.
619+
- to regenerate the expected test output, delete the `./tests/pg_regress/expected/TEST_NAME.out` file and re-add it with `cargo pgrx regress --add TEST_NAME`
620+
- `pg_regress` uses `psql` to run each test and literally diffs the output against the expected output file. pgrx does two things to help eliminate noise in the test output. The first is it sets `client_min_messages=warning` when starting the Postgres instance and it also passes `-v VERBOSITY=terse` through to `psql`.
621+
- In a workspace with a single pgrx extension crate, `--package` is auto-detected — no need to specify it manually
662622

663623
### Diffing `psql` Output?
664624

@@ -682,56 +642,10 @@ An example of an unkind test might be:
682642

683643
```console
684644
$ echo "CREATE TABLE foo();" > ./tests/pg_regress/sql/bad.sql
685-
$ cargo pgrx regress
686-
Using DefaultFeature("pg13") and `pg_config` from ~/.pgrx/13.20/pgrx-install/bin/pg_config
687-
Stopping Postgres v13
688-
Building extension with features pg13
689-
Running command " ~/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/bin/cargo" "build" "--lib" "--features" "pg13" "--no-default-features" "--message-format=json-render-diagnostics"
690-
Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.04s
691-
Installing extension
692-
Copying control file to ~/.pgrx/13.20/pgrx-install/share/postgresql/extension/range.control
693-
Copying shared library to ~/.pgrx/13.20/pgrx-install/lib/postgresql/range.so
694-
Discovered 9 SQL entities: 0 schemas (0 unique), 9 functions, 0 types, 0 enums, 0 sqls, 0 ords, 0 hashes, 0 aggregates, 0 triggers
695-
Rebuilding pgrx_embed, in debug mode, for SQL generation with features pg13
696-
Compiling range v0.0.0 ( ~/_work/pgrx/tests/pgrx-examples/range)
697-
Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.71s
698-
Writing SQL entities to ~/.pgrx/13.20/pgrx-install/share/postgresql/extension/range--0.1.0.sql
699-
Finished installing range
700-
Starting Postgres v13 on port 28813
701-
Re-using existing database range_regress
702-
Found 1 new tests, running each individually to create output
703-
Running command cd " ~/_work/pgrx/tests/pgrx-examples/range/tests/pg_regress" && env -u PGDATABASE -u PGHOST -u PGPORT -u PGUSER " ~/.pgrx/13.20/pgrx-install/lib/postgresql/pgxs/src/test/regress/pg_regress" "--host" "localhost" "--port" "28813" "--use-existing" "--dbname=range_regress" "--inputdir= ~/_work/pgrx/tests/pgrx-examples/range/pg_regress" "--outputdir= ~/_work/pgrx/tests/pgrx-examples/range/pg_regress" "bad" "--launcher=/tmp/pgrx-pg_regress-runner-2947999.sh"
704-
-----------
705-
CREATE TABLE foo();
706-
707-
test `bad` generated the above output:
708-
Accept [Y, n]?
709-
```
710-
711-
That looks like the perfect output, so we accept it:
712-
713-
```console
714-
...
715-
test `bad` generated the above output:
716-
Accept [Y, n]? Y
717-
Copying test output to ~/_work/pgrx/tests/pgrx-examples/range/tests/pg_regress/expected/bad.out
718-
Running command cd " ~/_work/pgrx/tests/pgrx-examples/range/tests/pg_regress" && env -u PGDATABASE -u PGHOST -u PGPORT -u PGUSER " ~/.pgrx/13.20/pgrx-install/lib/postgresql/pgxs/src/test/regress/pg_regress" "--host" "localhost" "--port" "28813" "--use-existing" "--dbname=range_regress" "--inputdir= ~/_work/pgrx/tests/pgrx-examples/range/pg_regress" "--outputdir= ~/_work/pgrx/tests/pgrx-examples/range/pg_regress" "bad" "make_range" "store_ranges" "--launcher=/tmp/pgrx-pg_regress-runner-2947999.sh"
719-
(using postmaster on localhost, port 28813)
720-
============== running regression test queries ==============
721-
test bad ... FAILED 5 ms
722-
test make_range ... ok 18 ms
723-
test store_ranges ... ok 19 ms
724-
725-
======================
726-
1 of 3 tests failed.
727-
======================
728-
729-
The differences that caused some tests to fail can be viewed in the
730-
file " ~/_work/pgrx/tests/pgrx-examples/range/tests/pg_regress/regression.diffs". A copy of the test summary that you see
731-
above is saved in the file " ~/_work/pgrx/tests/pgrx-examples/range/tests/pg_regress/regression.out".
645+
$ cargo pgrx regress --add bad
732646
```
733647

734-
And you see the `bad` test immediately failed! To see how it failed, look at the `./tests/pg_regress/regression.diffs` file:
648+
Then on a second run (without `--resetdb`), the `CREATE TABLE` will fail because the table already exists. You'd see the regression diffs printed inline:
735649

736650
```console
737651
$ diff -U3 ~/_work/pgrx/tests/pgrx-examples/range/tests/pg_regress/expected/bad.out ~/_work/pgrx/tests/pgrx-examples/range/tests/pg_regress/results/bad.out

0 commit comments

Comments
 (0)