Testing PostgreSQL
testing.postgresql is a Python library that automatically sets up a PostgreSQL instance in a temporary directory for testing purposes and destroys it afterward. The current version is 1.3.0. Its release cadence appears to be slow, with the last major update in 2016.
Warnings
- breaking This library requires a pre-installed PostgreSQL server in your system's PATH environment variable. It uses binaries like `initdb` and `postgres` directly. Without these, the library cannot function.
- gotcha The `testing-postgresql` project appears to be minimally maintained, with the last PyPI release in 2016 and limited GitHub activity since 2017. Users seeking active development, support for newer PostgreSQL features, or compatibility with recent Python versions might find it lacking.
- gotcha By default, `testing.postgresql.Postgresql` invokes `initdb` on every instantiation. This can be a slow operation, especially when creating many test databases for individual test cases, leading to increased test suite execution time.
- gotcha Failure to explicitly call `.stop()` on a `Postgresql` instance or neglecting to use it within a `with` statement (context manager) can leave lingering PostgreSQL processes and temporary data directories, consuming system resources and potentially causing conflicts.
Install
-
pip install testing.postgresql
Imports
- Postgresql
from testing.postgresql import Postgresql
- PostgresqlFactory
from testing.postgresql import PostgresqlFactory
Quickstart
import testing.postgresql
from sqlalchemy import create_engine
import psycopg2
# Basic usage with a context manager
with testing.postgresql.Postgresql() as postgresql:
# Connect using SQLAlchemy
engine = create_engine(postgresql.url())
with engine.connect() as conn:
result = conn.execute(postgresql.text("SELECT 1")).scalar()
print(f"SQLAlchemy: Connected to {postgresql.url()}, result: {result}")
# Connect using psycopg2 (requires psycopg2 to be installed)
try:
conn_psycopg = psycopg2.connect(**postgresql.dsn())
cursor = conn_psycopg.cursor()
cursor.execute("CREATE TABLE my_table (id SERIAL PRIMARY KEY, name VARCHAR(255))")
cursor.execute("INSERT INTO my_table (name) VALUES (%s)", ('test_name',))
cursor.execute("SELECT name FROM my_table WHERE id = 1")
name_result = cursor.fetchone()[0]
print(f"psycopg2: Inserted and retrieved: {name_result}")
cursor.close()
conn_psycopg.close()
except Exception as e:
print(f"psycopg2 connection/query failed: {e}")
# Example of using PostgresqlFactory for faster tests (e.g., in a test suite setup)
def custom_init_handler(pg_instance):
"""An optional handler to run SQL on a newly initialized DB."""
conn = psycopg2.connect(**pg_instance.dsn())
cursor = conn.cursor()
cursor.execute("CREATE TABLE users (id SERIAL PRIMARY KEY, username VARCHAR(255))")
conn.commit()
conn.close()
print("Factory DB initialized with 'users' table.")
PostgresqlFactory = testing.postgresql.PostgresqlFactory(
cache_initialized_db=True,
on_initialized=custom_init_handler
)
with PostgresqlFactory() as postgresql_cached:
conn = psycopg2.connect(**postgresql_cached.dsn())
cursor = conn.cursor()
cursor.execute("INSERT INTO users (username) VALUES (%s)", ('cached_user',))
conn.commit()
cursor.execute("SELECT username FROM users WHERE id = 1")
user_result = cursor.fetchone()[0]
print(f"Factory usage: Inserted and retrieved: {user_result}")
conn.close()