简体   繁体   English

与其他测试用例一起运行时,Django单元测试失败

[英]Django unit tests failing when run with other test cases

I'm getting inconsistent behavior with Django unit tests. 我与Django单元测试的行为不一致。 On my development machine using sqlite, if I run tests on my two apps separately the tests pass, but if I run manage.py test to test everything at once, I start getting unit test failures consistently on two tests. 在我使用sqlite的开发机器上,如果我分别在我的两个应用程序上运行测试,则测试通过,但是如果我运行manage.py test来一次测试所有内容,我会在两次测试中始终获得单元测试失败。

On my staging server which uses Postgres, I have a particular test that works when testing it individually (eg manage.py test MyApp.tests.MyTestCase.testSomething ), but fails when running the entire test case (eg manage.py test MyApp.tests.TestCase ). 在我使用Postgres的登台服务器上,我有一个特定的测试在单独测试时有效(例如manage.py test MyApp.tests.MyTestCase.testSomething ),但在运行整个测试用例时失败(例如manage.py test MyApp.tests.TestCase )。

Other related StackOverflow questions seem to have two solutions: 其他相关的StackOverflow问题似乎有两个解决方案:

  1. Use Django TestCase's instead of the Python equivalent 使用Django TestCase而不是Python等价物
  2. Use TransactionTestCase's to make sure the database is cleaned up properly after every test. 使用TransactionTestCase确保在每次测试后正确清理数据库。

I've tried both to no avail. 我试过两个都无济于事。 Out of frustration, I also tried using django-nose instead, but I was seeing the same errors. 出于挫折感,我也尝试使用django-nose,但我看到了同样的错误。 I'm on Django 1.6. 我在Django 1.6上。

Besides using TestCase for all your tests, you need to make sure you tear down any patching that was done in your setup methods: 除了在所有测试中使用TestCase之外,还需要确保删除在设置方法中完成的任何修补:

def setUp(self):
    self.patcher = patch('my.app.module')

def tearDown(self):
    self.patcher.stop()

I just spent all day debugging a similar problem. 我只花了一整天调试类似的问题。 In my case, the issue was as follows. 就我而言,问题如下。

In one of my view functions I was using the Django send_mail() function. 在我的一个视图函数中,我使用的是Django send_mail()函数。 In my test, rather than having it send me an email every time I ran my tests, I patch ed send_mail in my test method: 在我的测试,而不是它的每一个我跑我的测试时间发邮件给我,我patchsend_mail在我的测试方法:

from mock import patch
...

def test_stuff(self):
    ...

    with patch('django.core.mail.send_mail') as mocked_send_mail:

    ...

That way, after my view function is called, I can test that send_mail was called with: 这样,在调用我的视图函数后,我可以测试调用send_mail

self.assertTrue(mocked_send_mail.called)

This worked fine when running the test on its own, but failed when run with other tests in the suite. 这在单独运行测试时工作正常,但在套件中使用其他测试运行时失败。 The reason this fails is that when it runs as part of the suite other views are called beforehand, causing the views.py file to be loaded, causing send_mail to be imported before I get the chance to patch it. 这个失败的原因是当它作为套件的一部分运行时,事先调用其他视图,导致加载views.py文件,导致我有机会patch之前导入send_mail So when send_mail gets called in my view, it is the actual send_mail that gets called, not my patched version. 因此,当在我的视图中调用send_mail时,它是被调用的实际send_mail ,而不是我的修补版本。 When I run the test alone, the function gets mocked before it is imported, so the patched version ends up getting imported when views.py is loaded. 当我单独运行测试时,该函数在导入之前会被模拟,因此修补后的版本最终会在加载views.py时导入。 This situation is described in the mock documentation , which I had read a few times before, but now understand quite well after learning the hard way... 这种情况在模拟文档中有所描述,我之前已经阅读了几次,但是在学习了很多方法后现在理解得很好......

The solution was simple: instead of patching django.core.mail.send_mail I just patched the version that had already been imported in my views.py - myapp.views.send_mail . 解决方案很简单:我只修补了我在views.py - myapp.views.send_mail导入的版本,而不是修补django.core.mail.send_mail In other words: 换一种说法:

with patch('myapp.views.send_mail') as mocked_send_mail:
...

This took me a long time to debug, so I thought I would share my solution. 这花了我很长时间来调试,所以我想我会分享我的解决方案。 I hope it works for you too. 我希望它对你也有用。 You may not be using mocks, in which case this probably won't help you, but I hope it will help someone. 您可能没有使用模拟,在这种情况下,这可能对您没有帮助,但我希望它能帮到某些人。

I had the same thing happening today with a series of tests. 通过一系列测试,我今天也发生了同样的事情。 I had 23 regular django.test.TestCase tests and then one django.contrib.staticfiles.testing.StaticLiveServerTestCase test. 我有23个常规的django.test.TestCase测试,然后是一个django.contrib.staticfiles.testing.StaticLiveServerTestCase测试。 It was that final test that would always fail when ran with the rest of them but pass on its own. 这是最后的测试,当与其余的一起运行时总会失败但是自己传递。

Solution

In the 23 regular TestCase tests I really had implemented a subclass of the regular TestCase so that I could provide some common functionality specific to my application to the tests. 在23个常规TestCase测试中,我确实实现了常规TestCase的子类,以便我可以为测试提供特定于我的应用程序的一些常用功能。 In the tearDown methods I had failed to call the super method. tearDown方法中,我没有调用super方法。 Once I called the super method in the tearDown method, it worked. 一旦我在tearDown方法中调用了super方法,它就可以工作了。 So the lesson here was to check to make sure you are cleaning up your methods. 所以这里的教训是检查以确保你正在清理你的方法。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM