更改“的”值的最佳方法;“设置”;在Python测试用例中?
我第一次用Python为Django应用程序编写单元测试。我遇到了一个问题。为了测试特定的功能,我需要更改应用程序设置之一的值。这是我的第一次尝试:更改“的”值的最佳方法;“设置”;在Python测试用例中?,python,django,unit-testing,namespaces,Python,Django,Unit Testing,Namespaces,我第一次用Python为Django应用程序编写单元测试。我遇到了一个问题。为了测试特定的功能,我需要更改应用程序设置之一的值。这是我的第一次尝试: def test_in_list(self): mango.settings.META_LISTS = ('tags',) tags = Document(filepath).meta['tags'] self.assertEqual(tags, [u'Markdown', u'Django', u'Mango']) 我试
def test_in_list(self):
mango.settings.META_LISTS = ('tags',)
tags = Document(filepath).meta['tags']
self.assertEqual(tags, [u'Markdown', u'Django', u'Mango'])
我试图做的是更改META_list
的值,以便在创建文档
对象时使用新值。相关进口商品是
# tests.py
from mango.models import Document
import mango.settings
# models.py
from mango.settings import *
如果我理解正确,因为models.py
已经从mango.settings
导入了名称,所以在mango.settings
中更改META\u列表的值不会更改mango.models
中的META\u列表的值
有可能——甚至有可能——我的做法完全错误。在测试用例中改变这样一个“设置”值的正确方法是什么
Edit:我没有提到文件models.py
包含普通Python类,而不是Django模型。我当然需要重命名这个文件 在models.py中,使用导入mango.settings
。然后,您可以在测试代码中设置一个变量,就像其他变量一样:
mango.settings.foo = 'bar'
模块是一个单体。您可以从代码中的任何位置更改其命名空间中的值
但是,如果使用mango.settings import*
中的,这将不起作用,因为该表达式将模块中的值复制到当前名称空间中。在整个测试过程中是否会使用此设置?在这种情况下,一个解决方案是创建一个用于测试的设置文件。例如,为测试添加设置\u.py
# settings_for_tests.py
from settings import * # Get everything from default settings file.
# Override just what is required.
META_LISTS = ('tags',)
然后运行测试,如下所示:
$ python ./manage.py test mango --settings=settings_for_tests
这将确保使用测试设置而不是默认设置创建测试数据库中的模型
如果要这样做,将设置文件移动到目录中也是有意义的。例如
project
|
|_ settings
| |
| |_ __init__.py # Contains merely from settings import *
| |_ settings.py
| |_ settings_for_tests.py
|
|_ apps
|
有一种更简单的方法可以做到这一点
使用多个设置文件——每个文件都在适当的配置控制下
我们这样做
我们有一个主设置
模块,该模块具有“始终应用”设置。中间件、已安装的应用程序、我们的应用程序特有的其他设置
我们有“子类”设置,(a)导入主设置,然后(b)引入特定于平台(或特定于阶段,或特定于客户)的设置。这就是我们的Windows文件路径隔离的地方。加上静态媒体文件的位置。加上特定于客户的模板路径等
我们将测试脚本分成几个部分。“default”tests.py
进行基本的模型、表单和视图功能测试,这些测试必须在所有平台、所有开发阶段(开发、测试、质量保证等)和所有客户上进行
我们有单独的单元测试脚本,需要对特别复杂的装置进行特殊设置。这些脚本不在tests.py
中,并且不会自动运行。它们需要显式调用Django的实用程序来设置和拆卸测试环境
看
您如何建议测试一个愚蠢的函数,当特定设置为truthy时返回“hello”,当falsy时返回“再见”
这可能表明设计很差。测试驱动设计(TDD)建议您应该将其设计为无需复杂的设置即可进行测试
如果你必须通过设置来实现,你到底在测试什么?设置值会传播到你的代码中?这很愚蠢。你应该相信框架是有效的。事实上,你必须假设框架是有效的,否则,你必须测试框架的每一个功能
你应该有一个接受设置的函数。一些设置作为参数,这样你就可以把它作为一个独立的单元来测试,而不必费心去修改整个环境。你必须相信环境和框架确实可以工作。对于在测试用例中更改设置,我使用这个snipp的修改版本et
下面是我对这个片段的修改
然后使用测试设置创建文件,然后使用(来自项目的示例):
它将跟踪原始设置并让
测试完成后,可以轻松地将它们还原回去。谢谢,Andrew,我认为可能是这样。目前,models.py
在许多地方引用了这些设置,为了可读性,我希望保持导入语句的原样(MARKDOWN_EXTENSIONS
比mango.settings.MARKDOWN_EXTENSIONS
更容易让人眼前一亮)。这是一个很好的答案,我喜欢你对导入模块
和自模块导入*
之间的功能差异所作的解释。你也可以使用mango导入设置
中的,这两种设置都让你受益匪浅。是的,尽管在这个特殊情况下,我也在使用django.conf导入setti中的ngs
,so“设置"已经被使用了。mongo的作为如何?导入设置作为m_设置是可行的,但是如果要使用m_设置
为什么不使用额外的四个字符并使用mango.settings
?这只是一个美学问题,真的。最后我可能会咬紧牙关,改变导入代码>语句,但我仍然渴望了解是否存在替代方案(即,在保留import*
语句的同时是否可能实现相同的结果)。非常感谢你的回答,Manoj。我意识到我应该在几个方面更清楚一些。首先,models.py
中定义的类实际上不是Django模型(并且不以任何方式与数据库交互)。也许这个文件有更好的名称?其次,我需要
class SerializationTestCase(SettingsTestCase):
fixtures = ['test_users.json', 'test_moderation.json']
test_settings = 'moderation.tests.settings.generic'
def setUp(self):
self.user = User.objects.get(username='moderator')
self.profile = UserProfile.objects.get(user__username='moderator')
def test_serialize_of_object(self):
"""Test if object is propertly serialized to json"""
json_field = SerializedObjectField()
self.assertEqual(json_field._serialize(self.profile),
'[{"pk": 1, "model": "test_app.userprofile", "fields": '\
'{"url": "http://www.google.com", "user": 1, '\
'"description": "Old description"}}]',
)