lundi 19 octobre 2020

pytest PostgreSQL - different fixture for two environments to set up test DB either locally or on CI

I am trying to have pytest setup a test database automatically based on whether it runs locally or on our CI server. Please see below the code. For this I created a CLI option.

When this option is passed I want pytest-postgresql to use the postgresql_noproc_factory (GitHub README). So I created a fixture that selects the factory to be used. However, if I understand correctly, this creates a "fixture of a fixture" so when it is injected into setup_database it doesn't work and gives an error message:

    def dbcreator():
>       return postgresql_my.cursor().connection
E       AttributeError: 'function' object has no attribute 'cursor'

Do you possibly know how this could be done with pytest? How do I make pytest instantiate the nested fixture so that it configures the right PostgreSQL engine?

import os
import tempfile

from psycopg2.extensions import connection
import pytest
from pytest_postgresql import factories
from sqlalchemy import create_engine
from sqlalchemy.engine import Engine


def pytest_addoption(parser):
    parser.addoption(
        "--remote-psql", action="store_true", help="Run it in environment where PSQL runs on network."
    )


@pytest.fixture(scope="session")
def cmdopt_remote_psql(request):
    return request.config.getoption("--remote-psql")


# Using the postgresql factories to create a postgresql fixture instance
socket_dir = tempfile.TemporaryDirectory()
postgresql_proc_factory = factories.postgresql_proc(port=None, unixsocketdir=socket_dir.name)
postgresql_noproc_factory = factories.postgresql_noproc()


@pytest.fixture(scope="session")
def postgresql_my(cmdopt_remote_psql):
    if cmdopt_remote_psql:
        return factories.postgresql("postgresql_noproc_factory")
    else:
        return factories.postgresql("postgresql_proc_factory")


@pytest.fixture(scope="function", autouse=True)
def setup_database(postgresql_my: connection) -> Engine:
    """
    See https://medium.com/@geoffreykoh/fun-with-fixtures-for-database-applications-8253eaf1a6d
    """
    def dbcreator():
        return postgresql_my.cursor().connection

    engine = create_engine("postgresql+psycopg2://", creator=dbcreator)
    return engine

Aucun commentaire:

Enregistrer un commentaire