Skip to main content
 首页 » 编程设计

python之Django DB 记录在第一次测试用例运行后消失

2025年05月04日34cmt

我正在开发一个基于 Django REST Framework 的项目。所以我需要为我的 REST API 编写一些测试用例。

我编写了一些从标准 DRF APITransactionTestCase 继承的基本类(我们称之为 BaseAPITestCase)。

在这个类中,我定义了 setUp 方法,我正在创建一些测试属于某些组的用户(我正在使用 UserFactory 用 FactoryBoy 编写)。

当我运行我的测试时,第一个(来自第一个 child 类的第一个测试用例方法)成功创建了一个具有指定组的用户,但其他的没有(其他测试用例方法在同一类(class))。

此时数据库中不存在用户组。似乎在每次新的测试用例运行时都从数据库中删除了现有记录。但是它是如何第一次起作用的呢?

我已经阅读了 Django 测试文档,但无法弄清楚为什么会发生...任何人都可以解释一下吗?

主要问题是我应该怎么做才能使这些测试有效?

我应该创建一次用户并将其存储在对象变量中吗?

我应该添加一些参数来保留用户组数据吗?

或者我应该将用户组添加到灯具中吗?在那种情况下,我怎样才能正确地创建这个夹具? (所有相关模型,例如权限和内容类型)

用于说明的简化源代码:

from rest_framework.test import APITransactionTestCase     
 
class BaseAPITestCase(APITransactionTestCase): 
 
    def setUp(self): 
        self.user = UserFactory( 
            username='login', 
            password='pass', 
            group_names=('admin', ) 
        ) 
        self.client = APIClient() 
        self.client.force_login(self.user) 
 
    def tearDown(self): 
        self.client.logout()     
 
class CampaignListTest(BaseAPITestCase): 
 
    def test_authorized_get(self): 
        # successfully gets user groups from DB 
 
    def test_authorized_post(self): 
        # couldn't find any groups 

请您参考如下方法:

TransactionTestCase是测试事务的测试用例。因此,它明确不使用事务来隔离测试,因为这会干扰正在测试的事务的行为。

为了隔离测试,TransactionTestCase 通过截断所有表来回滚数据库。这是不使用事务的最简单和最快的解决方案,但正如您所注意到的,这将删除所有 数据,包括在 post_migrate 信号接收器中生成的组。您可以在类上设置 serialized_rollback = True,在这种情况下,它将序列化对数据库的所有更改,并在每次测试后撤销这些更改。但是,这会明显变慢,并且通常会大大增加运行测试套件所需的时间,因此这不是默认设置。

TestCase 没有这个限制,所以它将每个测试用例包装在一个事务中,并将每个单独的测试包装在一个保存点中。使用事务和保存点回滚速度很快,并允许您保留事务或保存点开始时的数据。因此,最好尽可能使用 TestCase。

这扩展到 DRF 的 APITransactionTestCase 和 APITestCase,它们只是继承自 Django 的测试用例。