Lerne, wie du deine Python-Übungen auf Exercism testest.
Wir verwenden pytest als Test-Runner für unsere Website.
Du musst pytest auf deinem Entwicklungsrechner installieren, wenn du die Übungstests für den Python-Track lokal herunterladen und ausführen möchtest.
Außerdem solltest du die folgenden pytest-Plugins installieren:
Wir empfehlen außerdem das Linting-Programm pylint, denn es ist Teil unseres automatisierten Feedbacks auf der Website und kann ein sehr nützliches Werkzeug für die statische Codeanalyse sein.
Der Einfachheit halber kannst du mit dem pytest-pylint-Plugin für pytest pylint über pytest auf der Kommandozeile ausführen.
Die Pylint-Konfiguration kann etwas viel sein. Deshalb kann dieses Tutorial von pylint.readthedocs.io beim Einstieg helfen, ebenso wie dieser Überblick über Code-Qualität: Tools und Best Practices von Real Python.
Pytest lässt sich mit dem in Python integrierten Werkzeug pip installieren und aktualisieren.
Für weitere Tipps hat Brett Cannon eine schöne schnelle Anleitung zur Installation von Python-Paketen und eine großartige Erklärung, warum du python -m pip verwenden solltest.
Mehr zu den Kommandozeilenargumenten von Python findest du unter Kommandozeile und Umgebung in der Python-Dokumentation.
Hinweis: Ob Python3 und py auf deinem System Aliase für Python sind, ist nicht sicher.
Passe die Installationsbefehle unten entsprechend an.
Um pytest in einer virtuellen Umgebung zu installieren, stelle sicher, dass die Umgebung aktiviert ist, bevor du Befehle ausführst.
Andernfalls wird pytest global installiert.
PS C:\Users\foobar> py -m pip install pytest pytest-cache pytest-subtests pytest-pylint
Successfully installed pytest-8.3.3 ...
$ python3 -m pip install pytest pytest-cache pytest-subtests pytest-pylint
Successfully installed pytest-8.3.3 ...
So prüfst du, ob die Installation erfolgreich war:
$ python3 -m pytest --version
pytest 8.3.3
Um die Tests auszuführen, wechsle mit cd in deinem Terminal in den Ordner, in dem die Übung gespeichert ist (ersetze <exercise-folder-location> unten durch deinen Pfad).
$ cd <exercise-folder-location>
<exercise-folder-location> und die meisten Dinge in spitzen Klammern stehen für einen Platzhalterwert.
Ein normaler Pfad oder Dateiname wird ohne Klammern geschrieben.
Zum Beispiel: /Users/janedoe/exercism/python/exercises/concept/chaitanas-colossal-coaster (auf *nix-Systemen), C:\Users\janedoe\exercism\python\exercises\practice\hello-world\ (unter Windows), myFolder oder my_file.py.
Die Datei, die du ausführen möchtest, endet normalerweise auf _test.py.
Diese Datei enthält die Tests für die Übungslösung, und es sind dieselben Tests, die auf der Website laufen, wenn eine Lösung hochgeladen wird.
Führe als Nächstes den folgenden Befehl in deinem Terminal aus und ersetze <exercise_test.py> durch den Speicherort/Namen der Testdatei:
$ python3 -m pytest -o markers=task <exercise_test.py>
==================== 7 passed in 0.08s ====================
Wenn du im obigen Befehl pytest -o markers=task nicht verwendest, kann es sein, dass du warnings über „unknown markers“ erhältst, wenn du einen Test ausführst, der unsere neue Syntax verwendet.
Um nicht bei jedem Test, den du ausführst, pytest -o markers=task eintippen zu müssen, kannst du eine Konfigurationsdatei pytest.ini verwenden, die du im obersten Verzeichnis des Python-Tracks herunterladen kannst: pytest.ini.
Du kannst auch deine eigene pytest.ini-Datei mit folgendem Inhalt erstellen:
[pytest]
markers =
task: A concept exercise task.
Wenn du diese Datei im Stammverzeichnis oder Arbeitsverzeichnis für Exercism-Übungen ablegst, werden die Marker registriert und die Warnungen verschwinden.
Mehr Informationen zu pytest-Markern findest du in der pytest-Dokumentation unter Markieren von Testfunktionen mit Attributen und in der pytest-Dokumentation unter Arbeiten mit benutzerdefinierten Markern.
Weitere Informationen zum Anpassen von pytest-Konfigurationen findest du in der pytest-Dokumentation unter Formate von Konfigurationsdateien
Wenn Tests fehlschlagen, gibt pytest den Text jedes fehlgeschlagenen Tests zusammen mit den erwarteten und tatsächlichen return-Werten an das Terminal aus.
Unten siehst du ein allgemeines Beispiel für einen fehlgeschlagenen Test:
$(my_venv) python3 -m pytest -o markers=task <exercise_test.py>
=================== FAILURES ====================
______________ name_of_failed_test ______________
# Test code inside of <exercise_test.py> that failed.
...
E TypeOfError: ReturnedValue != ExpectedValue
exercise_test.py:<line_of_failed_test>: TypeOfError
============ short test summary info ============
FAILED exercise_test.py::ExerciseTest::name_of_failed_test
========== 1 failed, 2 passed in 0.13s ==========
Wenn du genau festlegen möchtest, was pytest auf deinem Bildschirm ausgibt, findest du hier einige praktische Kommandozeilenargumente, mit denen du das Verhalten konfigurieren kannst.
-v]Mit dem Flag -v (verbose) erhältst du zusätzlich zu den fehlgeschlagenen Tests auch Umgebungsinformationen und eine Testzusammenfassung:
$(my_venv) python3 -m pytest -o markers=task -v exercises/<exercise_name>/<test_file_test.py>
======================================== test session starts ===========================================
platform darwin -- Python 3.9.0, pytest-6.2.5, -- /usr/local/envs/my_env/bin/python3
cachedir: .pytest_cache
metadata: {'Python': '3.9.0', 'Platform': 'macOS-10.14.6-x86_64-i386-64bit', 'Packages': {'pytest': '6.2.1'}, 'Plugins': {'subtests': '0.5.0', 'pylint': '0.18.0'}
rootdir: /Users/<user>/exercism/python, configfile: pytest.ini
plugins: subtests-0.5.0, pylint-0.18.0
collected 5 items
exercises/exercise-name/exercise_file_test.py::ExerciseNameTest::test_one FAILED [ 20%]
exercises/exercise-name/exercise_file_test.py::ExerciseNameTest::test_two FAILED
exercises/exercise-name/exercise_file_test.py::ExerciseNameTest::test_three PASSED [ 40%]
exercises/concept/exercise-name/exercise_file_test.py::ExerciseNameTest::test_four FAILED
exercises/concept/exercise-name/exercise_file_test.py::ExerciseNameTest::test_five PASSED [ 60%]
exercises/concept/exercise-name/exercise_file_test.py::ExerciseNameTest::test_six FAILED
exercises/concept/exercise-name/exercise_file_test.py::ExerciseNameTest::test_seven PASSED [ 80%]
exercises/concept/exercise-name/exercise_file_test.py::ExerciseNameTest::test_eight FAILED
exercises/concept/exercise-name/exercise_file_test.py::ExerciseNameTest::test_nine PASSED [100%]
================================================ FAILURES ======================================================
# Failed tests are then individually printed out below
.......
-x]Mit dem Flag -x laufen die Tests wie gewohnt, aber der Testlauf stoppt beim ersten fehlgeschlagenen Test.
Das hilft, wenn du jeweils nur eine einzelne Aufgabe oder einen einzelnen Testfehler debuggen möchtest:
$(my_venv) python3 -m pytest -o markers=task -x exercises/<exercise_name>/<test_file_test.py>
=================== FAILURES ====================
_______________ example_test_foo ________________
...
...
============ short test summary info ============
FAILED example_test.py::ExampleTest::example_test_foo
!!!!!!!!!!! stopping after 1 failures !!!!!!!!!!!
========== 1 failed, 5 passed in 0.28s ==========
--ff]Das Plugin pytest-cache merkt sich, welche Tests beim letzten pytest-Lauf fehlgeschlagen sind. Mit dem Flag --ff weist du pytest an, zuvor fehlgeschlagene Tests zuerst auszuführen und dann mit den restlichen Tests fortzufahren.
Das kann deine Testläufe beschleunigen, wenn du viele kleinere Korrekturen an einer bestimmten Aufgabe oder einer Gruppe von Eingaben vornimmst.
$(my_venv) python3 -m pytest -o markers=task --ff <example_file_test.py>
==================== 7 passed in 503s ====================
Wir empfehlen die folgenden Befehle, um dein Debugging einfacher und (möglicherweise) schneller zu machen:
Wechsle zuerst in das Verzeichnis der Übung, die du testen möchtest:
$(my_venv) cd path/to/exercise
Führe dann die Tests mit den zuvor erklärten Argumenten -x und--ff aus:
$(my_venv) python3 -m pytest -o markers=task -x --ff <example_file_test.py>
Damit wird deine Lösung getestet.
Wenn pytest auf einen fehlgeschlagenen Test stößt, stoppt das Programm und sagt dir, welcher Test fehlgeschlagen ist.
Wenn du Korrekturen vornimmst und den Test erneut ausführst, führt pytest zuerst den zuvor fehlgeschlagenen Test aus und fährt dann mit den restlichen Tests fort.
Wenn du „wie ein Profi debuggen“ möchtest, kannst du das Argument --pdb nach dem pytest-Befehl verwenden und in den integrierten Python-Debugger, PDB, einsteigen.
$(my_venv) python3 -m pytest -o markers=task -x --ff --pdb <example_file_test.py>
=============== 4 passed in 0.15s ===============
Wenn ein Test fehlschlägt, kannst du mit PDB deinen Code Schritt für Schritt durchgehen, den aktuellen Gültigkeitsbereich ansehen sowie die Werte von Variablen und die Signatur verschiedener Funktionen prüfen.
Weitere Details zum PDB-Modul findest du in der Python-Dokumentation zu PDB.
Außerdem sind die pytest-Dokumentation zu PDB und diese Anleitung von Real Python äußerst hilfreich.
Wenn du deine IDE um einige Tools erweitern möchtest, die dir beim Testen und Verbessern deines Codes helfen, schau dir die Seite Tools an. Dort stellen wir verschiedene IDEs, Editoren und einige nützliche Erweiterungen für Linting und Debugging vor.
Hinweis: Wenn du Python unter Windows mit dem PSF Installer installiert hast, lautet der Befehl py statt python3.
Jedes Mal, wenn du ein Modul ausführen willst, python3 -m einzutippen, kann etwas nervig werden.
Um das zu vermeiden, kannst du den Ordner Scripts deiner Python-Installation zu deinem PATH hinzufügen.
Wenn du nicht weißt, wo du Python installiert hast, führe den folgenden Befehl in deinem Terminal aus:
$ python3 -c "import os, sys; print(os.path.dirname(sys.executable))"
<python_directory>
Das zurückgegebene Verzeichnis ist der Ort, an dem deine aktuell aktive Python-Version installiert ist; in diesem Abschnitt wird es als <python_directory> bezeichnet.
Klicke auf die Schaltfläche Windows Start, suche nach Edit the system environment variables und drücke die Eingabetaste.
Drücke dann auf Environment Variables...:

Suche dann in deinen User variables die Variable Path, wähle sie aus und klicke auf Edit...:

Füge dann, wie im Bild gezeigt, eine neue Zeile hinzu und ersetze <python_directory> durch das Verzeichnis deiner Python-Installation:

Das Folgende sollte für die meisten Linux- und MacOS-Varianten mit einer bash-Shell funktionieren.
Die Befehle können je nach Linux-Distribution und danach variieren, ob eine fish- oder zsh-Shell verwendet wird.
Ersetze <python_directory> durch die Ausgabe von python3 -c "import os, sys; print(os.path.dirname(sys.executable))"
export PATH="$PATH:<python_directory>"