Django 中单元测试的覆盖设置无法正常工作
Posted
技术标签:
【中文标题】Django 中单元测试的覆盖设置无法正常工作【英文标题】:Overriding Settings for unit tests in Django doesn't work properly 【发布时间】:2015-05-02 05:10:03 【问题描述】:我尝试对我的 Django 程序进行单元测试,我想检查我的 settings.py
文件中几个变量的几个值。
在文档中,“Overriding settings”部分描述了一种方法。但是,尽管我进行了所有尝试,但在测试运行时,我仍然无法在程序中提供更改。以下是我在一个最小示例上所做的总结:
首先,新建一个项目:
$ pyvenv virtualenv
$ cd virtualenv/
$ . bin/activate
(virtualenv) $ pip install django
(virtualenv) $ django-admin startproject myapp
(virtualenv) $ cd myapp/
然后,添加以下文件。
文件settings.py
...
TEST_VALUE = 'a'
文件tests.py
from django.test import TestCase
from myapp.settings import TEST_VALUE
class CheckSettings(TestCase):
def test_settings(self):
self.assertEqual(TEST_VALUE, 'a')
def test_modified_settings(self):
with self.settings(TEST_VALUE='b'):
self.assertEqual(TEST_VALUE, 'b')
当我运行测试时,我得到以下信息:
$ ./manage.py test
Creating test database for alias 'default'...
F.
======================================================================
FAIL: test_modified_settings (myapp.tests.CheckSettings)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/virtualenv/myapp/tests.py", line 12, in test_modified_settings
self.assertEqual(TEST_VALUE, 'b')
AssertionError: 'a' != 'b'
----------------------------------------------------------------------
Ran 2 tests in 0.001s
FAILED (failures=1)
Destroying test database for alias 'default'...
您可能已经注意到,TEST_VALUE
的原始值为'a'
,我尝试通过self.settings(TEST_VALUE='b')
对其进行修改...但是没有成功。
你可以通过一个空项目(Django 是 1.6.5)来尝试。
那么,为了让它正常工作,我缺少什么?
【问题讨论】:
只是猜测,但也许您必须通过settings
访问设置——例如from testing_settings import settings
,然后在你的断言中使用settings.TEST_VALUE
。更改已导入的值似乎有点太神奇了。
实际上是from django.conf import settings
。
@IsmailBadawi:该死,你是对的!!!总结一下,我是通过from myapp.settings import TEST_VALUE
从settings.py
文件中获取变量,但实际上我应该像from django.conf import settings
然后settings.TEST_VALUE
那样做...谢谢你的提示!它帮助很大。
另外,请注意有一个 modify_settings()
装饰器。 docs.djangoproject.com/en/1.9/topics/testing/tools/…
【参考方案1】:
总结一下我从 Ismail Badawi 的评论中了解到的内容,事实上,我没有正确调用来自 settings.py
的变量,因为我使用的是 from myapp.settings import TEST_VALUE
,我应该使用 from django.conf import settings
来调用它然后settings.TEST_VALUE
。
所以,这是一个正确的tests.py
文件:
from django.test import TestCase
from django.conf import settings
class CheckSettings(TestCase):
def test_settings(self):
self.assertEqual(settings.TEST_VALUE, 'a')
def test_modified_settings(self):
with self.settings(TEST_VALUE='b'):
self.assertEqual(settings.TEST_VALUE, 'b')
还有,这是./manage.py test
的结果:
$ ./manage.py test
Creating test database for alias 'default'...
..
----------------------------------------------------------------------
Ran 2 tests in 0.001s
OK
Destroying test database for alias 'default'...
所以,这个小故事的教训是在使用时始终从django.conf
而不是myapp.settings
获取设置值。
另请注意,如果您使用缓存,您的 settings.py
的某些值可能会存储在其中,并且可能会被它们的缓存值屏蔽。为此,“Overriding settings”上的 Django 文档给出了解决此类问题的提示:
覆盖设置时,请确保处理应用代码使用缓存或类似功能的情况,即使设置更改也会保留状态。 Django 提供
django.test.signals.setting_changed
信号,允许您注册回调以在设置更改时清理或重置状态。
想了一下,没有给出真正实现它的方法。下一个问题可能是个好问题......
【讨论】:
此外,如果您在模块级别使用其中一些设置(例如,将它们存储在一些全局变量中以便更快地查找/减少繁琐的访问),则必须根据 settings_changed 信号重新加载它们。在这里没有用,但认为值得添加它,因为它密切相关。 @spectras:是的,你说得对,我会记录下来。【参考方案2】:您应该使用 @override_settings 装饰器。 https://docs.djangoproject.com/en/1.4/topics/testing/#django.test.utils.override_settings
【讨论】:
以上是关于Django 中单元测试的覆盖设置无法正常工作的主要内容,如果未能解决你的问题,请参考以下文章
从 1.8 升级到 2.2.4 后,Django 无法创建用于单元测试的表
带有 Chai 错误的 Express 单元测试 = 发送后无法设置标头