Δοκιμές στη διαδρομή Python

Μάθε πώς να δοκιμάζεις τις ασκήσεις σου σε Python στο Exercism.


Χρησιμοποιούμε το pytest ως εργαλείο εκτέλεσης δοκιμών για τον ιστότοπό μας. Θα χρειαστεί να εγκαταστήσεις το pytest στον υπολογιστή ανάπτυξής σου, αν θέλεις να κατεβάσεις και να εκτελέσεις τοπικά τις δοκιμές των ασκήσεων για το Python track. Θα πρέπει επίσης να εγκαταστήσεις τα ακόλουθα πρόσθετα του pytest:

Σου προτείνουμε επίσης να χρησιμοποιήσεις το πρόγραμμα ελέγχου κώδικα pylint, καθώς αποτελεί μέρος της αυτοματοποιημένης ανατροφοδότησης στον ιστότοπό μας και μπορεί να είναι ένα πολύ χρήσιμο εργαλείο στατικής ανάλυσης κώδικα. Για ευκολία στη χρήση, το πρόσθετο pytest-pylint για το pytest σου επιτρέπει να εκτελείς το pylint μέσω του pytest από τη γραμμή εντολών.

Η ρύθμιση του Pylint μπορεί να είναι λίγο βαριά, οπότε αυτό το σεμινάριο από το pylint.readthedocs.io μπορεί να σε βοηθήσει να ξεκινήσεις, όπως και αυτή η επισκόπηση του Code Quality: Tools and Best Practices από το Real Python.

Εγκατάσταση του pytest

Το pytest μπορεί να εγκατασταθεί και να ενημερωθεί με το ενσωματωμένο βοηθητικό πρόγραμμα της Python pip.

Για επιπλέον συμβουλές, ο Brett Cannon έχει έναν ωραίο γρήγορο και πρόχειρο οδηγό για το πώς να εγκαθιστάς πακέτα για την Python, μαζί με μια εξαιρετική εξήγηση για το γιατί πρέπει να χρησιμοποιείς το python -m pip. Για περισσότερα σχετικά με τα ορίσματα γραμμής εντολών της Python, δες το command line and environment στην τεκμηρίωση της Python.

Σημείωση: Το Python3 και το py μπορεί να είναι ή να μην είναι ψευδώνυμα για την Python στο σύστημά σου. Προσάρμοσε ανάλογα τις εντολές εγκατάστασης παρακάτω. Για να εγκαταστήσεις το pytest σε ένα εικονικό περιβάλλον, βεβαιώσου ότι το περιβάλλον είναι ενεργοποιημένο πριν εκτελέσεις εντολές. Διαφορετικά, η εγκατάσταση του pytest θα γίνει καθολικά.

Windows

PS C:\Users\foobar> py -m pip install pytest pytest-cache pytest-subtests pytest-pylint
Successfully installed pytest-8.3.3 ...

Linux / MacOS

$ python3 -m pip install pytest pytest-cache pytest-subtests pytest-pylint
Successfully installed pytest-8.3.3 ...

Για να ελέγξεις αν η εγκατάσταση ήταν επιτυχής:

$ python3 -m pytest --version
pytest 8.3.3

Εκτέλεση των δοκιμών

Για να εκτελέσεις τις δοκιμές, πήγαινε στον φάκελο όπου είναι αποθηκευμένη η άσκηση χρησιμοποιώντας cd στο τερματικό σου (αντικατέστησε το <exercise-folder-location> παρακάτω με τη διαδρομή σου).

$ cd <exercise-folder-location>

Note

<exercise-folder-location> ή τα περισσότερα πράγματα μέσα σε γωνιακές αγκύλες δηλώνουν μια τιμή κράτησης θέσης. Ένα κανονικό μονοπάτι ή όνομα αρχείου πρέπει να γράφεται χωρίς αγκύλες.

Για παράδειγμα: /Users/janedoe/exercism/python/exercises/concept/chaitanas-colossal-coaster (σε συστήματα *nix), C:\Users\janedoe\exercism\python\exercises\practice\hello-world\ (στα Windows), myFolder ή my_file.py.


Το αρχείο που θα θελήσεις να εκτελέσεις συνήθως τελειώνει σε _test.py. Αυτό το αρχείο περιέχει τις δοκιμές για τη λύση της άσκησης και είναι οι ίδιες δοκιμές που εκτελούνται στον ιστότοπο όταν ανεβαίνει μια λύση. Στη συνέχεια, εκτέλεσε την ακόλουθη εντολή στο τερματικό σου, αντικαθιστώντας το <exercise_test.py> με τη θέση/όνομα του αρχείου δοκιμών:

