Conversation
A ctypes binding of libpq (bindings, constants, OIDs, library discovery, notification and result handling) plus a Session class providing synchronous, asynchronous, pipeline, COPY-free NOTIFY/notice and non-blocking query execution. This lets the Python test suite run SQL in-process without forking psql.
PostgresServer manages a cluster's lifecycle (initdb, start/stop/restart, promote), configuration, in-process SQL, log inspection, backup/streaming/ archiving/restore, WAL helpers, replication-slot helpers and connect_ok/ connect_fails connection assertions. PgBin runs client programs; the fixtures (pg_bin, create_pg, pg, conn, bindir, libdir) build the common test objects and tear them down automatically. Author: Jelte Fennema-Nio <postgres@jeltef.nl> Reviewed-by: Andrew Dunstan <andrew@dunslane.net>
pgtap is a pytest plugin that emits TAP for the meson/prove harness when TESTLOGDIR is set, and maps a whole-module skip to success. The repository pyproject.toml carries the pytest configuration. meson gains a pytest feature option and a kind=='pytest' test branch, so each directory can list pytest suites beside its tap suites. Includes the suite's own self-tests. The root pyproject.toml also configures the suite's code quality gates: black for formatting, and pylint and mypy for linting and type checking (the dev-tooling dependency group lives in src/test/pytest/pyproject.toml; none of it is needed to run the tests). The whole suite is kept black-clean, pylint 10.00/10 and mypy-clean. Author: Jelte Fennema-Nio <postgres@jeltef.nl> Reviewed-by: Andrew Dunstan <andrew@dunslane.net>
Helpers used by the heavier test suites: a pg_regress runner, an OpenSSL-backed SSL server configurator, an slapd launcher, a stand-alone Kerberos KDC, and a launcher for the mock OAuth provider.
Document the Python port of the Perl TAP suite: layout, how to run the tests under meson and directly with pytest, the shared fixtures, and the PostgresServer/Session/PgBin framework classes.
Replace the four src/bin/psql Perl TAP tests with their pytest equivalents and switch the meson test registration from 'tap' to 'pytest'. The interactive tab-completion and pager tests drive psql through a pty via pexpect (the interactive_psql fixture in pyt/conftest.py) and skip when pexpect, readline or a working "wc -l" is unavailable.
Replace the four src/bin/pg_ctl Perl TAP tests with their pytest equivalents and switch the meson test registration from 'tap' to 'pytest'.
Replace the six src/interfaces/libpq Perl TAP tests with their pytest equivalents and switch the meson test registration from 'tap' to 'pytest', preserving the existing env and deps.
Convert the streaming-replication recovery test as a representative multi-node physical-replication example. Add a 'pytest' block to src/test/recovery/meson.build for pyt/test_001_stream_rep.py and drop the corresponding t/001_stream_rep.pl from the 'tap' list; the remaining recovery Perl tests are unchanged.
Convert the logical-replication change-propagation test as a representative multi-node logical-replication example. Add a 'pytest' block to src/test/subscription/meson.build for pyt/test_001_rep_changes.py and drop the corresponding t/001_rep_changes.pl from the 'tap' list; the remaining subscription Perl tests are unchanged.
Enable the pytest suite (-Dpytest=enabled) on all jobs. This needs pytest installed where the images do not already provide it: via MacPorts on macOS (plus pexpect for the interactive psql tests, which need a pty and so skip on Windows), via pip on the Windows VS image, and via pacman on MinGW. The AddressSanitizer job needs one accommodation: the suite loads libpq in-process via ctypes, and dlopening an ASan-instrumented libpq into an uninstrumented python aborts because the ASan runtime must come first in the link order. Preload the ASan runtime for the test step to satisfy that; it is a no-op for the already-instrumented server binaries.
The SanityCheck job ran the TAP test pg_ctl/001_start_stop, which was removed when src/bin/pg_ctl was converted to pytest (see "python tests: convert the pg_ctl TAP suite to pytest"). Point MTEST_TARGET at the pytest equivalent pg_ctl/test_001_start_stop and enable -Dpytest on the SanityCheck setup (its minimal config uses --auto-features=disabled, so pytest must be requested explicitly; the Linux image already provides pytest). Also update the now-stale "a tap test" comment.
The pytest suites were wired into the Meson build only, so the autoconf/make build had no way to run them. After the converted Perl tests were removed, "make check" in the fully converted directories ran prove against an empty t/ and failed. Teach the make build to run pytest, mirroring the existing prove_check machinery: - configure: add --enable-pytest and locate pytest (falling back to "python -m pytest", as the Meson build does, for installations that ship only the module). - src/Makefile.global.in: add enable_pytest, PYTEST and the pytest_check / pytest_installcheck recipes. They set up the temporary install on PATH and put src/test/pytest on PYTHONPATH, then run "pytest pyt/test_*.py" from the test directory; the active pytest configuration comes from the repository-root pyproject.toml. - Wire the converted directories' check targets: psql, pg_ctl and libpq (fully converted) run pytest_check; recovery and subscription (one test each converted) run both prove_check and pytest_check so their remaining Perl tests still run. - CI: configure the Linux Autoconf job with --enable-pytest. Validated with a VPATH autoconf build: "make check" in src/bin/psql and src/interfaces/libpq runs the pytest suites to green TAP output.
…onvention
The converted pytest suites were named test_NNN_name.py, which required a
custom python_files = ["test_*.py"] pytest setting. Rename them to
NNN_name.py instead, mirroring the t/NNN_name.pl Perl originals they replace
(e.g. t/001_basic.pl -> pyt/001_basic.py); this is the project's TAP file
naming convention and makes the meson/prove test names match the Perl ones
(psql/001_basic rather than psql/test_001_basic).
The framework's own self-tests under src/test/pytest/pyt have no Perl origin
and keep the pytest-default test_*.py names. pyproject.toml's python_files
now lists both patterns ("[0-9]*.py" and "test_*.py"), and the make
pytest_check glob uses pyt/[0-9]*.py (which also excludes conftest.py). Test
*function* names keep the test_ prefix, as pytest requires.
Updates the five meson test lists, src/Makefile.global.in, the CI SanityCheck
target and the README accordingly.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Introduces the Python/pytest test framework (in-process libpq via ctypes, a
PostgresServer fixture layer, the pgtap plugin wired into the meson build) plus
a small representative sample of TAP→pytest conversions. Based on
master.Core framework
SessionPostgresServerframework + pytest fixturesRepresentative conversions (16 scripts)
Each converted script's Perl
t/*.plorigin is removed in the same commit.src/bin/psqlsrc/bin/pg_ctlsrc/interfaces/libpqsrc/test/recovery001_stream_rep(physical rep)src/test/subscription001_rep_changes(logical rep)Full directories flip the meson registration from
taptopytestentirely.The two partial conversions add a
pytestblock and drop only the one convertedPerl entry; the remaining Perl tests in those directories (e.g.
recovery/002_archiving,subscription/002_types) are untouched. Coverage spansinteractive client, server lifecycle, libpq/Session networking, and physical &
logical replication.
CI
ci: run the pytest suite in CI— enables-Dpytest=enabledon all jobs andinstalls the needed deps (MacPorts/pip/pacman; ASan
LD_PRELOADaccommodation).This branch deliberately removes the Perl scripts it converts rather than
carrying a "temporarily disable the Perl TAP tests" commit. The
pg_mkdir_pconcurrency fix is not included (already in
master).Validation
meson setup -Dpytest=enabledconfigures clean; meson registers exactly theconverted pytest tests with no dangling Perl references; the libpq suite runs
green (4 OK, 2 env-gated skips).