Skip to main content

CI Status PyPI package version PyPI python versions PyPI downloads

Documentation

testgres

Utility for orchestrating temporary PostgreSQL clusters in Python tests. Supports Python 3.7.3 and newer.

Installation

Install testgres from PyPI:

pip install testgres

Use a dedicated virtual environment for isolated test dependencies.

Usage

Environment

Note: by default testgres invokes initdb, pg_ctl, and psql binaries found in PATH.

Specify a custom PostgreSQL installation in one of the following ways:

  • Set the PG_CONFIG environment variable to point to the pg_config executable.
  • Set the PG_BIN environment variable to point to the directory with PostgreSQL binaries.

Example:

export PG_BIN=$HOME/pg_16/bin
python my_tests.py

Examples

Create a temporary node, run queries, and let testgres clean up automatically:

# create a node with a random name, port, and data directory
with testgres.get_new_node() as node:

    # run initdb
    node.init()

    # start PostgreSQL
    node.start()

    # execute a query in the default database
    print(node.execute('select 1'))

# the node is stopped and its files are removed automatically

Query helpers

testgres provides four helpers for executing queries against the node:

Command Description
node.psql(query, ...) Runs the query via psql and returns a tuple (returncode, stdout, stderr).
node.safe_psql(query, ...) Same as psql() but returns only stdout and raises if the command fails.
node.execute(query, ...) Connects via psycopg2 or pg8000 (whichever is available) and returns a list of tuples.
node.connect(dbname, ...) Returns a NodeConnection wrapper for executing multiple statements within a transaction.

Example of transactional usage:

with node.connect() as con:
    con.begin('serializable')
    print(con.execute('select %s', 1))
    con.rollback()

Logging

By default cleanup() removes all temporary files (data directories, logs, and so on) created by the API. Call configure_testgres(node_cleanup_full=False) before starting nodes if you want to keep logs for inspection.

Note: context managers (the with statement) call stop() and cleanup() automatically.

testgres integrates with the standard Python logging module, so you can aggregate logs from multiple nodes:

import logging

# write everything to /tmp/testgres.log
logging.basicConfig(filename='/tmp/testgres.log')

# enable logging and create two nodes
testgres.configure_testgres(use_python_logging=True)
node1 = testgres.get_new_node().init().start()
node2 = testgres.get_new_node().init().start()

node1.execute('select 1')
node2.execute('select 2')

# disable logging
testgres.configure_testgres(use_python_logging=False)

See tests/test_simple.py for a complete logging example.

Backup and replication

Creating backups and spawning replicas is straightforward:

with testgres.get_new_node('master') as master:
    master.init().start()

    with master.backup() as backup:
        replica = backup.spawn_replica('replica').start()
        replica.catchup()

        print(replica.execute('postgres', 'select 1'))

Benchmarks

Use pgbench through testgres to run quick benchmarks:

with testgres.get_new_node('master') as master:
    master.init().start()

    result = master.pgbench_init(scale=2).pgbench_run(time=10)
    print(result)

Custom configuration

testgres ships with sensible defaults. Adjust them as needed with default_conf() and append_conf():

extra_conf = "shared_preload_libraries = 'postgres_fdw'"

with testgres.get_new_node().init() as master:
    master.default_conf(fsync=True, allow_streaming=True)
    master.append_conf('postgresql.conf', extra_conf)

default_conf() is called by init() and rewrites the configuration file. Apply append_conf() afterwards to keep custom lines.

Remote mode

You can provision nodes on a remote host (Linux only) by wiring RemoteOperations into the configuration:

from testgres import ConnectionParams, RemoteOperations, TestgresConfig, get_remote_node

conn_params = ConnectionParams(
    host='example.com',
    username='postgres',
    ssh_key='/path/to/ssh/key'
)
os_ops = RemoteOperations(conn_params)

TestgresConfig.set_os_ops(os_ops=os_ops)

def test_basic_query():
    with get_remote_node(conn_params=conn_params) as node:
        node.init().start()
        assert node.execute('SELECT 1') == [(1,)]

Pytest integration

Use fixtures to create and clean up nodes automatically when testing with pytest:

import pytest
import testgres

