Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/ci/provider-groups.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
"tests/test_elasticsearch.py::test_plugin_imports_without_elasticsearch_clients",
"tests/test_mongodb.py::test_plugin_imports_without_pymongo",
"tests/test_mssql.py::test_plugin_imports_without_pymssql",
"tests/test_postgres.py::test_plugin_imports_without_psycopg",
"tests/test_spanner.py::test_plugin_imports_without_google_cloud_spanner",
"tests/test_valkey.py::test_plugin_imports_without_valkey"
],
Expand Down
35 changes: 16 additions & 19 deletions docs/getting-started/basic-usage.rst
Original file line number Diff line number Diff line change
@@ -1,34 +1,31 @@
Basic Usage
===========

Once a plugin is enabled (e.g., PostgreSQL), you can use its fixtures directly in your tests. There are typically two main types of fixtures:

1. **Service Fixture** (e.g., `postgres_service`): Provides details about the running database service (host, port, credentials, etc.). Useful for connecting with your own client.
2. **Connection Fixture** (e.g., `postgres_connection`): Provides a ready-to-use connection object (where applicable) to the database service.
Once a plugin is enabled (e.g., PostgreSQL), you can use its fixtures directly in your tests. The fixture you'll use most often is the **Service Fixture** (e.g., ``postgres_service``), which provides details about the running database service (host, port, credentials, etc.) so you can connect with your own client.

.. code-block:: python

# Assuming you have installed pytest-databases[postgres] and enabled the plugin
# Also assuming a client like psycopg is installed: pip install psycopg
# Assuming you have installed pytest-databases[postgres] and enabled the plugin.
# Install your preferred PostgreSQL client alongside it: pip install psycopg
import psycopg
from pytest_databases.docker.postgres import PostgresService

# Example using the Service Fixture
def test_connection_with_service_details(postgres_service: PostgresService) -> None:
conn_str = (
f"postgresql://{postgres_service.user}:{postgres_service.password}@"
f"{postgres_service.host}:{postgres_service.port}/{postgres_service.database}"
)
with psycopg.connect(conn_str, autocommit=True) as conn:
with conn.cursor() as cursor:
cursor.execute("SELECT 1")
assert cursor.fetchone() == (1,)
with psycopg.connect(conn_str, autocommit=True) as conn, conn.cursor() as cursor:
cursor.execute("SELECT 1")
assert cursor.fetchone() == (1,)

# Example using the Connection Fixture
def test_with_direct_connection(postgres_connection) -> None:
# postgres_connection is often a configured client or connection object
with postgres_connection.cursor() as cursor:
cursor.execute("CREATE TABLE IF NOT EXISTS users (id INT PRIMARY KEY, name TEXT);")
cursor.execute("INSERT INTO users (id, name) VALUES (1, 'Alice');")
cursor.execute("SELECT name FROM users WHERE id = 1;")
assert cursor.fetchone() == ('Alice',)
def test_write_and_read(postgres_service: PostgresService) -> None:
conn_str = (
f"postgresql://{postgres_service.user}:{postgres_service.password}@"
f"{postgres_service.host}:{postgres_service.port}/{postgres_service.database}"
)
with psycopg.connect(conn_str, autocommit=True) as conn, conn.cursor() as cursor:
cursor.execute("CREATE TABLE IF NOT EXISTS users (id INT PRIMARY KEY, name TEXT);")
cursor.execute("INSERT INTO users (id, name) VALUES (1, 'Alice');")
cursor.execute("SELECT name FROM users WHERE id = 1;")
assert cursor.fetchone() == ("Alice",)
71 changes: 33 additions & 38 deletions docs/supported-databases/postgres.rst
Original file line number Diff line number Diff line change
@@ -1,92 +1,87 @@
PostgreSQL
==========

Integration with `PostgreSQL <https://www.postgresql.org/>`_ using the `PostgreSQL Docker Image <https://hub.docker.com/_/postgres>`_, Google's `AlloyDB Omni <https://cloud.google.com/alloydb/omni?hl=en>`_, `pgvector Docker Image <https://hub.docker.com/r/ankane/pgvector>`_, or `ParadeDB Docker Image <https://hub.docker.com/r/paradedb/paradedb>`_
Integration with `PostgreSQL <https://www.postgresql.org/>`_ using the `PostgreSQL Docker Image <https://hub.docker.com/_/postgres>`_, Google's `AlloyDB Omni <https://cloud.google.com/alloydb/omni?hl=en>`_, `pgvector Docker Image <https://hub.docker.com/r/ankane/pgvector>`_, or `ParadeDB Docker Image <https://hub.docker.com/r/paradedb/paradedb>`_.

Installation
------------

.. code-block:: bash

