how install postgres extension with pytest-django?
Asked Answered
F

4

5

I would like pytest-django to install a Postgres extension when it creates a test database. I've been mucking with conftest.py to try to get this to work, but I'm stuck.

My conftest.py is at the top level of my project (same directory as manage.py), and contains:

from django.db import connection
import pytest_django
@pytest.fixture(scope='session')
def django_db_setup(*args, **kwargs):
    pytest_django.fixtures.django_db_setup(*args, **kwargs)
    cursor = connection.cursor()
    cursor.execute("create extension pg_trgm")

But when I run it, I get:

_pytest.vendored_packages.pluggy.PluginValidationError: unknown hook 'pytest_django' in plugin <module 'conftest' from '/path/to/my/conftest.py'>
Fuqua answered 30/1, 2017 at 15:55 Comment(1)
It would be better to just migrate the extension in (using RunSQL), so it's there in both test and production databases.Misinterpret
V
8

You could use the pre_migrate signals. For example:

from django.db.models.signals import pre_migrate
from django.apps import apps

def app_pre_migration(sender, app_config, **kwargs):

    cur = connection.cursor()
    cur.execute('CREATE EXTENSION IF NOT EXISTS pg_trgm;')

pre_migrate.connect(app_pre_migration, sender=apps.get_app_config('app'))

I hope this could help you.

Vermicelli answered 22/5, 2017 at 16:9 Comment(0)
C
1

I've been trying to accomplish the same thing, and got this working (in conftest.py):

@pytest.fixture(scope="session")
def django_db_setup(django_db_setup, django_db_blocker):
    """Test session DB setup."""
    with django_db_blocker.unblock():
        with connection.cursor() as cursor:
            cursor.execute("CREATE EXTENSION IF NOT EXISTS citext;")

The key here is that you have to name your custom fixture with the same name as the standard pytest-django fixture, but also include the default fixture as an argument. This is the way to run the standard fixture, rather than importing and calling it. I also found this failed unless I ran django_db_blocker.unblock().

Crowe answered 19/3, 2020 at 20:58 Comment(1)
This didn't work for me, the exception caused by the CITEXT extension not being installed was occurring during the call of pytest.fixtures.django_db_setup() so cursor.execute() didn't even get called. I posted an alternative solution below.Boyle
B
1

I finally solved this using the django_test_environment fixture.

import pytest
from django.db import connection
from django.db.models.signals import pre_migrate
from django.apps import apps


def _pre_migration(sender, app_config, **kwargs):
    with connection.cursor() as cursor:
        cursor.execute("CREATE EXTENSION IF NOT EXISTS pg_trgm;")


@pytest.fixture(autouse=True, scope="session")
def django_test_environment(django_test_environment):
    pre_migrate.connect(_pre_migration, sender=apps.get_app_config("my_app"))
Bille answered 19/5 at 1:15 Comment(0)
B
0

An alternative solution would be to add the extension to the postgres template database. This means that all test databases created using the CREATE DATABASE command will have the specified extension:

psql -d template1 -c 'CREATE EXTENSION IF NOT EXISTS pg_trgm;'

Now whenever pytest creates a test database, the pg_trgm extension will be installed before migrations are run.

Boyle answered 1/8, 2022 at 12:26 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.