@pytest.fixture
def pg_node():
    node = testgres.get_new_node().init().start()
    try:
        yield node
    finally:
        node.stop()
        node.cleanup()

def test_simple(pg_node):
    assert pg_node.execute('select 1')[0][0] == 1

This pattern keeps tests concise and ensures that every node is stopped and removed even if the test fails.

Scaling tips

  • Run tests in parallel with pytest -n auto (requires pytest-xdist). Ensure each node uses a distinct port by setting PGPORT in the fixture or by passing the port argument to get_new_node().
  • Always call node.cleanup() after each test, or rely on context managers/fixtures that do it for you, to avoid leftover data directories.
  • Prefer node.safe_psql() for lightweight assertions that should fail fast; use node.execute() when you need structured Python results.

Authors

Ildar Musin
Dmitry Ivanov
Ildus Kurbangaliev
Yury Zhuravlev

Release files for testgres 1.16.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for testgres 1.16.1
File Size Uploaded
testgres-1.16.1.tar.gz 102.1 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for testgres 1.16.1
File Interpreter ABI Platform
testgres-1.16.1-py3-none-any.whl Python 3 none any Details

Total release size: 161.3 kB

Release files / testgres-1.16.1.tar.gz

Download URL testgres-1.16.1.tar.gz
Size 102.1 kB
Tags Source
SHA-256 checksum
How to use checksums
da7e41c67c91454417f1acedca803494cfa0f7bb0a02d6e7461e3c2765c93284
BLAKE2b-256 checksum
How to use checksums
6c8a78166005101be160b88f18b3ef193533e6a2e220469616af04bf82f8bd4e
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 19, 2026.

Transparency log

Release files / testgres-1.16.1-py3-none-any.whl

Download URL testgres-1.16.1-py3-none-any.whl
Size 59.2 kB
Tags Python 3
SHA-256 checksum
How to use checksums
81c2c3d67fdba4c0432f497c91d7d4262c2fe4245ed45c67a90904634da4d688
BLAKE2b-256 checksum
How to use checksums
bffa96a91dac32d2acb42a7a53c51a39a6a60bac3b0cd69cb6d71f23d9aa7ad4
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 19, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

1.16.1 This release

2 release files

1.16.0

2 release files

1.15.1

2 release files

1.15.0

2 release files

1.14.5

2 release files

1.14.4

2 release files

1.14.3

2 release files

1.14.2

2 release files

1.13.7

2 release files

1.13.6

2 release files

1.13.5

2 release files

1.13.4

2 release files

1.13.3

2 release files

1.13.2

2 release files

1.13.1

2 release files

1.13.0

2 release files

1.12.2

2 release files

1.12.1

2 release files

1.12.0

2 release files

1.11.1

2 release files

1.11.0

2 release files

1.10.5

2 release files

1.10.4

2 release files

1.10.3

2 release files

1.10.2

2 release files

1.10.1

2 release files

1.10.0

2 release files

1.9.3

2 release files

1.9.2

2 release files

1.9.1

2 release files

1.9.0

2 release files

1.8.9

2 release files

1.8.8

2 release files

1.8.7

2 release files

1.8.6

2 release files

1.8.5

1 release file

1.8.4

1 release file

1.8.3

1 release file

1.8.2

1 release file

1.8.1

1 release file

1.8.0

1 release file

1.7.0

1 release file

1.6.0

1 release file

1.5.0

1 release file

1.4.1

1 release file

1.4.0

1 release file

1.3.4

1 release file

1.3.3

1 release file

1.3.2

1 release file

1.3.1

1 release file

1.3.0

1 release file

1.2.1

1 release file

1.2.0

1 release file

1.1.0

1 release file

1.0.0

1 release file

0.4.0

1 release file

0.3.1

1 release file

0.3.0

1 release file

0.2.0

1 release file

0.1.19

1 release file

0.1.18

1 release file

0.1.17

1 release file

0.1.16

1 release file

0.1.15

1 release file

0.1.14

1 release file

0.1.13

1 release file

0.1.12

0.1.11

1 release file

0.1.10

1 release file

0.1.9

1 release file

0.1.8

1 release file

0.1.7

1 release file

0.1.6

1 release file

0.1.5

1 release file

0.1.4

1 release file

0.1.3

1 release file

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page