配置 Django 以查找所有模块中的所有文档测试?

发布于 2024-08-09 14:22:09 字数 454 浏览 15 评论 0原文

如果我运行以下命令:

>python manage.py test

Django 会查看我的应用程序中的tests.py,并运行该文件中的任何文档测试或单元测试。它还查看 __ test __ 字典以运行额外的测试。因此,我可以从其他模块链接文档测试,如下所示:

#tests.py
from myapp.module1 import _function1, _function2

__test__ = {
    "_function1": _function1,
    "_function2": _function2
}

如果我想包含更多文档测试,是否有比在本字典中枚举它们更简单的方法?理想情况下,我只想让 Django 找到 myapp 应用程序中所有模块中的所有文档测试。

是否有某种反射黑客可以让我到达我想要的地方?

If I run the following command:

>python manage.py test

Django looks at tests.py in my application, and runs any doctests or unit tests in that file. It also looks at the __ test __ dictionary for extra tests to run. So I can link doctests from other modules like so:

#tests.py
from myapp.module1 import _function1, _function2

__test__ = {
    "_function1": _function1,
    "_function2": _function2
}

If I want to include more doctests, is there an easier way than enumerating them all in this dictionary? Ideally, I just want to have Django find all doctests in all modules in the myapp application.

Is there some kind of reflection hack that would get me where I want to be?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

回眸一笑 2024-08-16 14:22:09

我不久前自己解决了这个问题:

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 文件中,这样它们就不会与我的应用程序代码的其余部分混淆。修改它很容易,只需在每个模块中查找文档测试并在找到它们时运行它们。

I solved this for myself a while ago:

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

This allowed me to put per-module tests in their own test.py file, so they didn't get mixed up with the rest of my application code. It would be easy to modify this to just look for doc tests in each of your modules and run them if it found them.

秋意浓 2024-08-16 14:22:09

使用django-nose,因为nose会自动递归地查找所有测试。

Use django-nose since nose automatically find all tests recursivelly.

假装爱人 2024-08-16 14:22:09

我不太了解 Djano 的测试速度,但据我了解,它使用自动 unittest discovery,就像 python -m unittest discovery 和 Nose 一样。

如果是这样,只需将以下文件放在发现可以找到的地方(通常只需将其命名为 test_doctest.py 或类似名称即可)。

your_package 更改为要测试的包。所有模块(包括子包)都将进行文档测试。

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

I'm not up to speed on Djano's testing, but as I understand it uses automatic unittest discovery, just like python -m unittest discover and Nose.

If so, just put the following file somewhere the discovery will find it (usually just a matter of naming it test_doctest.py or similar).

Change your_package to the package to test. All modules (including subpackages) will be 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
自此以后,行同陌路 2024-08-16 14:22:09

以下是解决方案的关键要素:

tests.py:

def find_modules(package):
    """Return list of imported modules from given package"""
    files = [re.sub('\.py

要添加递归,请使用 os.walk() 遍历模块树并查找 python 包。

, '', 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 包。

Here're key elements of solution:

tests.py:

def find_modules(package):
    """Return list of imported modules from given package"""
    files = [re.sub('\.py

To add recursion use os.walk() to traverse module tree and find python packages.

, '', 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)])

To add recursion use os.walk() to traverse module tree and find python packages.

孤单情人 2024-08-16 14:22:09

感谢亚历克斯和保罗。这就是我想出的:

# 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)

Thanks to Alex and Paul. This is what I came up with:

# 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)
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文