Chris Curvey
Chris Curvey

Reputation: 10389

how install postgres extension with pytest-django?

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'>

Upvotes: 5

Views: 3474

Answers (4)

Scott Gigante
Scott Gigante

Reputation: 1635

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"))

Upvotes: 2

Melipone
Melipone

Reputation: 630

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.

Upvotes: 0

bjudson
bjudson

Reputation: 4083

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().

Upvotes: 1

lefterisnik
lefterisnik

Reputation: 157

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.

Upvotes: 8

Related Questions