$ python3 -m pytest -o markers=task <exercise_test.py>
==================== 7 passed in 0.08s ====================

Διόρθωση προειδοποιήσεων

Αν δεν χρησιμοποιήσεις το pytest -o markers=task στην παραπάνω εντολή, είναι πιθανό να λάβεις warnings για "unknown markers" όταν εκτελείς μια δοκιμή που χρησιμοποιεί τη νέα σύνταξή μας.

Για να μην πληκτρολογείς pytest -o markers=task σε κάθε δοκιμή που εκτελείς, μπορείς να χρησιμοποιήσεις ένα αρχείο ρυθμίσεων pytest.ini, το οποίο μπορείς να κατεβάσεις από το ανώτερο επίπεδο του καταλόγου του Python track: pytest.ini.

Μπορείς επίσης να δημιουργήσεις το δικό σου αρχείο pytest.ini με το παρακάτω περιεχόμενο:

[pytest]
markers =
    task: A concept exercise task.

Αν τοποθετήσεις αυτό το αρχείο στον ριζικό ή στον τρέχοντα κατάλογο εργασίας για τις ασκήσεις του Exercism, θα καταχωρηθούν τα marks και θα σταματήσουν οι προειδοποιήσεις. Περισσότερες πληροφορίες για τα marks του pytest μπορείς να βρεις στην τεκμηρίωση του pytest για το marking test functions with attributes και στην τεκμηρίωση του pytest για το working with custom markers.

Περισσότερες πληροφορίες για την προσαρμογή των ρυθμίσεων του pytest μπορείς να βρεις στην τεκμηρίωση του pytest για τις configuration file formats

Αποτυχίες δοκιμών

Όταν οι δοκιμές αποτυγχάνουν, το pytest εκτυπώνει στο τερματικό το κείμενο κάθε αποτυχημένης δοκιμής, μαζί με την αναμενόμενη και την πραγματική return τιμή της καθεμιάς. Παρακάτω υπάρχει ένα γενικό παράδειγμα μιας αποτυχημένης δοκιμής:

