BigBoy1337
BigBoy1337

Reputation: 4963

How to use pytest with Django?

When I use pytest with Django, no test_<db_name> is created.

Minimum reproducible example:

In Django project:

./manage.py startapp testing_pytest

in models.py

class Snippet(models.Model):

    created = models.DateTimeField(auto_now_add=True)
    title = models.CharField(max_length=100, blank=True, default='')
    code = models.TextField()
    linenos = models.BooleanField(default=False)
    external_id = models.CharField(max_length=100, default='0')

    class Meta:
        ordering = ['created']

then create a db named loc_db in Postgres,

./manage.py makemigrations
./manage.py migrate 

in serializers.py

class BulkUpdateOrCreateListSerializer(serializers.ListSerializer):
    def create(self, validated_data):
        result = [self.child.create(attrs) for attrs in validated_data]
        try:
            res = self.child.Meta.model.objects.bulk_create(result)
        except IntegrityError as e:
            raise ValidationError(e)
        return res

class SnippetSerializer(serializers.ModelSerializer):
    class Meta:
        model = Snippet
        fields = ['id','title', 'code', 'linenos']
        read_only_fields = ['id']
        list_serializer_class = BulkUpdateOrCreateListSerializer

    def create(self, validated_data):
        instance = Snippet(**validated_data)
        if isinstance(self._kwargs["data"], dict):
            instance.save()
        return instance

in views.py

class SnippetGetView(generics.ListAPIView):
    serializer_class = SnippetSerializer
    queryset = Snippet.objects.all()

class SnippetUpdateView(generics.ListCreateAPIView):
    queryset = Snippet.objects.all()
    serializer_class = SnippetSerializer
    def get_serializer(self, *args, **kwargs):
        if isinstance(kwargs.get("data", {}), list):
            kwargs["many"] = True
        return super(SnippetUpdateView, self).get_serializer(*args, **kwargs)

in tests.py

@pytest.fixture(scope='session',autouse=True)
def my_faker():
    return Faker()

@pytest.fixture(scope='session',autouse=True)
def factory():
    return APIRequestFactory()

@pytest.fixture(scope='session',autouse=True)
def snippets():
    snippets = []
    for i in range(TEST_SIZE):
        snippets.append({'title':'snippet'+str(i),'code':'print(True)','linenos':False,'external_id':'1'})
    return snippets

@pytest.mark.django_db
def test_update_snippet(factory,snippets):
    request = factory.post('/add-snippets/',snippets)
    view = SnippetUpdateView.as_view()
    response = view(request)
    response.render()
    assert status.is_success(response.status_code)

and in <project_name>/settings.py

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.postgresql_psycopg2',
        'NAME': 'loc_db',
        'USER': '<some name>',
        'PASSWORD': '<some pass>',
        'HOST': 'localhost',
        'PORT': '5432',
    }
}

and in pytest.ini

[pytest]
DJANGO_SETTINGS_MODULE = <project_dir>.settings
python_files = tests.py test_*.py *_tests.py

I was hoping that running pytest when those tests are executed would create test_loc_db and then save that array of snippets doing a bulk create. However no test_db is created. Instead it just passes that test. But im not sure why. Where are those snippets being saved?

Upvotes: 2

Views: 839

Answers (1)

AzyCrw4282
AzyCrw4282

Reputation: 7744

I don't think pytest has such a feature, where the db transactions are outputted to a file. I have also checked the docs and it doesn't seem like that feature exists.

It normally (and as in your behaviour) just outputs whether the test has passed or not. The final line looks something like this

============================== <N Tests> passed in 0.27s ==============================

Failed tests are also reported on the test console. The closest mention of any kind of db saving is the following

This data will be available to tests marked with the pytest.mark.django_db() mark, or tests which use the db fixture. The test data will be saved in the database and will not be reset.

You can see that from here. You can also look into Django's test framework to see if it's supported with that.

Upvotes: 1

Related Questions