如果我运行下面的命令:
>python manage.py test
Django就在tests.py在我的应用程序,并运行该文件中的任何文档测试或单元测试。 它也着眼于__ __测试字典额外的测试运行。 所以,我可以从其他模块,像这样的doctests链接:
#tests.py
from myapp.module1 import _function1, _function2
__test__ = {
"_function1": _function1,
"_function2": _function2
}
如果我想包括更多的文档测试,有没有比枚举他们都在这本字典更简单的方法? 理想情况下,我只是想有Django的找到所有的doctests在MyApp应用程序的所有模块。
是否有某种反射黑客的,我想是会得到我吗?
我前一阵子解决了这个我自己:
apps = settings.INSTALLED_APPS
for app in apps:
try:
a = app + '.test'
__import__(a)
m = sys.modules[a]
except ImportError: #no test jobs for this module, continue to next one
continue
#run your test using the imported module m
这让我把每个模块的测试,在自己的test.py文件,所以他们没有人混在一起的我的应用程序代码的其余部分。 这将是容易修改这只是看在每个模块的文档测试和运行它们,如果发现他们。
使用Django的鼻子 ,因为鼻子自动查找所有测试recursivelly。
我这里还有的溶液关键要素:
tests.py:
def find_modules(package):
"""Return list of imported modules from given package"""
files = [re.sub('\.py$', '', f) for f in os.listdir(os.path.dirname(package.__file__))
if f.endswith(".py") and os.path.basename(f) not in ('__init__.py', 'test.py')]
return [imp.load_module(file, *imp.find_module(file, package.__path__)) for file in files]
def suite(package=None):
"""Assemble test suite for Django default test loader"""
if not package: package = myapp.tests # Default argument required for Django test runner
return unittest.TestSuite([doctest.DocTestSuite(m) for m in find_modules(package)])
要添加递归使用os.walk()
遍历模块树,并找到Python包。
感谢亚历克斯和保罗。 这是我想出了:
# tests.py
import sys, settings, re, os, doctest, unittest, imp
# import your base Django project
import myapp
# Django already runs these, don't include them again
ALREADY_RUN = ['tests.py', 'models.py']
def find_untested_modules(package):
""" Gets all modules not already included in Django's test suite """
files = [re.sub('\.py$', '', f)
for f in os.listdir(os.path.dirname(package.__file__))
if f.endswith(".py")
and os.path.basename(f) not in ALREADY_RUN]
return [imp.load_module(file, *imp.find_module(file, package.__path__))
for file in files]
def modules_callables(module):
return [m for m in dir(module) if callable(getattr(module, m))]
def has_doctest(docstring):
return ">>>" in docstring
__test__ = {}
for module in find_untested_modules(myapp.module1):
for method in modules_callables(module):
docstring = str(getattr(module, method).__doc__)
if has_doctest(docstring):
print "Found doctest(s) " + module.__name__ + "." + method
# import the method itself, so doctest can find it
_temp = __import__(module.__name__, globals(), locals(), [method])
locals()[method] = getattr(_temp, method)
# Django looks in __test__ for doctests to run
__test__[method] = getattr(module, method)
我达不到的Djano的测试速度,但据我所知它使用自动单元测试发现,就像python -m unittest discover
和鼻子。
如果是这样,只要把以下文件的某处发现会发现它(通常只是它命名的问题test_doctest.py
或类似)。
更改your_package
到封装测试。 所有模块(包括子包)将doctested。
import doctest
import pkgutil
import your_package as root_package
def load_tests(loader, tests, ignore):
modules = pkgutil.walk_packages(root_package.__path__, root_package.__name__ + '.')
for _, module_name, _ in modules:
try:
suite = doctest.DocTestSuite(module_name)
except ValueError:
# Presumably a "no docstrings" error. That's OK.
pass
else:
tests.addTests(suite)
return tests