Frage

Wenn ich den folgenden Befehl:

>python manage.py test

Django schaut tests.py in meiner Anwendung und läuft alle Doctests oder Unit-Tests in dieser Datei. Es sieht auch am __ __ Test Wörterbuch für zusätzliche Tests auszuführen. So kann ich Doctests von anderen Modulen verknüpft wie folgt:

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

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

Wenn ich mehr Doctests aufnehmen möchten, gibt es einen einfacheren Weg, als sie alle in diesem Wörterbuch aufzählt? Idealerweise möchte ich nur Django haben alle Doctests in allen Modulen in der myapp Anwendung finden.

Gibt es irgendeine Art von Reflexion Hack, der mich würde, wo ich sein möchte?

War es hilfreich?

Lösung 4

Danke an Alex und Paul. Das ist, was ich kam mit:

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

Andere Tipps

Ich löste dieses für mich vor einer Weile:

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

Das erlaubte mir, pro-Modultests im eigenen test.py Datei zu setzen, so haben sie nicht mit dem Rest meines Anwendungscode einmischen. Es wäre leicht, dies zu ändern, um nur in jedem Ihrer Module für doc Tests zu suchen und sie laufen, wenn er sie gefunden.

Verwenden Sie django-Nase seit Nase automatisch alle Tests finden recursivelly.

Here're Schlüsselelemente der Lösung:

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

Um Rekursion Verwendung os.walk() in dem Modulbaum durchlaufen und Python-Pakete finden.

Ich bin oben nicht auf Djano des Tests zu beschleunigen, aber wie ich es verwendet automatische verstehen Unittest Entdeckung, wie python -m unittest discover und Nase.

Wenn ja, nur die folgende Datei setzt irgendwo die Entdeckung es findet (in der Regel nur eine Frage der Namensgebung test_doctest.py oder ähnliches).

Ändern your_package um das Paket zu testen. Alle Module (einschließlich Subpackages) wird doctested werden.

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
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top