pytest-dev / pytest-dev/pytest-asyncio

[pytest-django] Database is not properly rolled back after async tests

Open
#226 9 comments 16 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

needsinfo
Dominant language
Python
Stars
1.7k
Forks
207
Avg merge
5h 35m
Merged PRs (30d)
9

Description

When using pytest-django's pytest.mark.django_db marker in conjunction with pytest.mark.asyncio, any writes to the database are not rolled back when the test completes and affect subsequent tests.

To test, I created a fresh django app, installed pytest-django and pytest-asyncio, created a simple model, and wrote two tests:

models.py:

from django.db import models

class MyModel(models.Model):
    my_field = models.TextField(null=True, blank=True)

test_app.py:

import pytest
from asgiref.sync import sync_to_async

from app.models import MyModel


@pytest.mark.django_db
@pytest.mark.asyncio
async def test_save_model_to_db():
    await sync_to_async(MyModel.objects.create)()


@pytest.mark.django_db
def test_check_if_model_present():
    assert MyModel.objects.count() == 0

Running pytest resulted in the first test succeeding and the second failing:

    @pytest.mark.django_db
    def test_check_if_model_present():
>       assert MyModel.objects.count() == 0
E       assert 1 == 0

At first I thought it might be due to how Django runs synchronous code from an asynchronous context. Maybe it was creating the instance in another transaction that pytest wasn't rolling back.

So, I updated the test code to set DJANGO_ALLOW_ASYNC_UNSAFE to "true" so I could remove the sync_to_async() wrapper around the create() call, ensuring the instance would be included created in the same thread and within pytest's transaction.

Unfortunately, the test failed for the same reason. This could be an issue with pytest-asyncio or compatibility with pytest-django.

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by reproducing the failure from the issue's test_app.py example with pytest, pytest-django, and pytest-asyncio. Verify whether the async test's database write remains visible to test_check_if_model_present; done means the second test passes with the write rolled back after the first test.

Written by the indexing model from the issue text.

Assessment

Tech stack
python
Domain
databases, testing-qa
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
38/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.