pytest-django:测试后无法删除数据库

时间:2018-12-25 13:40:16

标签: python django database pytest pytest-django

我有一个Django应用程序,我正在尝试使用pytestpytest-django对其进行测试。但是,很多时候,当测试完成运行时,我收到错误的消息,指出数据库删除失败:DETAIL: There is 1 other session using the database.

基本上,我可以将其缩小到的最小测试代码是:

@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))

每一次测试都会因上述错误而失败。我做错什么了吗?或者我该如何解决?

我正在使用的数据库是PostgreSQL 9.6。

1 个答案:

答案 0 :(得分:0)

我将其发布为答案,因为我需要发布大量代码并且因为此功能有效。但是,对我来说,这似乎是一个肮脏的技巧,如果更好,我将非常乐意接受其他人的回答。 这是我的解决方案:基本上,将可将所有用户从给定db中踢出的原始sql添加到销毁db的方法中。并通过monkeypatching做到这一点。为了确保在测试之前进行猴子修补,请将其作为自动使用的夹具添加到根conftest.py文件中:

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

请注意,启动代码可能取决于您的数据库引擎,并且在不同的Django版本中,需要进行猴子修补的方法可能有所不同。