在 Django 中覆盖单元测试的设置无法正常工作

Overriding Settings for unit tests in Django doesn't work properly

我试图对我的 Django 程序进行单元测试,我想检查 settings.py 文件中几个变量的几个值。

在文档中,“Overriding settings”部分描述了一种方法。但是,尽管我进行了所有尝试,但在测试 运行ning 期间,我无法使更改在程序中可用。以下是我在一个最小示例中所做的总结:

首先,创建一个新项目:

$ 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)。

那么,我缺少什么才能让它正常工作?

只是总结一下我从 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 的某些值可能会存储在其中,并且可能会被其缓存值掩盖。为此,Django 关于“Overriding settings”的文档给出了解决此类问题的提示:

When overriding settings, make sure to handle the cases in which your app’s code uses a cache or similar feature that retains state even if the setting is changed. Django provides the django.test.signals.setting_changed signal that lets you register callbacks to clean up and otherwise reset state when settings are changed.

想了想,真正实现的方法没有给出。下一个问题可能是个好问题...

你应该使用@override_settings装饰器。 https://docs.djangoproject.com/en/1.4/topics/testing/#django.test.utils.override_settings