【问题标题】:Django unit tests failing when run with other test cases与其他测试用例一起运行时,Django 单元测试失败
【发布时间】:2013-12-09 22:03:53
【问题描述】:

我的 Django 单元测试行为不一致。在我使用 sqlite 的开发机器上,如果我分别对我的两个应用程序运行测试,则测试通过,但如果我运行 manage.py test 一次测试所有内容,我开始在两个测试中始终遇到单元测试失败。

在我使用 Postgres 的登台服务器上,我有一个特定的测试在单独测试时有效(例如manage.py test MyApp.tests.MyTestCase.testSomething),但在运行整个测试用例时失败(例如manage.py test MyApp.tests.TestCase)。

其他相关的StackOverflow问题似乎有两种解决方案:

  1. 使用 Django TestCase 代替 Python 等效项
  2. 使用 TransactionTestCase 确保每次测试后都正确清理数据库。

我都试过了,都没有用。出于沮丧,我也尝试使用 django-nose 代替,但我看到了同样的错误。我在 Django 1.6 上。

【问题讨论】:

  • 究竟是什么错误?
  • 如果不查看整个单元测试,该错误将没有多大意义,但基本上测试失败,说明应该在执行 POST 后创建的对象不存在。
  • @mathew 你能发布你的整个单元测试,以及完整的错误吗?您是否使用 django TestCase 进行所有测试?你有泄露数据吗? django 的 TestCase 有什么好处是它在每次测试后都会清理你的数据库

标签: django unit-testing


【解决方案1】:

除了对所有测试使用 TestCase 之外,您还需要确保拆除在您的设置方法中完成的所有补丁:

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

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

【讨论】:

  • “my.app.module”是什么意思?
【解决方案2】:

我只是花了一整天时间调试一个类似的问题。就我而言,问题如下。

在我的一个视图函数中,我使用了 Django send_mail() 函数。在我的测试中,我没有在每次运行测试时都给我发送电子邮件,而是在我的测试方法中patched 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:
...

这花了我很长时间来调试,所以我想我会分享我的解决方案。我希望它也适合你。您可能没有使用模拟,在这种情况下,这可能对您没有帮助,但我希望它会对某人有所帮助。

【讨论】:

    【解决方案3】:

    我今天通过一系列测试发生了同样的事情。我进行了 23 次常规 django.test.TestCase 测试,然后进行了一次 django.contrib.staticfiles.testing.StaticLiveServerTestCase 测试。当与其他人一起运行时,最终测试总是会失败,但会自行通过。

    解决方案

    在 23 个常规 TestCase 测试中,我确实实现了常规 TestCase 的子类,以便我可以为测试提供一些特定于我的应用程序的通用功能。在tearDown 方法中,我未能调用超级方法。一旦我在tearDown 方法中调用了超级方法,它就起作用了。所以这里的教训是检查以确保你正在清理你的方法。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-03-20
      • 1970-01-01
      • 2015-05-31
      • 1970-01-01
      • 1970-01-01
      • 2022-10-13
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多