Python Testing
Das Testen hat bei untypisiertem Sprachen wie Python einen noch hĂśheren Stellenwert, da viele Fehler nicht vom Compiler entdeckt werden kĂśnnen, sondern erst zur Laufzeit auftreten.
In folgendem Beispiel
name = input("Wie ist dein name?")
if name == "Pierre":
name_int=int(name)
print(name)
tritt der Fehler int(name)
erst in Erscheinung, wenn ich den Namen Pierre
eingebe. Um dieses Problem zu lĂśsen benĂśtigt man viele Tests ... oder einen intelligenten Editor, der Python-Wissen hat und diese Probleme erkennen kann.
Der intelligente Editor hilft allerdings nur, wenn man konsequent Type Hints verwendet. Das ist ABOSULUT empfohlen ... nur nicht um Fehler zu vermeiden, sondern auch um den Komfort zu erhĂśhen, wenn man Code schreibt.
EinfĂźhrung
Prinzipiell kann man die __main__.py
eines Pakets verwenden (oder jedes beliebige Python-Modul), um Test-Code auszufĂźhren. Hierin kĂśnnte man dann
if __name__ == "__main__":
# testcode
test_my_func1()
test_my_func2()
verwenden, um die Tests auszufĂźhren.
Allerdings sollen Tests i. a. nicht bei dem ersten Fehler zu einem Abbruch fĂźhren, sondern alle Tests ausfĂźhren und ganz am Ende eine Statistik zeigen ... mit einem entsprechenden Fehlerreport.
Hier kommen Testrunner ins Spiel, die in einem Test-Framework/Library enthalten sind:
unittest
nose2
pytest
unittest
Bei diesem Test-Framework muĂ man die Tests in Klassen schreiben, die von unittest.TestCase
erben. Dadurch erhält man aber auch den Komfort von setUp()
und tearDown()
Methoden.
AusfĂźhrung
python -m unittest discover
pytest
Die
pytest
Tools fĂźhren auchunittest
-Library-Tests aus.
Im Gegensatz zu unittest
mĂźssen die Tests nicht in eine Klasse gepackt werden ... es genĂźgt:, sondern nur als Funktion
def test_always_passes():
assert True
Installation
pip install pytest
Entwicklung
Parametrisierung ist ein nettes Feature, um Test-Code zu reduzieren (von hier)
@pytest.mark.parametrize("maybe_palindrome, expected_result", [
("", True),
("a", True),
("Bob", True),
("Never odd or even", True),
("Do geese see God?", True),
("abc", False),
("abab", False),
])
def test_is_palindrome(maybe_palindrome, expected_result):
assert is_palindrome(maybe_palindrome) == expected_result
AusfĂźhrung
pytest
Auf diese Weise werden alle Tests unterhalb des aktuellen Verzeichnisses ausgefĂźhrt.
Folgende FiltermĂśglichkeiten stehen zudem zur VerfĂźgung:
Name-Based-Filtering mit
-k
-ParameterTest-Categories mit
-m
-Parameter
Fixtures
wiederverwendbarer Initialisierungscode ... ein Test erhält die Fixture als Parameter.
import pytest
@pytest.fixture
def people_data():
return [
{
"given_name": "Pierre",
"family_name": "Feldbusch",
"title": "Senior Software Engineer",
},
{
"given_name": "Robin",
"family_name": "Feldbusch",
"title": "Project Manager",
},
]
def test_format_data_for_display(people_data):
assert format_data_for_display(example_people_data) == [
"Pierre Feldbusch: Senior Software Engineer",
"Robin Feldbusch: Project Manager",
]
def test_format_data_for_excel(people_data):
assert format_data_for_excel(example_people_data) == """given,family,title
"Pierre Feldbusch: Senior Software Engineer",
"Robin Feldbusch: Project Manager",
"""
Man kann Fixtures in eine Datei mit dem Namen conftest.py
auslagern und die stehen allen Tests im gleichen Verzeichnis oder darunter zur VerfĂźgung.
Plugins
pytest
läĂt sich Ăźber Plugins erweitern ... beispielsweise um Helper fĂźr bestimmte Frameworks (z. B. Django)
tox.ini
Auf diese Weise kann man testen, ob sich ein Package auf verschiedenen Python-Versionen installieren läĂt - zudem laufen die Tests auch alle auf den definierten Python-Versionen.
sehr zu empfehlen ... hab ich gelesen ...
Last updated
Was this helpful?