问题描述
对于我的一项功能测试,我决定使用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的测试数据库中不存在Object.objects.latest('created')
而导致我尝试使用Object
。
是否有某种方法可以阻止Django将所有测试包装在测试运行程序中,从而阻止我的测试直接访问Object
?
解决方法
首先进行一些解释。
默认情况下,当您运行./manage.py test
时,django test-runner会执行一些步骤,包括创建测试数据库(在app settings的每个数据库名称前加上test_
前缀),运行迁移并销毁测试数据库(有关跑步者步骤的更多详细信息,请参见here)
在您单独运行unittest.TestCase
的情况下,没有会创建测试数据库:
$ 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看到它(django.TestCase it has时,原始unittest.TestCase
不具有databases
属性)
但是,当您调用整个模块(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'...
正如您提到的,测试失败是因为没有准备好的对象。
解决方案
这时我看不到解决方案。
-
为测试明确准备测试数据(通过fixtures或在测试或设置中手动进行准备),以便它们独立于数据库的当前状态
-
明确使用所需的数据库。
使用
--keepdb
选项运行测试(即./manage.py test --keepdb
,它将使用现有数据库,并且在测试运行后不会销毁它),并在应用设置中将test database name设置为{{3 }}(在这种情况下,它不会为测试数据库添加test_
前缀) -
由于您不想使用
django.TestCase
,所以根本不使用它们吗?将其替换为unittest.TestCase
,它将不会创建测试数据库