Seite anzeigenÄltere VersionenLinks hierherNach oben Diese Seite ist nicht editierbar. Sie können den Quelltext sehen, jedoch nicht verändern. Kontaktieren Sie den Administrator, wenn Sie glauben, dass hier ein Fehler vorliegt. ====== Unit Tests ====== Python bietet mit seinem Standard-Modul [[https://docs.python.org/3/library/unittest.html|unittest]] einen standardisierten UnitTest-Framework an. Dabei werden die Testmethoden der Klasse [[https://docs.python.org/3/library/unittest.html#unittest.TestCase|unittest.TestCase]] hinzugefügt und können darüber hinaus einer [[https://docs.python.org/3/library/unittest.html#unittest.TestSuite|unittest.TestSuite]] zugeordnet werden. Mit weiteren Tools wie [[https://nose.readthedocs.io/en/latest/man.html|nosetest]], [[https://docs.nose2.io/en/latest/|nose2]] und [[https://docs.pytest.org/en/stable/|pytest]] können die Standard UnitTests ausgeführt werden und bieten -- je nach Framework -- zusätzliche Möglichkeiten an. So bieten nosetest und nose2 die Möglichkeit dem Test Attribute zuzuweisen, die später bei der Ausführung zum Filtern von relevanten UnitTests Verwendung findet. Die Stärke von pytest besteht zum einen darin, nicht auf die implementierten ''self.assert*''-Funktionen des Standard-Frameworks angewiesen zu sein. Auch die Handhabung von [[#Fixtures]] ist in pytest anders geregelt. Zum anderen bietet pytest eine reichhaltige Infrastruktur an Plugins die vieles unterstützen. Allen weiteren Frameworks gemeinsam ist, sind Test erst mal mit den spezifischen Eigenheiten erweitert, lassen sie sich nur schwer auf einen Standard-UnitTest oder in das Format eines der anderen Frameworks umstellen. ^ ^ unittest.TestCase ^^ nosetest ^^ nose2 ^^ py.test ^^ | Framework unterstützt von | spyder, VS Code || || spyder || spyder, VS Code || | [[#Einzelne Testfunktionen|Testfunktionen]]\\ (Einzelne Funktionen) | --- | --- | @with_setup() | @with_setup() | @with_setup() | @with_teardown() | :?: | :?: | | [[#Ebene der Testmethode|Testmethode]]\\ (Methode der Klasse) | **setUp()** | **tearDown()** | **setUp()** | **tearDown()** | **setUp()** | **tearDown()** | * | * | | [[#Ebene der Testklasse|Testklasse]]\\ (Klassenmethode der Klasse) | **setUpClass()** | **tearDownClass()** | **setUpClass()** | **tearDownClass()** | **setUpClass()** | **tearDownClass()** | * | * | | ::: | ::: | ::: | setupClass() | teardownClass() | ::: | ::: | ::: | ::: | | ::: | ::: | ::: | setup_class() | teardown_class() | ::: | ::: | setup_class() | teardown_class() | | ::: | ::: | ::: | setupAll() | teardownAll() | ::: | ::: | ::: | ::: | | ::: | ::: | ::: | setUpAll() | tearDownAll() | ::: | ::: | ::: | ::: | | [[#Ebene der Testmodule|Modul]] (Datei)\\ (Funktion) | **setUpModule()** | **tearDownModule()** | **setUpModule()** | **tearDownModule()** | **setUpModule()** | **tearDownModule()** | * | * | | ::: | ::: | ::: | setup_module() | teardown_module() | ::: | ::: | setup_module() | teardown_module() | | ::: | ::: | ::: | setUp() | tearDown() | ::: | ::: | ::: | ::: | | ::: | ::: | ::: | setup() | teardown() | ::: | ::: | ::: | ::: | | Package (Verzeichnis)\\ (Funktion in %%__init__.py%%) | --- | --- | setUpPackage() | tearDownPackage() | --- | --- | * | * | | ::: | ::: | ::: | setup_package() | teardown_package() | ::: | ::: | ::: | ::: | | ::: | ::: | ::: | setUp() | tearDown() | ::: | ::: | ::: | ::: | | ::: | ::: | ::: | setup() | teardown() | ::: | ::: | ::: | ::: | | [[#nose2 Layer-System|Layer-System]]\\ (separate Klasse) | --- | --- | --- | --- | **setUp()** | **tearDown()** | --- | --- | ===== Fixtures ===== <WRAP box> <WRAP right> ^ Std. UnitTest ^ nosetest ^ nose2 ^ py.test ^ | nein | ja | ja | :?: | </WRAP> === Einzelne Testfunktionen === Einzelne Testfunktionen (ohne Klasse) können mit ''@with_setup(<setup>, <teardown>)'' (→ nosetest) bzw. mit ''@with_setup()'' und ''@with_teardown()'' (→ nose2) dekoriert werden, um auf eine zentral definierte setUp-/tearDown-Funktion zu verweisen. </WRAP> <WRAP box> <WRAP right> ^ Std. UnitTest ^ nosetest ^ nose2 ^ py.test ^ | ja | ja | ja | * | </WRAP> === Ebene der Testmethode === ''setUp()''/''tearDown()'' auf Ebene der Testmethode bieten alle Frameworks. Dabei wird vor der Ausführung der Testmethode die Methode ''setUp()'' der aktuellen Testklasse ausgeführt und im Abschluss nach der Testmethode die ''tearDown()'' Methode. </WRAP> <WRAP box> <WRAP right> ^ Std. UnitTest ^ nosetest ^ nose2 ^ py.test ^ | ja | ja | ja | * | </WRAP> === Ebene der Testklasse === ''setUpClass()''/''tearDownClass()'' auf Ebene der Testklasse bieten ebenfalls alle Frameworks an. Dabei wird zu Beginn der Testklasse die ''setUpClass()'' Methode ausgeführt. Danach folgt die Sequenz der ''setUp()''/''test_methode()''/''tearDown()''. Und zum Abschluss nach allen Tests erfolgt die ''tearDownClass()'' Methode. </WRAP> <WRAP box> <WRAP right> ^ Std. UnitTest ^ nosetest ^ nose2 ^ py.test ^ | ja | ja | ja | * | </WRAP> === Ebene der Testmodule === ''setUpModule()''/''tearDownModule()'' bieten alle Frameworks an, wenn auch teilweise mit unterschiedlicher Schreibweise. Die separate Funktion ''setUpModule()'' wird zu Beginn des Moduls ausgeführt. Im Anschluss werden alle UnitTest-Klassen abgearbeitet und zum Abschluss des Moduls wird ''tearDownModule()'' ausgeführt. </WRAP> <WRAP box> <WRAP right> ^ Std. UnitTest ^ nosetest ^ nose2 ^ py.test ^ | nein | nein | ja | nein | </WRAP> === nose2 Layer-System === Mit den verschiedenen Varianten von ''setUp()'' und ''tearDown()'' Funktionen/Methoden ergeben sich maximal 4 Ebenen auf denen Initialisierungen und Deinitialisierungen stattfinden können. Eine unbegrenzte Anzahl von Ebenen ergeben sich durch das Alleinstellungsmerkmal von ''nose2'' mit seinem Layer-System. Dabei wird eine Klasse erstellt, welche die zwei Funktionen ''setUp()'' und ''tearDown()'' definiert. Diese Klasse stellt ein //<wrap :en>Layer</wrap>// dar. Durch die Definition weiterer Layer-Klassen, die von einer vorangegangenen Layer-Klasse erbt, wird eine Hierarchie aufgebaut. Die erste Layer-Klasse stellt dabei das unterste Layer dar. Jeder weitere Erbe ein Layer darüber. In den UnitTest-Klassen wird ein Property definiert, das auf das entsprechende Layer verweist. ''nose2'' ließt die Testverzeichnisse in einem ersten Durchgang ein und erstellt eine interne Liste der auszuführenden Testmethoden. Dabei können einzelne Testmethoden durch Bedingungen ausgeschlossen sein. Die ''setUp()'' und ''tearDown()'' Methoden der Layer-Klassen, zwischen denen keine auszuführenden Testmethoden (z.B. durch Ausschluss) vorhanden sind, werden auch nicht ausgeführt. Alle anderen ''setUp()'' und ''tearDown()'' methoden der Layer-Klassen werden gemäß ihren Layern ausgeführt. </WRAP> ===== Testauswahl ===== In der Regel werden alle UnitTests ausgeführt, die definiert sind. Einschränkungen können erfolgen durch * die geschickte Platzierung der UnitTest-Klassen in entsprechende Module (Dateien) und Pakete (Verzeichnisse). * das Überspringen (//<wrap :en>skip</wrap>//) von Tests, was auch im Ausführungsprotokoll notiert wird. Darüber hinaus definieren nosetest und nose2 die Möglichkeit den einzelnen Testmethoden beliebige Attribute zuzuweisen, die zur Ausführung ausgewertet werden können. Ausgelassene Tests werden nicht protokolliert. ====== UnitTest Strategie ====== <blockquote> * **Statische Analyse** mit ''pylint''. * **Dynamisch Analyse** mit ''unittest''.\\ Ziel beim testen: * Prüfen auf Annahme ist ''True''. * **Test Checkliste:**\\ Auf was sollen ''Unit Tests'' ausgelegt sein. * **Existence** * Classes * Methods * functions * UI elements * assets * **Content** * data types * input values * ideal * accidental * boundaries * mathematically wrong * malicious <cite>Mariya Sha, [[https://www.youtube.com/watch?v=EqJWhlC1H6k&t=14s|Testing GUI Apps - What to test? How to test it? Mini Coding Course for Beginners]]</cite> </blockquote> python/unittests.txt Zuletzt geändert: 29.07.2025 20:41von marsch