pip install pytest-databases[postgres]
pip install pytest-databases[postgres] psycopg

The ``psycopg`` Python client is no longer pulled by ``pytest-databases[postgres]`` — install your preferred PostgreSQL client alongside ``pytest-databases``.

Usage Example
-------------

.. code-block:: python

import pytest
import psycopg
from pytest_databases.docker.postgres import PostgresService

pytest_plugins = ["pytest_databases.docker.postgres"]

def test(postgres_service: PostgresService) -> None:
with psycopg.connect(
f"postgresql://{postgres_service.user}:{postgres_service.password}@{postgres_service.host}:{postgres_service.port}/{postgres_service.database}"
f"postgresql://{postgres_service.user}:{postgres_service.password}"
f"@{postgres_service.host}:{postgres_service.port}/{postgres_service.database}"
) as conn:
db_open = conn.execute("SELECT 1").fetchone()
assert db_open is not None and db_open[0] == 1

def test(postgres_connection: psycopg.Connection) -> None:
postgres_connection.execute("CREATE TABLE if not exists simple_table as SELECT 1")
result = postgres_connection.execute("select * from simple_table").fetchone()
assert result is not None and result[0] == 1
result = conn.execute("SELECT 1").fetchone()
assert result is not None and result[0] == 1

Available Fixtures
------------------

* ``postgres_host``: The PostgreSQL host address (defaults to "127.0.0.1", can be overridden with ``POSTGRES_HOST`` environment variable).
* ``postgres_user``: The PostgreSQL user.
* ``postgres_password``: The PostgreSQL password.
* ``postgres_database``: The PostgreSQL database name to use.
* ``postgres_image``: The Docker image to use for PostgreSQL.
* ``postgres_port``: Optional host-side port pin (default ``None``, override via ``POSTGRES_PORT`` env).
* ``postgres_service``: A fixture that provides a PostgreSQL service.
* ``postgres_connection``: A fixture that provides a PostgreSQL connection.
* ``postgres_service``: A fixture that provides a ``PostgresService`` (``host``, ``port``, ``container``, ``database``, ``user``, ``password``).

The following version-specific fixtures are also available. Each has its own
``*_port`` fixture and matching env var so multiple versions can be pinned in
the same session without colliding:

* ``postgres_11_service``, ``postgres_11_connection``, ``postgres_11_port`` (env: ``POSTGRES_11_PORT``)
* ``postgres_12_service``, ``postgres_12_connection``, ``postgres_12_port`` (env: ``POSTGRES_12_PORT``)
* ``postgres_13_service``, ``postgres_13_connection``, ``postgres_13_port`` (env: ``POSTGRES_13_PORT``)
* ``postgres_14_service``, ``postgres_14_connection``, ``postgres_14_port`` (env: ``POSTGRES_14_PORT``)
* ``postgres_15_service``, ``postgres_15_connection``, ``postgres_15_port`` (env: ``POSTGRES_15_PORT``)
* ``postgres_16_service``, ``postgres_16_connection``, ``postgres_16_port`` (env: ``POSTGRES_16_PORT``)
* ``postgres_17_service``, ``postgres_17_connection``, ``postgres_17_port`` (env: ``POSTGRES_17_PORT``)
* ``postgres_18_service``, ``postgres_18_connection``, ``postgres_18_port`` (env: ``POSTGRES_18_PORT``)
* ``postgres_11_service``, ``postgres_11_port`` (env: ``POSTGRES_11_PORT``)
* ``postgres_12_service``, ``postgres_12_port`` (env: ``POSTGRES_12_PORT``)
* ``postgres_13_service``, ``postgres_13_port`` (env: ``POSTGRES_13_PORT``)
* ``postgres_14_service``, ``postgres_14_port`` (env: ``POSTGRES_14_PORT``)
* ``postgres_15_service``, ``postgres_15_port`` (env: ``POSTGRES_15_PORT``)
* ``postgres_16_service``, ``postgres_16_port`` (env: ``POSTGRES_16_PORT``)
* ``postgres_17_service``, ``postgres_17_port`` (env: ``POSTGRES_17_PORT``)
* ``postgres_18_service``, ``postgres_18_port`` (env: ``POSTGRES_18_PORT``)

pgvector
^^^^^^^^

