我在Django 1.5中测试过这些条件:
TestCase
时但是当使用python manage.py test
运行完整的测试套件时,它会失败。为什么会发生这种情况?
异常测试使用django.test.Client
POST
将某些数据发送到端点,然后测试检查对象是否已成功更新。其他一些应用可以修改测试客户端或数据本身吗?
我尝试了一些打印调试,我看到所有数据都按预期发送和接收。特定的失败是当我尝试从db中获取要更新的对象时引发的不存在的异常。奇怪的是,在异常处理程序本身中,我可以查询该类型的所有对象,并看到目标对象确实存在。
编辑:
当我发现我正在id
和User
而不是id
和UserProfile
查询目标对象时,我的问题已得到解决,但它已经解决了仍然让我感到困惑的是,这会在某些情况下起作用,但在其他情况下会失败。
我还发现测试会因python manage.py test auth <myapp>
答案 0 :(得分:17)
听起来你的问题不涉及嘲讽,但我只花了一整天调试一个有类似症状的问题,而你的问题是我在寻找解决方案时出现的第一个问题,所以我想分享一下这里的解决方案,以防它对其他人有用。就我而言,问题如下。
我有一个单独的测试可以隔离通过,但是作为我的完整测试套件的一部分运行时会失败。在我的一个视图函数中,我使用的是Django send_mail()
函数。在我的测试中,我没有在每次运行测试时向我发送电子邮件,而是在我的测试方法中patch
编辑send_mail
:
from mock import patch
...
def test_stuff(self):
...
with patch('django.core.mail.send_mail') as mocked_send_mail:
...
这样,在调用我的视图函数后,我可以测试send_mail
被调用:
self.assertTrue(mocked_send_mail.called)
这在单独运行测试时工作正常,但在套件中运行其他测试时失败。失败的原因是,当它作为套件的一部分运行时,其他视图会事先被调用,从而导致views.py
文件被加载,导致send_mail
在之前导入有机会patch
它。因此,在我的视图中调用send_mail
时,实际的send_mail
会被调用,而不是我的修补版本。当我单独运行测试时,该函数在导入之前被模拟,因此修补后的版本最终会在加载views.py
时导入。这种情况在mock documentation中有所描述,我之前已经阅读了几次,但是在学习了很多方法之后现在明白了......
解决方案很简单:我只是修补了django.core.mail.send_mail
- views.py
中已导入的版本,而不是修补myapp.views.send_mail
。换句话说:
with patch('myapp.views.send_mail') as mocked_send_mail:
...
答案 1 :(得分:1)
另一种可能性是你在测试类的setUp中断开了信号,并且没有在tearDown中重新连接。这解释了我的问题。
答案 2 :(得分:1)
有很多非确定性可以来自涉及数据库的测试。
例如,除非您按顺序执行,否则大多数数据库都不提供确定性选择。这导致了奇怪的行为,当星星对齐时,数据库以不同于您预期的顺序返回事物,并且测试看起来像
result = pull_stuff_from_database()
assert result[0] == 1
assert result[1] == 2
将失败,因为result[0] == 2 and result[1] == 1
。
奇怪的不确定行为的另一个来源是id自动增量以及某种类型的排序。
假设每个测试都会创建两个项目,并在执行断言之前按项目名称进行排序。单独运行时,“项目1”和“项目2”正常工作并通过测试。但是,当您运行整个套件时,其中一个测试会生成“第9项”和“第10项”。 “项目10”在“项目9”之前排序,因此您的测试失败,因为订单被翻转。
答案 3 :(得分:0)
试试这个来帮助你调试:
./manage.py test --reverse
在我的情况下,我意识到一个测试正在更新某些数据,这会导致以下测试失败。
答案 4 :(得分:0)
因此,我首先阅读@elethan的答案,然后说“嗯,这当然不是我的问题,我没有修补任何东西”。但是事实证明,我确实是在另一个测试套件中修补了一个方法,在其余的测试运行期间,该方法始终处于永久性修补状态。
我正在进行这种事情;
send_comment_published_signal_mock = MagicMock()
comment_published_signal.send = send_comment_published_signal_mock
您可以看到如果在运行测试套件后未清除某些内容,这将是一个问题的原因。在我的情况下,解决方案是使用有用的with
来限制范围。
signal = 'authors.apps.comments.signals.comment_published_signal.send'
with patch(signal) as comment_published_signal_mock:
do_your_test_stuff()
这是最简单的部分,在您知道要查找的位置之后。有罪测试可能来自任何地方。解决方案是将失败的测试和其他测试一起运行,直到找到原因为止,然后再次逐个模块逐个缩小范围。
类似的东西
./manage.py test A C.TestModel.test_problem
./manage.py test B C.TestModel.test_problem
./manage.py test D C.TestModel.test_problem
然后递归返回,例如,如果B
是有问题的孩子;
./manage.py test B.TestModel1 C.TestModel.test_problem
./manage.py test B.TestModel2 C.TestModel.test_problem
./manage.py test B.TestModel3 C.TestModel.test_problem
此answer为所有这些提供了很好的解释。
这个答案是在django
的上下文中,但实际上可以应用于任何python测试。
祝你好运。
答案 5 :(得分:0)
这也在我身上发生。
分别运行测试时,它们通过了,但是使用./manage.py test
运行所有测试均失败了。
我的问题是因为我有一些测试是从unittest.TestCase
继承而来的,而不是从django.test.TestCase
继承的,所以某些测试失败了,因为以前的测试在数据库中有寄存器。
使所有测试都继承自django.test.TestCase
之后,这个问题就消失了。