2013-04-12 16 views
130

In unserem Team Rennen, definieren wir die meisten Testfälle wie folgt aus:einzigen Test von unittest.TestCase über die Kommandozeile

One "Rahmen" Klasse ourtcfw.py:

import unittest 

class OurTcFw(unittest.TestCase): 
    def setUp: 
     # something 

    # other stuff that we want to use everywhere 

und viele Test Fälle wie testMyCase.py:

import localweather 

class MyCase(OurTcFw): 

    def testItIsSunny(self): 
     self.assertTrue(localweather.sunny) 

    def testItIsHot(self): 
     self.assertTrue(localweather.temperature > 20) 

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

Wenn ich neue Testcode zu schreiben bin und möchte es oft laufen, und sparen Zeit, was ich tue, ist, dass ich „__“ vor allen anderen Tests unterzogen. Aber es ist umständlich, lenkt mich von dem Code ab, den ich schreibe, und das Commit-Geräusch, das dadurch entsteht, ist einfach nervig.

Also z.B. wenn Änderungen an testItIsHot() machen, ich möchte, dies zu tun in der Lage:

$ python testMyCase.py testItIsHot 

und unittest Lauf haben nurtestItIsHot()

Wie kann ich das erreichen?

Ich habe versucht, den if __name__ == "__main__": Teil umzuschreiben, aber da ich neu bei Python bin, fühle ich mich verloren und schlage weiter in alles andere als die Methoden.

+2

Bitte denken Sie daran, die akzeptierte [Antwort] (https://Stackoverflow.com/a/26531790/) auf die von Ajay zu aktualisieren; es funktioniert tatsächlich. –

Antwort

161

Dies funktioniert, wie Sie vorschlagen - Sie müssen nur als auch den Klassennamen angeben:

python testMyCase.py MyCase.testItIsHot 
+1

Oh mein! Da die Tests auf python2.6 laufen sollen (99% der Zeit kann ich * die Tests selbst mit python2.7 testen), habe ich 2.6.8 doc angeschaut und so viel verpasst! :-) –

+1

Habe gerade gemerkt, dass das nur funktioniert, wenn die Methode "test *" heißt, also kann es leider nicht genutzt werden, um gelegentlich Tests auszuführen, die durch umbenennen "disabled" sind. –

+2

Funktioniert nicht für Tests in einem Unterverzeichnis - am meisten allgemeiner Fall in einem ausgereiften Python-Programm. –

42

Es kann gut arbeiten, wie Sie

python testMyCase.py MyCase.testItIsHot 

erraten Und es gibt eine weitere Möglichkeit, nur Test testItIsHot:

suite = unittest.TestSuite() 
    suite.addTest(MyCase("testItIsHot")) 
    runner = unittest.TextTestRunner() 
    runner.run(suite) 
+6

Ich fand den zweiten Teil dieser Antwort sehr hilfreich: Ich schreibe Tests in Eclipse + PyDev und ich möchte nicht auf die Befehlszeile wechseln! –

63

Wenn Sie Ihre Testfälle organisieren, das heißt, nach dem gleichen Organe isierung wie der eigentliche Code und verwenden auch relativ Importe für Module im selben Paket

Sie auch das folgende Befehlsformat verwenden können: Sie

python -m unittest mypkg.tests.test_module.TestClass.test_method 
# In your case, this would be: 
python -m unittest testMyCase.MyCase.testItIsHot 
+9

Dies sollte die akzeptierte Antwort sein. –

9

Wenn Sie überprüfen die Hilfe der Unittest-Modul es sagt mehrere Kombinationen, mit denen Sie Testfallklassen aus einem Modul ausführen und Methoden aus einer Testfallklasse testen können.

python3 -m unittest -h 

[...] 

Examples: 
    python3 -m unittest test_module    - run tests from test_module 
    python3 -m unittest module.TestClass   - run tests from module.TestClass 
    python3 -m unittest module.Class.test_method - run specified test method 