* ``pgvector_image``, ``pgvector_service``, ``pgvector_connection``, ``pgvector_port`` (env: ``PGVECTOR_PORT``) — default image ``pgvector/pgvector:pg18``
* ``pgvector_13_service``, ``pgvector_13_connection``, ``pgvector_13_port`` (env: ``PGVECTOR_13_PORT``)
* ``pgvector_14_service``, ``pgvector_14_connection``, ``pgvector_14_port`` (env: ``PGVECTOR_14_PORT``)
* ``pgvector_15_service``, ``pgvector_15_connection``, ``pgvector_15_port`` (env: ``PGVECTOR_15_PORT``)
* ``pgvector_16_service``, ``pgvector_16_connection``, ``pgvector_16_port`` (env: ``PGVECTOR_16_PORT``)
* ``pgvector_17_service``, ``pgvector_17_connection``, ``pgvector_17_port`` (env: ``PGVECTOR_17_PORT``)
* ``pgvector_18_service``, ``pgvector_18_connection``, ``pgvector_18_port`` (env: ``PGVECTOR_18_PORT``)
* ``pgvector_image``, ``pgvector_service``, ``pgvector_port`` (env: ``PGVECTOR_PORT``) — default image ``pgvector/pgvector:pg18``
* ``pgvector_13_service``, ``pgvector_13_port`` (env: ``PGVECTOR_13_PORT``)
* ``pgvector_14_service``, ``pgvector_14_port`` (env: ``PGVECTOR_14_PORT``)
* ``pgvector_15_service``, ``pgvector_15_port`` (env: ``PGVECTOR_15_PORT``)
* ``pgvector_16_service``, ``pgvector_16_port`` (env: ``PGVECTOR_16_PORT``)
* ``pgvector_17_service``, ``pgvector_17_port`` (env: ``PGVECTOR_17_PORT``)
* ``pgvector_18_service``, ``pgvector_18_port`` (env: ``PGVECTOR_18_PORT``)

ParadeDB
^^^^^^^^

ParadeDB extends PostgreSQL with BM25 full-text search and analytics extensions.

* ``paradedb_image``, ``paradedb_service``, ``paradedb_connection``, ``paradedb_port`` (env: ``PARADEDB_PORT``) — default image ``paradedb/paradedb:latest-pg18``
* ``paradedb_15_service``, ``paradedb_15_connection``, ``paradedb_15_port`` (env: ``PARADEDB_15_PORT``)
* ``paradedb_16_service``, ``paradedb_16_connection``, ``paradedb_16_port`` (env: ``PARADEDB_16_PORT``)
* ``paradedb_17_service``, ``paradedb_17_connection``, ``paradedb_17_port`` (env: ``PARADEDB_17_PORT``)
* ``paradedb_18_service``, ``paradedb_18_connection``, ``paradedb_18_port`` (env: ``PARADEDB_18_PORT``)
* ``paradedb_image``, ``paradedb_service``, ``paradedb_port`` (env: ``PARADEDB_PORT``) — default image ``paradedb/paradedb:latest-pg18``
* ``paradedb_15_service``, ``paradedb_15_port`` (env: ``PARADEDB_15_PORT``)
* ``paradedb_16_service``, ``paradedb_16_port`` (env: ``PARADEDB_16_PORT``)
* ``paradedb_17_service``, ``paradedb_17_port`` (env: ``PARADEDB_17_PORT``)
* ``paradedb_18_service``, ``paradedb_18_port`` (env: ``PARADEDB_18_PORT``)

AlloyDB Omni
^^^^^^^^^^^^

* ``alloydb_omni_image``, ``alloydb_omni_service``, ``alloydb_omni_connection``, ``alloydb_omni_port`` (env: ``ALLOYDB_OMNI_PORT``) — default image ``google/alloydbomni:17``
* ``alloydb_omni_15_service``, ``alloydb_omni_15_connection``, ``alloydb_omni_15_port`` (env: ``ALLOYDB_OMNI_15_PORT``)
* ``alloydb_omni_16_service``, ``alloydb_omni_16_connection``, ``alloydb_omni_16_port`` (env: ``ALLOYDB_OMNI_16_PORT``)
* ``alloydb_omni_17_service``, ``alloydb_omni_17_connection``, ``alloydb_omni_17_port`` (env: ``ALLOYDB_OMNI_17_PORT``)
* ``alloydb_omni_image``, ``alloydb_omni_service``, ``alloydb_omni_port`` (env: ``ALLOYDB_OMNI_PORT``) — default image ``google/alloydbomni:17``
* ``alloydb_omni_15_service``, ``alloydb_omni_15_port`` (env: ``ALLOYDB_OMNI_15_PORT``)
* ``alloydb_omni_16_service``, ``alloydb_omni_16_port`` (env: ``ALLOYDB_OMNI_16_PORT``)
* ``alloydb_omni_17_service``, ``alloydb_omni_17_port`` (env: ``ALLOYDB_OMNI_17_PORT``)

Configuration
-------------
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ mongodb = []
mssql = []
mysql = []
oracle = []
postgres = ["psycopg>=3"]
postgres = []
redis = ["redis"]
spanner = []
valkey = []
Expand Down
Loading