454 Stimmen

Wie kann ich alle Python-Unit-Tests in einem Verzeichnis ausführen?

Ich habe ein Verzeichnis, das meine Python-Unit-Tests enthält. Jedes Unit-Test-Modul hat die Form test_*.py . Ich versuche, eine Datei namens all_test.py die, Sie haben es erraten, alle Dateien in der oben erwähnten Testform ausführt und das Ergebnis zurückgibt. Ich habe bisher zwei Methoden ausprobiert; beide sind fehlgeschlagen. Ich werde die beiden Methoden zeigen und hoffe, dass jemand da draußen weiß, wie man das richtig macht.

Bei meinem ersten tapferen Versuch dachte ich: "Wenn ich einfach alle meine Testmodule in die Datei importiere und diese dann aufrufe unittest.main() Dingsbums, das funktioniert doch, oder?" Nun, es stellte sich heraus, dass ich falsch lag.

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

Das hat nicht funktioniert, das Ergebnis war:

$ python all_test.py 

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

OK

Bei meinem zweiten Versuch dachte ich mir, ok, vielleicht versuche ich, diese ganze Testsache auf eine mehr "manuelle" Art und Weise zu machen. Also habe ich versucht, das unten zu tun:

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

Auch das hat nicht funktioniert, aber es scheint so nahe dran zu sein!

$ 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

Ich scheine eine Art von Suite zu haben, und ich kann das Ergebnis ausführen. Ich bin etwas besorgt über die Tatsache, dass es heißt, ich hätte nur run=1 scheint das zu sein run=2 aber es ist ein Fortschritt. Aber wie kann ich das Ergebnis an main übergeben und anzeigen? Oder wie bekomme ich es grundsätzlich so hin, dass ich nur diese Datei ausführen kann und dabei alle Unit-Tests in diesem Verzeichnis ausführe?

28voto

demented hedgehog Punkte 6311

Wenn Sie alle Tests aus verschiedenen Testfallklassen ausführen möchten und diese explizit angeben möchten, können Sie dies so tun:

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()
    tests = [
        loader.loadTestsFromTestCase(test)
        for test in (TestSymbols, TestPatterns)
    ]
    suite = TestSuite(tests)

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

donde uclid ist mein Projekt und TestSymbols y TestPatterns sind Unterklassen von TestCase .

15voto

rds Punkte 25174

Ich habe die discover Methode und eine Überladung von load_tests um dieses Ergebnis mit einer (minimalen, denke ich) Anzahl von Codezeilen zu erreichen:

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

Ausführung bei Fünfen etwa wie

Ran 27 tests in 0.187s
OK

9voto

zinking Punkte 5285

Ich habe verschiedene Ansätze ausprobiert, aber alle scheinen fehlerhaft zu sein, oder ich muss Code nachbessern, das ist ärgerlich. Aber es gibt einen bequemen Weg unter Linux, nämlich einfach jeden Test durch ein bestimmtes Muster zu finden und sie dann einen nach dem anderen aufzurufen.

find . -name 'Test*py' -exec python '{}' \;

und, was am wichtigsten ist, es funktioniert definitiv.

8voto

saaj Punkte 19920

Im Falle eines verpackt Bibliothek oder Anwendung, dann sollten Sie das nicht tun. setuptools wird es für Sie tun .

Um diesen Befehl zu verwenden, müssen die Tests Ihres Projekts in eine unittest Testsuite entweder durch eine Funktion, eine TestCase-Klasse oder -Methode oder ein Modul oder Paket, das TestCase Klassen. Handelt es sich bei der benannten Suite um ein Modul, und hat das Modul eine additional_tests() Funktion, wird sie aufgerufen und das Ergebnis (das ein unittest.TestSuite ) wird zu den auszuführenden Tests hinzugefügt. Wenn die benannte Suite ein Paket ist, alle Untermodule und Unterpakete werden rekursiv zur gesamten Testsuite hinzugefügt .

Sagen Sie ihm einfach, wo sich Ihr Root-Testpaket befindet, z. B:

setup(
    # ...
    test_suite = 'somepkg.test'
)

Und laufen python setup.py test .

Die dateibasierte Entdeckung kann in Python 3 problematisch sein, es sei denn, Sie vermeiden relative Importe in Ihrer Testsuite, weil discover verwendet den Datei-Import. Auch wenn es optionale top_level_dir aber ich hatte einige unendliche Rekursionsfehler. Eine einfache Lösung für einen nicht paketierten Code besteht darin, Folgendes einzufügen __init__.py Ihres Testpakets (siehe load_tests Protokoll ).

import unittest

from . import foo, bar

def load_tests(loader, tests, pattern):
    suite = unittest.TestSuite()
    suite.addTests(loader.loadTestsFromModule(foo))
    suite.addTests(loader.loadTestsFromModule(bar))

    return suite

5voto

Plasty Grove Punkte 2743

Das ist eine alte Frage, aber was für mich jetzt (2019) funktioniert hat, ist:

python -m unittest *_test.py

Alle meine Testdateien befinden sich in demselben Ordner wie die Quelldateien und enden mit _test .

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X