Es ist erforderlich, dass Sie eine unittest.main() als Standardverhalten des Moduls zu definieren.

+0

+1 und da die Terminologie verwirrend sein kann, wenn sie in einer Sprache neu ist (und die 'usage' sogar seltsam inkonsistent ist): Die Ausführung von' python -m unittest module_test.TestClass.test_method' setzt eine Datei 'module_test.py' (von aktuell ausgeführt) voraus Verzeichnis; und "__init.py__" ist _nicht_ erforderlich); und 'module_test.py' enthält' class TestClass (unittest.TestCase) ... 'welches' def test_method (self, ...) 'enthält (dies funktioniert auch für mich auf Python 2.7.13) – michael

-4

Hier ist eine andere Art und Weise

testname = "testItIsHot" 
testcase = MyCase(testname) 
testcase.testItIsHot() 
+4

Dies beantwortet nicht die Frage, die explizit "via Kommandozeile" sagt. –

1

Inspiriert von @yarkee ich es mit einigen der Code kombiniert ich schon habe. Sie können dies auch von einem anderen Skript aus aufrufen, indem Sie einfach die Funktion run_unit_tests() aufrufen, ohne die Befehlszeile verwenden zu müssen, oder sie einfach über die Befehlszeile mit python3 my_test_file.py aufrufen.

import my_test_file 
my_test_file.run_unit_tests() 

Leider funktioniert dies nur für Python 3.3 oder überlegen:

import unittest 


class LineBalancingUnitTests(unittest.TestCase): 

    @classmethod 
    def setUp(self): 
     self.maxDiff = None 

    def test_it_is_sunny(self): 
     self.assertTrue("a" == "a") 

    def test_it_is_hot(self): 
     self.assertTrue("a" != "b") 


def run_unit_tests(): 
    runner = unittest.TextTestRunner() 

    classes = \ 
    [ 
     LineBalancingUnitTests, 
    ] 

    # Comment all the tests names on this list, to run all Unit Tests 
    unit_tests_to_run = \ 
    [ 
     "test_it_is_sunny", 
     # "test_it_is_hot", 
    ] 

    runner.run(suite(classes, unit_tests_to_run)) 


def suite(classes, unit_tests_to_run): 
    """ 
     Problem with sys.argv[1] when unittest module is in a script 
     https://stackoverflow.com/questions/2812218/problem-with-sys-argv1-when-unittest-module-is-in-a-script 

     Is there a way to loop through and execute all of the functions in a Python class? 
     https://stackoverflow.com/questions/2597827/is-there-a-way-to-loop-through-and-execute-all-of-the-functions 

     looping over all member variables of a class in python 
     https://stackoverflow.com/questions/1398022/looping-over-all-member-variables-of-a-class-in-python 
    """ 
    suite = unittest.TestSuite() 
    unit_tests_to_run_count = len(unit_tests_to_run) 

    for _class in classes: 
     _object = _class() 

     for function_name in dir(_object): 

      if function_name.lower().startswith("test"): 

       if unit_tests_to_run_count > 0 \ 
         and function_name not in unit_tests_to_run: 

        continue 

       suite.addTest(_class(function_name)) 

    return suite 


if __name__ == "__main__": 

    print("\n\n") 
    run_unit_tests() 

den Code bearbeiten wenig, können Sie ein Array mit allen Komponententests übergeben Sie anrufen möchten:

... 
def run_unit_tests(unit_tests_to_run): 
    runner = unittest.TextTestRunner() 

    classes = \ 
    [ 
     LineBalancingUnitTests, 
    ] 

    runner.run(suite(classes, unit_tests_to_run)) 
... 

Und eine andere Datei:

import my_test_file 

# Comment all the tests names on this list, to run all Unit Tests 
unit_tests_to_run = \ 
[ 
    "test_it_is_sunny", 
    # "test_it_is_hot", 
] 

my_test_file.run_unit_tests(unit_tests_to_run) 
Verwandte Themen