68 votes

Python: Comment exécuter unittest.main () pour tous les fichiers source d’un sous-répertoire?

Je suis en train d'élaborer un module Python avec plusieurs fichiers sources, chacune avec sa propre classe dérivée de unittest droit dans la source. Examiner la structure de répertoire:

dirFoo\
    test.py
    dirBar\
        __init__.py
        Foo.py
        Bar.py

De tester soit Foo.py ou Bar.py je voudrais ajouter ceci à la fin de la Foo.py et Bar.py source des fichiers:

if __name__ == "__main__":
    unittest.main()

Et de lancer Python sur que ce soit la source, c'est à dire

$ python Foo.py
...........
----------------------------------------------------------------------
Ran 11 tests in 2.314s

OK

Idéalement, j'aurais "test.py" automagiquement de recherche dirBar pour tout unittest classes dérivées et faire un appel à "unittest.main()". Quelle est la meilleure façon de le faire dans la pratique?

J'ai essayé d'utiliser Python pour appeler execfile pour tous *.py fichier dans dirBar, qui ne fonctionne que pour la première .py fichier trouvé & sort de l'appelant test.py, plus, puis-je dupliquer mon code en ajoutant unittest.main() dans chaque fichier source--qui viole SEC principes.

64voto

Peter Gibson Points 5376

Comme de Python 2.7, test de la découverte est automatisé dans le unittest paquet. À partir de la docs:

Unittest soutient test simple découverte. Afin d'être compatible avec le test de la découverte, tous les fichiers de test doivent être des modules ou des paquets importable depuis le répertoire de plus haut niveau le projet (ce qui signifie que leurs noms de fichier doit être valide identifiants).

Test de la découverte est mis en œuvre en TestLoader.discover(), mais peut aussi être utilisé à partir de la ligne de commande. La commande de base utilisation de la ligne est:

cd project_directory
python -m unittest discover

Par défaut, il recherche les paquets nommé test*.py, mais cela peut être modifié de sorte que vous pouvez utiliser quelque chose comme

python -m unittest discover --pattern=*.py

À la place de votre test.py script.

37voto

p4sven Points 181

Voici mon test de découverte de code qui semble faire le travail. Je voulais m'assurer que je peux prolonger les tests facilement, sans avoir à en faire la liste de tout les fichiers, mais aussi d'éviter l'écriture de tous les tests en un seul Übertest fichier.

Ainsi, la structure est

myTests.py
testDir\
    __init__.py
    testA.py
    testB.py

myTest.py ressembler à ceci:

import unittest

if __name__ == '__main__':
    testsuite = unittest.TestLoader().discover('.')
    unittest.TextTestRunner(verbosity=1).run(testsuite)

Je crois que c'est la solution la plus simple pour l'écriture de plusieurs scénarios de test dans un répertoire. La solution nécessite Python 2.7 et Python 3.

30voto

Pete Points 3535

Je savais qu'il y avait une solution évidente:

 dirFoo\
    test.py
    dirBar\
        Foo.py
        Bar.py
 

Contenu de dirFoo / test.py

 from dirBar import *
import unittest

if __name__ == "__main__":

    unittest.main()
 

Exécutez les tests:

 $ python test.py
...........
----------------------------------------------------------------------
Ran 11 tests in 2.305s

OK
 

Désolé pour la question idiote.

18voto

Cristian Points 10133

Tu devrais essayer le nez . C'est une bibliothèque pour aider à créer des tests et elle s'intègre avec unittest ou doctest . Tout ce que vous avez à faire est de lancer nosetests et il trouvera tous vos testaments pour vous.

 % nosetests # finds all tests in all subdirectories
% nosetests tests/ # find all tests in the tests directory
 

2voto

cdleary Points 18869

Je suis venu avec un extrait qui peut faire ce que vous voulez. Il parcourt un chemin que vous fournissez à la recherche de packages / modules Python et accumule un ensemble de suites de tests à partir de ces modules, qu'il exécute ensuite d'un coup.

La bonne chose à propos de cela est que cela fonctionnera sur tous les packages imbriqués dans le répertoire que vous spécifiez, et vous ne devrez pas modifier manuellement les importations lorsque vous ajoutez de nouveaux composants.

 import logging
import os
import unittest

MODULE_EXTENSIONS = set('.py .pyc .pyo'.split())

def unit_test_extractor(tup, path, filenames):
    """Pull ``unittest.TestSuite``s from modules in path
    if the path represents a valid Python package. Accumulate
    results in `tup[1]`.
    """
    package_path, suites = tup
    logging.debug('Path: %s', path)
    logging.debug('Filenames: %s', filenames)
    relpath = os.path.relpath(path, package_path)
    relpath_pieces = relpath.split(os.sep)

    if relpath_pieces[0] == '.': # Base directory.
        relpath_pieces.pop(0) # Otherwise, screws up module name.
    elif not any(os.path.exists(os.path.join(path, '__init__' + ext))
            for ext in MODULE_EXTENSIONS):
        return # Not a package directory and not the base directory, reject.

    logging.info('Base: %s', '.'.join(relpath_pieces))
    for filename in filenames:
        base, ext = os.path.splitext(filename)
        if ext not in MODULE_EXTENSIONS: # Not a Python module.
            continue
        logging.info('Module: %s', base)
        module_name = '.'.join(relpath_pieces + [base])
        logging.info('Importing from %s', module_name)
        module = __import__(module_name)
        module_suites = unittest.defaultTestLoader.loadTestsFromModule(module)
        logging.info('Got suites: %s', module_suites)
        suites += module_suites

def get_test_suites(path):
    """:return: Iterable of suites for the packages/modules
    present under :param:`path`.
    """
    logging.info('Base path: %s', package_path)
    suites = []
    os.path.walk(package_path, unit_test_extractor, (package_path, suites))
    logging.info('Got suites: %s', suites)
    return suites

if __name__ == '__main__':
    logging.basicConfig(level=logging.WARN)
    package_path = os.path.dirname(os.path.abspath(__file__))
    suites = get_test_suites(package_path)
    for suite in suites:
        unittest.TextTestRunner(verbosity=2).run(suite)
 

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X