postgresqldockerpytest-django

Database is not cleaned up after each test in pytest-django


I have a problem with pytest-django with a Postgres database in docker. Problem is that pytest does not delete the data after adding it to the database. And they are visible when you run the same test again. And I don't know if it's the fault of the pytest, docker or database configuration :(

@pytest.fixture
def django_db_setup():
    settings.DATABASES['default'] = {
        'ENGINE': 'django.db.backends.postgresql',
        'HOST': 'postgres',
        'NAME': 'name',
    }
@pytest.mark.django_db
@pytest.mark.parametrize("parm1,parm2,expected1,expected2", [
    (
            '000-01', 'NEW', 'NEW', '000-01'
    ),
    (
            '000-02', 'NEW2', 'NEW2', '000-02'
    ),

])
def test_add_model(parm1,parm2,expected1,expected2):
    obj = AddModel(
        field1=parm1, field2=parm2
    )
    new = obj.create()
    assert new.field1 == expected1
    assert new.field2 == expected2

Rerunning this test gives the error duplicate key value violates unique constraint


Solution

  • You're just missing transaction=True here:

    @pytest.mark.django_db(transaction=True)
    

    It's possible that you don't want to delete the data after inserting it, what you want is to run tests in transactions (which has the same outcome)

    https://pytest-django.readthedocs.io/en/latest/database.html#testing-transactions

    Testing transactions

    Django itself has the TransactionTestCase which allows you to test transactions and will flush the database between tests to isolate them. The downside of this is that these tests are much slower to set up due to the required flushing of the database. pytest-django also supports this style of tests, which you can select using an argument to the django_db mark:

    @pytest.mark.django_db(transaction=True)
    def test_spam():
        pass  # test relying on transactions
    

    EDIT: It's also possible that you don't want to reuse the testing database between runs and would prefer to create a new one every time:

    https://pytest-django.readthedocs.io/en/latest/database.html#reuse-db-reuse-the-testing-database-between-test-runs

    I think the former is probably what you want, rather than the latter, though