【问题标题】:Django test runner not respecting unittest.TestCase?Django 测试运行器不尊重 unittest.TestCase?
【发布时间】:2020-08-10 20:57:23
【问题描述】:

对于我的一项功能测试,我决定使用unittest.TestCase 而不是 Django 测试类,因为在清理测试以在测试本身中直接访问我的本地开发数据库时很方便。

像我预期的那样单独运行测试通过:

$ python manage.py test functional_tests.test_functionality
System check identified no issues (0 silenced).
...
----------------------------------------------------------------------
Ran 3 tests in 0.040s

OK

但是,当我尝试同时运行所有测试时,该测试特别出错,抱怨对象 DoesNotExist,好像它正在使用 Django 测试数据库:

$ python manage.py test functional_tests
Creating test database for alias 'default'...
System check identified no issues (0 silenced).
..................E..
======================================================================
ERROR: some_functional_test (functional_tests.test_functionality.FunctionalTest)
----------------------------------------------------------------------
Traceback (most recent call last):

... etc.

app.models.Object.DoesNotExist: Object matching query does not exist.

----------------------------------------------------------------------
Ran 21 tests in 0.226s

FAILED (errors=1)
Destroying test database for alias 'default'...

当 Django 的测试数据库中不存在 Objects 时,我认为错误是我尝试使用 Object.objects.latest('created')

有什么方法可以防止 Django 将所有测试包装在与测试运行器有关的任何东西中,从而阻止我的测试直接访问 Object

【问题讨论】:

  • 如果一些额外的上下文有帮助,我正在对本地服务器上运行的 API 端点运行功能测试。我正在测试一个 create 方法,并且我试图避免必须针对端点请求 DELETE 以清理由测试创建的测试记录。我不太担心意外的数据丢失,因为测试是针对本地开发数据库运行的

标签: python django functional-testing


【解决方案1】:

先做一点解释。

默认情况下,当您运行./manage.py test django test-runner 时,会执行几个步骤,包括创建测试数据库(test_ 前缀为来自app settings 的每个数据库名称)、运行迁移和销毁测试数据库(有关 runner 的更多详细信息步骤可以找到here)

关于django如何处理测试数据库的一个很好的解释here


在您的情况下,当您单独运行 unittest.TestCase no 时会创建测试数据库:

$ python manage.py test functional_tests.test_functionality
System check identified no issues (0 silenced).
...
----------------------------------------------------------------------
Ran 3 tests in 0.040s

OK

( ^没有关于创建测试数据库的日志)

那是因为没有调用django.test.TestCase。我们可以从sources看到(处女unittest.TestCase没有databases属性,当django.TestCaseit has时)

但是当您调用整个模块 (python manage.py test functional_tests) 时,您似乎在套件中有一些 django.test.TestCase 测试,所以这就是创建新测试数据库的原因:

$ python manage.py test functional_tests
Creating test database for alias 'default'...  # <-- THIS ONE
##<skipped for readability>
Destroying test database for alias 'default'...

正如你提到的,测试失败是因为没有为它们准备好的对象。


解决方案

在这一点上,我看到几个选项来解决这个问题。

  1. 为测试明确准备测试数据(通过fixtures 或在测试或设置中手动),以便它们独立于数据库的当前状态

  2. 明确使用所需的数据库。

    使用--keepdb 选项运行测试(即./manage.py test --keepdb,它将使用现有数据库并且不会在测试运行后销毁它)并在应用程序设置中将test database name 设置为working database(在这种情况下它将不为测试数据库附加 test_ 前缀)

  3. 既然你不想使用django.TestCase,那么就不要使用它们了吗?将它们替换为unittest.TestCase,它不会创建测试数据库

【讨论】:

  • 感谢您提供的信息。承认 Django 处理测试用例的方式,我的问题是关于如何强制特定测试在测试数据库/测试事务之外运行。在这种特殊情况下,我的意图是让测试针对我的本地数据库运行,而不是包装在 Django 事务中。
  • 现在我想我明白你的要求了。我稍后会更新我的答案,谢谢你的澄清
  • @Derek 看起来我对你的情况有所了解,我已经完全更新了我的答案,请看一下
猜你喜欢
  • 2013-04-05
  • 1970-01-01
  • 2017-04-03
  • 1970-01-01
  • 1970-01-01
  • 2020-08-26
  • 1970-01-01
  • 2011-01-03
相关资源
最近更新 更多