Django pytest for django_filters FilterSet

33 Views Asked by At

I used unittest.TestCase class with the decorator @pytest.mark.django_db() in trying to test a django_filters.FilterSet class. In the setUp method, I created new data instances that would later on be used for testing.

Because there had been model restructuring, I used Django ORM to query data and manipulate them in one of my migration files. The problem is that when pytest is going through the migration files (to create the test database), the ORM is using the default database instead of test_default. This results to the ORM querying fields that do not exist in the latest version of the models.

Note that the model of the filter set is not even the model used in the migration where the error is occuring.

Here's a sample of my models:

# module1/models.py

from django.contrib.sites.models import Site
from django.db.models import Model, OneToOneField


class Model1(Model):
    model2 = OneToOneField(Site)
    ...
# module2/models.py

from django.db.models import ForeignKey, Model


class Model1(Model):
    ...


class Model2(Model):
    model1 = ForeignKey(Model1, ...)

Here's the migration file:

# 0007_auto_xxxxxxxx_xxxx.py

from __future__ import unicode_literals
from django.db import connections, migrations


def foo(apps, _schema_editor):
    Model1 = apps.get_model("module1", "Model1")
    Site = apps.get_model("sites", "Site")

    for instance in Model1.objects.all():  # uses default database
        instance.model2, _created = Site.objects.get_or_create(...)
        instance.save()


class Migration(migrations.Migration):
    dependencies = [
        ("sites", "0002_alter_domain_unique"),
        ("module1", "0006_auto_xxxxxxxx_xxxx"),
    ]

    operations = [
        migrations.RunPython(foo, migrations.RunPython.noop),
    ]

Here's a sample of the unit test:

import pytest
from unittest import TestCase
from src.module2.models import Model1, Model2
from src.module2.filters import Model2Filter


@pytest.mark.django_db()
class FilterTestCase(TestCase):
    def setUp(self) -> None:
        model1_instance = Model1.objects.create(...)
        Model2.objects.create(model1=model1_instance, ...)
        Model2.objects.create(model1=model1_instance, ...)
        Model2.objects.create(model1=model1_instance, ...)
        Model2.objects.create(model1=model1_instance, ...)
        Model2.objects.create(model1=model1_instance, ...)


    def test_filter_by_field1_true(self) -> None:
        filter_set = Model2Filter(
            {"field1", True},
            queryset=Model2.objects.all(),  # why I need test database
        )
        assert ...

I've tried pointing the test database to an existing database (stackoverflow/48096745). This removes the error during migration but makes my query get data not created during TestCase.setUp.

I want to stick with using the use of test_default to isolate the data during testing, but I want all the queries during pytest to use it including the ones in migration files.

As much as possible, I also want to stick with the use of Django ORM.

0

There are 0 best solutions below