我的单元测试和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时不会成功)
看来自动提交与此无关。在
^{} 类将测试封装在两个原子块中。因此,如果从}。在
TestCase
继承,则不可能使用transaction.set_autocommit()
或{正如文档所说,如果您正在测试特定的数据库事务行为,那么应该使用
TransactionTestCase
。在将
autocommit = transaction.set_autocommit(False)
放在send
函数内感觉不对。禁用事务可能是出于测试目的而在这里完成的,但经验法则是将测试逻辑保持在代码之外。在正如@Alasdair指出的,django docs声明“出于性能原因,Django的TestCase类也将每个测试封装在事务中。”
从您的问题中不清楚您是否在测试特定的数据库事务逻辑,如果是这样,那么@Alasdair使用
TransactionTestCase
的答案就是正确的方法。在否则,从
send
函数内的stuff
周围删除事务上下文开关应该会有所帮助。在既然您提到
pytest
作为您的测试运行程序,我也建议您使用pytest。pytestdjango插件具有一些很好的特性,比如使用markers,有选择地将一些测试设置为需要事务。在如果安装一个插件太多了,那么您可以使用自己的
^{pr2}$transaction manage
fixture。像您的
test_send
将需要no_transaction
夹具。在相关问题 更多 >
编程相关推荐