pytest-dev / pytest-dev/pytest-django

DB fails to clean up after tests, says db is used by another user

Open
#696 1 comment 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
Python
Stars
1.5k
Forks
367
PR merge metrics
No merged PRs in 30d

Description

This is basically a repost of my question from stackoverflow. I hope it will be more useful here.

I have a Django application, and I'm trying to test it using pytest and pytest-django. However, quite often, when the tests finish running, I get the error that the database failed to be deleted: DETAIL: There is 1 other session using the database.

Basically, the minimum test code that I could narrow it down to is:

@pytest.fixture
def make_bundle():
    a = MyUser.objects.create(key_id=uuid.uuid4())
    return a

class TestThings:
    def test_it(self, make_bundle):
        all_users = list(MyUser.objects.all())
        assert_that(all_users, has_length(1))

Every now and again the tests will fail with the above error. Is there something I am doing wrong? Or how can I fix this?

The database that I am using is PostgreSQL 9.6.

And here is the dirty fix I seem to have found for this:

def _destroy_test_db(self, test_database_name, verbosity):
    """
    Internal implementation - remove the test db tables.
    """
    # Remove the test database to clean up after
    # ourselves. Connect to the previous database (not the test database)
    # to do so, because it's not allowed to delete a database while being
    # connected to it.
    with self.connection._nodb_connection.cursor() as cursor:
        cursor.execute(
            "SELECT pg_terminate_backend(pg_stat_activity.pid) "
            "FROM pg_stat_activity "
            "WHERE pg_stat_activity.datname = '{}' "
                "AND pid <> pg_backend_pid();".format(test_database_name)
        )

        cursor.execute("DROP DATABASE %s"
                       % self.connection.ops.quote_name(test_database_name))


@pytest.fixture(autouse=True)
def patch_db_cleanup():
    creation.BaseDatabaseCreation._destroy_test_db = _destroy_test_db

Is there a better solution for the situation? Or is it a bug in pytest-django?

Contributor guide

Open the contributing guide

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 with Django's BaseDatabaseCreation._destroy_test_db entry point and pytest-django's test database teardown, using the minimal fixture and PostgreSQL 9.6 setup described in the issue to reproduce the failure. Compare the normal teardown path with the proposed monkey patch; done means the test database is cleaned up reliably without requiring that local patch.

Written by the indexing model from the issue text.

Assessment

Tech stack
django, postgresql, python
Domain
backend, databases, testing
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Needs clarification
Newbie friendliness
25/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.