Question

Si j'exécute la commande suivante:

>python manage.py test

Django examine tests.py dans mon application et exécute tous les doctests ou les tests unitaires de ce fichier. Il examine également le dictionnaire __ test __ pour des tests supplémentaires à exécuter. Je peux donc relier des docttes d’autres modules comme ceci:

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

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

Si je veux inclure plus de doctests, existe-t-il un moyen plus simple que de les énumérer tous dans ce dictionnaire? Idéalement, je veux juste que Django trouve tous les doctests dans tous les modules de l’application myapp.

Y a-t-il une sorte de bidouille de réflexion qui me conduirait là où je veux être?

Était-ce utile?

La solution 4

Merci à Alex et Paul. C’est ce que j’ai trouvé:

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

Autres conseils

J'ai résolu ce problème il y a quelque temps:

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

Cela m'a permis de mettre des tests par module dans leur propre fichier test.py, afin qu'ils ne soient pas mélangés avec le reste de mon code d'application. Il serait facile de modifier cela en recherchant simplement des tests de doc dans chacun de vos modules et en les lançant s’ils les trouvaient.

Utilisez django-nose , car nose trouve automatiquement tous les tests de manière récursive.

Voici les éléments clés de la solution:

tests.py:

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

Pour ajouter de la récursivité, utilisez os.walk () pour parcourir l’arborescence des modules et rechercher les packages 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)])

Pour ajouter de la récursivité, utilisez os.walk () pour parcourir l’arborescence des modules et rechercher les packages Python.

Je ne suis pas au courant des tests de Djano, mais si je comprends bien, il utilise automatiquement les découverte unittest , tout comme python -m unittest discover et Nose.

Si tel est le cas, placez simplement le fichier suivant quelque part dans lequel la découverte le trouvera (il suffit généralement de le nommer test_doctest.py ou similaire).

Remplacez votre_paquet par le paquet à tester. Tous les modules (y compris les sous-paquetages) feront l’objet d’une modification.

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
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top