使用DJango / Python 3.7。我在这里阅读 - How do I run all Python unit tests in a directory?我可以使用“discover”命令在指定目录中查找测试。我想要一个“测试”文件夹,所以我创建了一个,然后运行
(venv) localhost:myproject davea$ python -m unittest discover tests
Traceback (most recent call last):
File "/usr/local/Cellar/python/3.7.2_2/Frameworks/Python.framework/Versions/3.7/lib/python3.7/runpy.py", line 193, in _run_module_as_main
"__main__", mod_spec)
File "/usr/local/Cellar/python/3.7.2_2/Frameworks/Python.framework/Versions/3.7/lib/python3.7/runpy.py", line 85, in _run_code
exec(code, run_globals)
File "/usr/local/Cellar/python/3.7.2_2/Frameworks/Python.framework/Versions/3.7/lib/python3.7/unittest/__main__.py", line 18, in <module>
main(module=None)
File "/usr/local/Cellar/python/3.7.2_2/Frameworks/Python.framework/Versions/3.7/lib/python3.7/unittest/main.py", line 100, in __init__
self.parseArgs(argv)
File "/usr/local/Cellar/python/3.7.2_2/Frameworks/Python.framework/Versions/3.7/lib/python3.7/unittest/main.py", line 124, in parseArgs
self._do_discovery(argv[2:])
File "/usr/local/Cellar/python/3.7.2_2/Frameworks/Python.framework/Versions/3.7/lib/python3.7/unittest/main.py", line 244, in _do_discovery
self.createTests(from_discovery=True, Loader=Loader)
File "/usr/local/Cellar/python/3.7.2_2/Frameworks/Python.framework/Versions/3.7/lib/python3.7/unittest/main.py", line 154, in createTests
self.test = loader.discover(self.start, self.pattern, self.top)
File "/usr/local/Cellar/python/3.7.2_2/Frameworks/Python.framework/Versions/3.7/lib/python3.7/unittest/loader.py", line 344, in discover
raise ImportError('Start directory is not importable: %r' % start_dir)
ImportError: Start directory is not importable: 'tests'
这对我来说很奇怪,因为我有一个(空的)初始化文件...
(venv) localhost:myproject davea$ ls web/tests/
__init__.py model_tests.py
我还需要做些什么才能识别我的测试目录?
编辑:以下是model_tests.py的内容......
from django.conf import settings
from django.test import TestCase
from django.core import management
def setup():
print("setup")
management.call_command('loaddata', 'test_data.yaml', verbosity=0)
def teardown():
management.call_command('flush', verbosity=0, interactive=False)
class ModelTest(TestCase):
# Verify we can correctly calculate the amount of taxes when we are working
# with a state whose tax rates are defined in our test data
def test_calculate_tax_rate_for_defined_state(self):
state = "MN"
income = 30000
taxes = IndividualTaxBracket.objects.get_taxes_owed(state, income)
print(taxes)
self.assertTrue(taxes > 0, "Failed to calucate taxes owed properly.")
我认为你对discover
命令有些困惑。根据文件。
Unittest支持简单的测试发现。为了与测试发现兼容,所有测试文件必须是可从项目的顶级目录导入的模块或包(包括命名空间包)(这意味着它们的文件名必须是有效的标识符)。
这意味着所有测试文件都必须可以从运行命令的目录(包含web
目录的目录)导入。确保这一点,所有测试文件必须在有效的python包中(包含__init__.py
的目录)。
其次,你运行命令python -m unittest discover tests
这是错误的。您最后不必添加tests
。 unittests with discover命令支持4个选项。你可以阅读更多关于它here。
我有以下目录结构。
web
├── __init__.py
└── tests
├── __init__.py
└── test_models.py
我正在按照命令运行。
python3 -m unittest discover
有以下结果。
...
----------------------------------------------------------------------
Ran 3 tests in 0.000s
OK
第一件事:拥有__init__.py
并不罕见,因为__init__.py
告诉python该目录是一个模块;它通常有一个空的__init__.py
文件。我有同样的错误,并通过重命名我的目录.
修复它。
如果一个名为tests.py
的文件作为tests
模块的兄弟存在,那可能会导致提到的ImportError,并且删除test.py应该修复它。
如果仍未发现单元测试,则需要提出几个问题:
1)测试模块是否至少包含一个派生自django.test.TestCase的类?
2)在这种情况下,该类是否包含至少一个名称以“test_”开头的方法
请注意,包含单元测试的任何文件的名称都应以“test”开头。
所以model_test.py不起作用; is通常用于设置一些假模型,但单元测试应该驻留在其他地方。
您可以使用此管理命令发现并运行测试:
python manage.py test
要么
python manage.py test appname
使用python -m unittest discover
有什么特别的原因吗?我认为这也可以,但是你必须手动引导django环境
完成......
你已经知道形式here:
您的测试和文件的名称必须与特定模式匹配才能被
discover()
发现。
但是你得到了这个错误:
“django.core.exceptions.ImproperlyConfigured:请求的设置,但未配置设置”
这意味着Django在运行测试时无法找到其设置。您可以使用环境变量告知在何处查找设置:
DJANGO_SETTINGS_MODULE='myproyect.settings' python3 -m unittest discover
参考:https://docs.djangoproject.com/en/2.2/topics/settings/#designating-the-settings
您应该运行Django测试
./manage.py tests
这将是search tests automatically using the same mechanism than discover()
,因为你将运行Django命令,你将有一些好处直接运行Django测试。
在model_tests.py
文件的最开头有from django.conf import settings
行,在创建设置LazyObject
实例时,Django将搜索该环境变量。阅读代码以获取更多详细信息。
我将在此处发布该代码的片段以供说明。
# django.conf module.
ENVIRONMENT_VARIABLE = "DJANGO_SETTINGS_MODULE"
class LazySettings(LazyObject):
"""
A lazy proxy for either global Django settings or a custom settings object.
The user can manually configure settings prior to using them. Otherwise,
Django uses the settings module pointed to by DJANGO_SETTINGS_MODULE.
"""
def _setup(self, name=None):
"""
Load the settings module pointed to by the environment variable. This
is used the first time we need any settings at all, if the user has not
previously configured the settings manually.
"""
settings_module = os.environ.get(ENVIRONMENT_VARIABLE)
if not settings_module:
desc = ("setting %s" % name) if name else "settings"
raise ImproperlyConfigured(
"Requested %s, but settings are not configured. "
"You must either define the environment variable %s "
"or call settings.configure() before accessing settings."
% (desc, ENVIRONMENT_VARIABLE))
self._wrapped = Settings(settings_module)
所以,如果你这样做:
from django.conf import settings
这个环境变量已经解决了,声明
settings.configure()
将与RuntimeError('Settings already configured.')
失败