使用TransactionTestCase和pytes测试失败

2024-10-04 11:28:36 发布

您现在位置:Python中文网/ 问答频道 /正文

我的单元测试和django管理事务的方式有问题。在

在我的代码中我有一个函数:

def send():
    autocommit = transaction.set_autocommit(False)
    try:
         # stuff
    finally:
         transaction.rollback()
         transaction.set_autocommit(autocommit)

在我的测试中,我有:

^{pr2}$

我遇到的问题是我的test_send成功通过了,但其他测试的80%都没有通过。在

其他测试的交易似乎失败了

顺便说一句,我正在使用py.测试运行我的测试

编辑: 当我只使用 myapp.test.test_模块.py它运行良好,所有3个测试都通过了,但当我运行所有测试时,大多数测试都失败了,将尝试生成一个测试应用程序

另外,我的所有测试都通过了django的默认测试运行器

编辑2: 下面是一个测试此问题的最小示例:

class ManagementTestCase(TransactionTestCase):

    def test_transfer_ubl(self, MockExact):
        pass

class TestTestCase(TestCase):

     def test_1_user(self):
         get_user_model().objects.get(username="admin")
         self.assertEqual(get_user_model().objects.all().count(), 1)

请记住,有一个数据迁移会添加一个“admin”用户(TestTestCase单独成功,但在之前运行managementtestcase时不会成功)

看来自动提交与此无关。在


Tags: djangopytestselfsend编辑getmodel
2条回答

^{}类将测试封装在两个原子块中。因此,如果从TestCase继承,则不可能使用transaction.set_autocommit()或{}。在

正如文档所说,如果您正在测试特定的数据库事务行为,那么应该使用TransactionTestCase。在

autocommit = transaction.set_autocommit(False)放在send函数内感觉不对。禁用事务可能是出于测试目的而在这里完成的,但经验法则是将测试逻辑保持在代码之外。在

正如@Alasdair指出的,django docs声明“出于性能原因,Django的TestCase类也将每个测试封装在事务中。”

从您的问题中不清楚您是否在测试特定的数据库事务逻辑,如果是这样,那么@Alasdair使用TransactionTestCase的答案就是正确的方法。在

否则,从send函数内的stuff周围删除事务上下文开关应该会有所帮助。在

既然您提到pytest作为您的测试运行程序,我也建议您使用pytest。pytestdjango插件具有一些很好的特性,比如使用markers,有选择地将一些测试设置为需要事务。在

pytest.mark.django_db(transaction=False)

如果安装一个插件太多了,那么您可以使用自己的transaction managefixture。像

^{pr2}$

您的test_send将需要no_transaction夹具。在

def test_send(no_transaction):
    send()

相关问题 更多 >