$(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 ==========

Επιπλέον ορίσματα

Αν θέλεις πραγματικά να προσδιορίσεις με ακρίβεια τι εμφανίζει το pytest στην οθόνη σου, ορίστε μερικά χρήσιμα ορίσματα γραμμής εντολών που σου επιτρέπουν να ρυθμίσεις τη συμπεριφορά του.

Επιστροφή όλων των λεπτομερειών [-v]

Προσθέτοντας το όρισμα -v (verbose), θα λάβεις και πληροφορίες περιβάλλοντος και μια σύνοψη των δοκιμών, επιπλέον των αποτυχιών:

$(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]

Χρησιμοποιώντας το όρισμα -x, οι δοκιμές θα εκτελεστούν κανονικά, αλλά η εκτέλεση θα σταματήσει στην πρώτη αποτυχία δοκιμής. Αυτό βοηθάει όταν θέλεις να κάνεις debug σε μία μόνο εργασία ή αποτυχία δοκιμής τη φορά:

$(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]

Το πρόσθετο pytest-cache θυμάται ποιες δοκιμές απέτυχαν την τελευταία φορά που έτρεξες το pytest, οπότε χρησιμοποιώντας το όρισμα --ff λες στο pytest να εκτελέσει πρώτα τις δοκιμές που απέτυχαν προηγουμένως και μετά να συνεχίσει με τις υπόλοιπες. Αυτό μπορεί να επιταχύνει τις δοκιμές σου, αν κάνεις πολλές μικρές διορθώσεις γύρω από μια συγκεκριμένη εργασία ή ένα σύνολο δεδομένων εισόδου.

$(my_venv) python3 -m pytest -o markers=task --ff <example_file_test.py>
==================== 7 passed in 503s ====================

Προτεινόμενη ροή εργασίας

Σου προτείνουμε να χρησιμοποιήσεις τις παρακάτω εντολές, για να κάνεις το debugging σου ευκολότερο και (πιθανώς) ταχύτερο:

Πρώτα, άλλαξε τον κατάλογο εργασίας σου στον κατάλογο της άσκησης που θέλεις να δοκιμάσεις:

$(my_venv) cd path/to/exercise

Στη συνέχεια, εκτέλεσε τις δοκιμές μαζί με τα ορίσματα -x και --ff που εξηγήσαμε παραπάνω:

$(my_venv) python3 -m pytest -o markers=task -x --ff <example_file_test.py>

Αυτό θα δοκιμάσει τη λύση σου. Όταν το pytest συναντήσει μια αποτυχημένη δοκιμή, το πρόγραμμα θα σταματήσει και θα σου πει ποια δοκιμή απέτυχε. Όταν κάνεις διορθώσεις και εκτελέσεις ξανά τις δοκιμές, το pytest θα εκτελέσει πρώτα την προηγούμενη δοκιμή που απέτυχε και μετά θα συνεχίσει με τις υπόλοιπες.

Χρήση του PDB, του αποσφαλματωτή της Python, με το pytest

Αν θέλεις να κάνεις "debug σαν επαγγελματίας", μπορείς να χρησιμοποιήσεις το όρισμα --pdb μετά την εντολή pytest και να μπεις στον ενσωματωμένο αποσφαλματωτή της Python, το PDB.

$(my_venv) python3 -m pytest -o markers=task -x --ff --pdb <example_file_test.py>
=============== 4 passed in 0.15s ===============

Όταν μια δοκιμή αποτυγχάνει, μπαίνοντας στο PDB θα μπορείς να διατρέξεις τον κώδικά σου βήμα προς βήμα, βλέποντας την τρέχουσα εμβέλεια, καθώς και να ελέγξεις την τιμή των μεταβλητών και την υπογραφή διαφόρων συναρτήσεων. Περισσότερες λεπτομέρειες για τη μονάδα PDB μπορείς να βρεις στην τεκμηρίωση της Python για το PDB. Επιπλέον, τα έγγραφα του pytest για το PDB και αυτός ο οδηγός από το Real Python είναι εξαιρετικά χρήσιμα.

Επέκταση του IDE σου

Αν θέλεις να επεκτείνεις το IDE σου με μερικά εργαλεία που θα σε βοηθήσουν να δοκιμάζεις και να βελτιώνεις τον κώδικά σου, δες τη σελίδα tools. Εκεί εξερευνούμε πολλά IDE, επεξεργαστές κειμένου και μερικές χρήσιμες επεκτάσεις για έλεγχο κώδικα και αποσφαλμάτωση.

Πρόσθετες πληροφορίες

Προσθήκη της Python στο PATH σου

Σημείωση: Αν εγκατέστησες την Python στα Windows μέσω του PSF Installer, τότε η εντολή θα είναι py και όχι python3.

Το να πληκτρολογείς python3 -m κάθε φορά που θέλεις να εκτελέσεις μια μονάδα μπορεί να γίνει λίγο εκνευριστικό. Για να το αποφύγεις, μπορείς να προσθέσεις τον φάκελο Scripts της εγκατάστασης της Python στη διαδρομή σου. Αν δεν ξέρεις πού έχεις εγκαταστήσει την Python, εκτέλεσε την ακόλουθη εντολή στο τερματικό σου:

$ python3 -c "import os, sys; print(os.path.dirname(sys.executable))"
<python_directory>

Ο κατάλογος που επιστρέφεται είναι εκεί όπου είναι εγκατεστημένη η τρέχουσα ενεργή έκδοση της Python, και σε αυτή την ενότητα αναφέρεται ως <python_directory>.

Windows

Κάνε κλικ στο κουμπί Windows Start και αναζήτησε το Edit the system environment variables και πάτησε Enter. Στη συνέχεια, πάτησε Environment Variables...:

Πάτησε το μπλε κουμπί, lol

Έπειτα, βρες τη μεταβλητή Path στις User variables σου, επίλεξέ τη και κάνε κλικ στο Edit...:

Επιλογή της μεταβλητής Path

Έπειτα, πρόσθεσε μια νέα γραμμή, όπως φαίνεται στην εικόνα, αντικαθιστώντας το <python_directory> με τον κατάλογο της εγκατάστασης της Python:

Προσθήκη της Python στη διαδρομή

MacOS/Linux

Τα παρακάτω θα πρέπει να λειτουργούν για τις περισσότερες διανομές Linux και εκδόσεις MacOS με κέλυφος bash. Οι εντολές μπορεί να διαφέρουν ανάλογα με τη διανομή Linux και με το αν χρησιμοποιείται κέλυφος fish ή zsh. Αντικατέστησε το <python_directory> με την έξοδο της εντολής python3 -c "import os, sys; print(os.path.dirname(sys.executable))"

export PATH="$PATH:<python_directory>"