Djangoを構成して、すべてのモジュールのすべてのdoctestを検索しますか?

StackOverflow https://stackoverflow.com/questions/1615406

  •  06-07-2019
  •  | 
  •  

質問

次のコマンドを実行した場合:

>python manage.py test

Djangoは私のアプリケーションのtests.pyを見て、そのファイル内のdoctestまたはユニットテストを実行します。また、追加のテストを実行するための__ test __辞書も参照します。そのため、他のモジュールのdoctestを次のようにリンクできます。

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

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

さらに多くのdoctestを含めたい場合、これらすべてをこの辞書に列挙するよりも簡単な方法がありますか?理想的には、Djangoにmyappアプリケーションのすべてのモジュールのすべてのdoctestを検索させたいだけです。

自分がどこに行きたいのかを知るためのリフレクションハックがありますか?

役に立ちましたか?

解決 4

アレックスとポールに感謝します。これが私が思いついたものです:

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

他のヒント

しばらく前に自分でこれを解決しました:

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ファイルに入れることができたため、アプリケーションコードの他の部分と混同することはありませんでした。これを修正して、各モジュールでdocテストを探し、見つかった場合は実行するだけです。

鼻がすべてのテストを再帰的に見つけるので、 django-nose を使用します。

ソリューションの重要な要素は次のとおりです。

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パッケージを見つけます。

私はDjanoのテストの速度に精通していませんが、理解しているように、自動を使用しています。 python -m unittest discover およびNoseと同様に、unittest の検出。

その場合、次のファイルを検出が見つける場所に置くだけです(通常は test_doctest.py などの名前を付けるだけです)。

your_package をテストするパッケージに変更します。すべてのモジュール(サブパッケージを含む)がdoctestされます。

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
ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top