481 votes

Exécuter tous les tests unitaires dans le répertoire Python

Donc, j'ai un répertoire qui contient mon Python de test de l'unité. Chaque unité de module de test est de la forme "test_*.py". Je suis d'essayer de faire un fichier appelé "all_test.py" qui, vous l'aurez deviné, exécuter tous les fichiers précités formulaire de test et de retourner le résultat. J'ai essayé les deux méthodes de mesure, les deux ont échoué, je vais vous montrer deux méthodes, et espère que quelqu'un ici sait comment le faire correctement. Je vous remercie.

Pour ma première tentative vaillante, j'ai pensé: "Si je viens d'importer tous mes tests de modules dans le fichier, et ensuite appeler cette unittest.main() bidule, il va travailler, non?" Eh bien, s'avère faux.

import glob
import unittest

testSuite = unittest.TestSuite()
test_file_strings = glob.glob('test_*.py')
module_strings = [str[0:len(str)-3] for str in test_file_strings]

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

Cela ne fonctionne pas, le résultat de retour que j'ai eu était.

$ python all_test.py 

----------------------------------------------------------------------
Ran 0 tests in 0.000s

OK

Pour mon deuxième essai, j'ai bien, ok, peut-être que je vais essayer de le faire tout les tests de chose en plus "manuelle" de la mode. J'ai donc tenté de le faire ci-dessous.

import glob
import unittest

testSuite = unittest.TestSuite()
test_file_strings = glob.glob('test_*.py')
module_strings = [str[0:len(str)-3] for str in test_file_strings]
[__import__(str) for str in module_strings]
suites = [unittest.TestLoader().loadTestsFromName(str) for str in module_strings]
[testSuite.addTest(suite) for suite in suites]
print testSuite 

result = unittest.TestResult()
testSuite.run(result)
print result

#Ok, at this point, I have a result, how do I display it as the normal unit test
#command line output?
if __name__ == "__main__":
    unittest.main()

Cela aussi n'a pas de travail, mais il semble si proche!

$ python all_test.py 
<unittest.TestSuite tests=[<unittest.TestSuite tests=[<unittest.TestSuite tests=[<test_main.TestMain testMethod=test_respondes_to_get>]>]>]>
<unittest.TestResult run=1 errors=0 failures=0>

----------------------------------------------------------------------
Ran 0 tests in 0.000s

OK

Semble si proche!!!! Il me semble avoir un costume, de la sorte, et je peux exécuter le résultat. Je suis un peu inquiète sur le fait qu'il dit que j'ai seulement "run=1", semble que ce devrait être "run=2", mais c'est un progrès. Mais comment puis-je transmettre et d'afficher le résultat principal? Ou comment faire essentiellement le faire fonctionner donc je ne peux il suffit d'exécuter ce fichier, et en agissant de la sorte, l'exécution de tous les tests de l'unité dans ce répertoire?

723voto

Travis Bear Points 1408

Avec Python 2.7 et versions ultérieures, vous n'avez pas besoin d'écrire de nouveau code ni d'utiliser des outils tiers pour le faire. l'exécution récursive du test via la ligne de commande est intégrée.

 python -m unittest discover <test_directory>
# or
python -m unittest discover -s <directory> -p '*_test.py'
 

Vous pouvez en savoir plus dans python> 2.7 ou python 3.x unittest documentation.

111voto

Ned Batchelder Points 128913

Vous pouvez utiliser un testeur qui le ferait pour vous. le nez est très bon par exemple. Une fois exécuté, il trouvera des tests dans l’arborescence actuelle et les exécutera.

Mis à jour:

Voici un code de mes jours d'avant le nez. Vous ne voulez probablement pas la liste explicite des noms de modules, mais peut-être que le reste vous sera utile.

 testmodules = [
    'cogapp.test_makefiles',
    'cogapp.test_whiteutils',
    'cogapp.test_cogapp',
    ]

suite = unittest.TestSuite()

for t in testmodules:
    try:
        # If the module defines a suite() function, call it to get the suite.
        mod = __import__(t, globals(), locals(), ['suite'])
        suitefn = getattr(mod, 'suite')
        suite.addTest(suitefn())
    except (ImportError, AttributeError):
        # else, just load all the test cases from the module.
        suite.addTest(unittest.defaultTestLoader.loadTestsFromName(t))

unittest.TextTestRunner().run(suite)
 

33voto

Stephen Cagle Points 2784

En étudiant un peu le code ci-dessus (avec TextTestRunner et defaultTestLoader en particulier), j’ai pu me rapprocher. Finalement, j'ai corrigé mon code en passant simplement toutes les suites de tests à un seul constructeur de suites, plutôt que de les ajouter "manuellement", ce qui corrigeait mes autres problèmes. Alors voici ma solution.

 import glob
import unittest

test_file_strings = glob.glob('test_*.py')
module_strings = [str[0:len(str)-3] for str in test_file_strings]
suites = [unittest.defaultTestLoader.loadTestsFromName(str) for str
          in module_strings]
testSuite = unittest.TestSuite(suites)
text_runner = unittest.TextTestRunner().run(testSuite)
 

Merci pour tout le monde aide. Oui, il est probablement plus facile d’utiliser le nez que de le faire, mais c’est tout. :)

29voto

demented hedgehog Points 733

Si vous souhaitez exécuter tous les tests de différentes classes TestCase et que vous souhaitez les spécifier explicitement, vous pouvez le faire comme suit:

 from unittest import TestLoader, TextTestRunner, TestSuite
from uclid.test.test_symbols import TestSymbols
from uclid.test.test_patterns import TestPatterns

if __name__ == "__main__":

    loader = TestLoader()
    suite = TestSuite((
        loader.loadTestsFromTestCase(TestSymbols),
        loader.loadTestsFromTestCase(TestPatterns),
        ))

    runner = TextTestRunner(verbosity = 2)
    runner.run(suite)
 

où uclid est mon projet et TestSymbols et TestPatterns sont des sous-classes de TestCase

15voto

rds Points 5742

J'ai utilisé la méthode discover et une surcharge de load_tests pour obtenir ce résultat en un nombre (minimal, je pense) de lignes de code:

 def load_tests(loader, tests, pattern):
''' Discover and load all unit tests in all files named ``*_test.py`` in ``./src/``
'''
    suite = TestSuite()
    for all_test_suite in unittest.defaultTestLoader.discover('src', pattern='*_tests.py'):
        for test_suite in all_test_suite:
            suite.addTests(test_suite)
    return suite

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

Exécution sur cinq ans quelque chose comme

 Ran 27 tests in 0.187s
OK
 

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