Gyakorlat
Ebben a gyakorlatban a Pytest használatával tesztel egy függvényt. Ezután megkereshet és kijavíthat néhány lehetséges problémát a függvénysel kapcsolatban, amelyek sikertelen teszteket okoznak. A hibák vizsgálata és a Pytest részletes hibajelentésének használata elengedhetetlen a problémás tesztek vagy hibák azonosításához és javításához az éles kódban.
Ebben a gyakorlatban egy úgynevezett admin_command() függvényt használunk, amely bemenetként elfogad egy rendszerparancsot, és opcionálisan előtagot ad az sudo eszközhöz. A függvénynek van egy hibája, amelyet tesztek írásával fedezhet fel.
1. lépés – A gyakorlathoz tartozó teszteket tartalmazó fájl hozzáadása
A Python fájlnév-konvencióit használva a tesztfájlokhoz hozzon létre egy új tesztfájlt. Nevezze el a tesztfájlt test_exercise.py , és adja hozzá a következő kódot:
def admin_command(command, sudo=True): """ Prefix a command with `sudo` unless it is explicitly not needed. Expects `command` to be a list. """ if sudo: ["sudo"] + command return commandA függvény
admin_command()egy listát vesz fel bemenetként azcommandargumentum használatával, és opcionálisan előtagotsudois adhat a listának. Ha asudokulcsszóargumentum értéke be van állítvaFalse, akkor ugyanazt a parancsot adja vissza, mint a bemenet.Ugyanebben a fájlban fűzze hozzá a függvény tesztjeit
admin_command(). A tesztek egy segédmetódust használnak, amely egy mintaparancsot ad vissza:class TestAdminCommand: def command(self): return ["ps", "aux"] def test_no_sudo(self): result = admin_command(self.command(), sudo=False) assert result == self.command() def test_sudo(self): result = admin_command(self.command(), sudo=True) expected = ["sudo"] + self.command() assert result == expected
Feljegyzés
Nem gyakori, hogy a tesztek ugyanabban a fájlban vannak, mint a tényleges kód. Az egyszerűség kedvéért az ebben a gyakorlatban szereplő példák tényleges kóddal rendelkeznek ugyanabban a fájlban. A valós Python-projektekben a teszteket általában fájlok és könyvtárak választják el a tesztelt kódtól.
2. lépés – A tesztek futtatása és a hiba azonosítása
Most, hogy a tesztfájl rendelkezik egy tesztelendő függvénnyel és néhány teszttel a viselkedésének ellenőrzéséhez, ideje futtatni a teszteket, és hibákkal dolgozni.
Hajtsa végre a fájlt a Pythonnal:
$ pytest test_exercise.pyA futtatásnak egy teszttel és egy hibával kell befejeződnie, a hiba kimenetének pedig az alábbi kimenethez hasonlónak kell lennie:
=================================== FAILURES =================================== __________________________ TestAdminCommand.test_sudo __________________________ self = <test_exercise.TestAdminCommand object at 0x10634c2e0> def test_sudo(self): result = admin_command(self.command(), sudo=True) expected = ["sudo"] + self.command() > assert result == expected E AssertionError: assert ['ps', 'aux'] == ['sudo', 'ps', 'aux'] E At index 0 diff: 'ps' != 'sudo' E Right contains one more item: 'aux' E Use -v to get the full diff test_exercise.py:24: AssertionError =========================== short test summary info ============================ FAILED test_exercise.py::TestAdminCommand::test_sudo - AssertionError: assert... ========================= 1 failed, 1 passed in 0.04s ==========================A kimenet sikertelen a
test_sudo()teszten. A Pytest részletesen ismerteti az összehasonlítandó két listát. Ebben az esetben aresultváltozóban nincs meg asudoparancs, amit a teszt elvár.
3. lépés – A hiba kijavítása és a tesztek sikeressé tétele
Mielőtt bármilyen módosítást végez, először meg kell értenie, hogy miért van hiba. Bár láthatja, hogy a várakozás nem teljesül (sudo nem az eredmény), meg kell tudnia, hogy miért.
A feltétel teljesülése esetén admin_command() tekintse meg a sudo=True függvény következő kódsorait:
if sudo:
["sudo"] + command
A listák művelete nem az érték visszaadására szolgál. Mivel a függvény nem adja vissza, a függvény a parancsot sudo nem mindig adja vissza.
Frissítse a függvényt
admin_command()a listaművelet visszaadásához, hogy a rendszer a módosított eredményt használja egysudoparancs kérésekor. A frissített függvénynek így kell kinéznie:def admin_command(command, sudo=True): """ Prefix a command with `sudo` unless it is explicitly not needed. Expects `command` to be a list. """ if sudo: return ["sudo"] + command return commandFuttassa újra a tesztet a Pytesttel. Próbálja meg növelni a kimenet részletességét a
-vPytest jelölőjével:$ pytest -v test_exercise.pyMost ellenőrizze a kimenetet. Most két sikeres tesztet kell mutatnia:
============================= test session starts ============================== Python 3.9.6, pytest-6.2.5, py-1.11.0, pluggy-1.0.0 cachedir: .pytest_cache rootdir: /private collected 2 items test_exercise.py::TestAdminCommand::test_no_sudo PASSED [ 50%] test_exercise.py::TestAdminCommand::test_sudo PASSED [100%] ============================== 2 passed in 0.00s ===============================
Feljegyzés
Mivel a függvény több különböző burkolatú értékkel is képes dolgozni, további tesztekkel kell kiegészíteni ezeket a változatokat. Ez megakadályozhatja, hogy a függvény jövőbeli módosításai eltérő (váratlan) viselkedést okozzanak.
4. lépés – Új kód hozzáadása tesztekkel
Miután hozzáadta a teszteket az előző lépésekben, nyugodtan módosíthatja a függvényt, és tesztekkel ellenőrizheti őket. Még ha a meglévő tesztek nem is fedik le a módosításokat, biztos lehet abban, hogy nem szakítja meg a korábbi feltételezéseket.
Ebben az esetben a admin_command() függvény vakon bízik abban, hogy az command argumentum mindig lista. Ezt úgy javíthatjuk, hogy egy hasznos hibaüzenettel rendelkező kivételt emelünk ki.
Először hozzon létre egy tesztet, amely rögzíti a viselkedést. Bár a függvény még nem frissül, próbálkozzon egy első tesztalapú megközelítéssel (más néven tesztalapú fejlesztéssel vagy TDD-vel).
- Frissítse a test_exercise.py fájlt úgy, hogy felülről importálja
pytest. Ez a teszt egy belső segítőt használ apytestkeretrendszerből:
import pytest- Most fűzjön hozzá egy új tesztet az osztályhoz a kivétel ellenőrzéséhez. Ennek a tesztnek a függvénytől kell várnia,
TypeErrorha az átadott érték nem lista:
def test_non_list_commands(self): with pytest.raises(TypeError): admin_command("some command", sudo=True)- Frissítse a test_exercise.py fájlt úgy, hogy felülről importálja
Futtassa újra a teszteket a Pytest használatával. Mindannyiuknak át kell mennie.
============================= test session starts ============================== Python 3.9.6, pytest-6.2.5, py-1.11.0, pluggy-1.0.0 rootdir: /private/ collected 3 items test_exercise.py ... [100%] ============================== 3 passed in 0.00s ===============================A teszt elég jó ahhoz, hogy ellenőrizze
TypeError, de jó lenne hozzáadni a kódot egy hasznos hibaüzenettel.Frissítse a függvényt
TypeError, hogy egy hasznos hibaüzenettel explicit módon emelje fel a függvényt:def admin_command(command, sudo=True): """ Prefix a command with `sudo` unless it is explicitly not needed. Expects `command` to be a list. """ if not isinstance(command, list): raise TypeError(f"was expecting command to be a list, but got a {type(command)}") if sudo: return ["sudo"] + command return commandVégül frissítse a metódust a
test_non_list_commands()hibaüzenet ellenőrzéséhez:def test_non_list_commands(self): with pytest.raises(TypeError) as error: admin_command("some command", sudo=True) assert error.value.args[0] == "was expecting command to be a list, but got a <class 'str'>"A frissített teszt változóként használja
erroraz összes kivételinformációt. A használatávalerror.value.argsmegvizsgálhatja a kivétel argumentumait. Ebben az esetben az első argumentum a teszt által ellenőrizhető hibasztringgel rendelkezik.
Ellenőrizze munkáját
Ekkor rendelkeznie kell egy Python-tesztfájllal test_exercise.py , amely a következőket tartalmazza:
- Argumentumot
admin_command()és kulcsszóargumentumot elfogadó függvény. - Kivétel
TypeErroregy hasznos hibaüzenettel aadmin_command()függvényben. - Egy
TestAdminCommand()tesztosztály, amely egycommand()segédmetódussal és három, a függvényt ellenőrző tesztmetódussal rendelkezikadmin_command().
A terminálon való futtatáskor az összes tesztnek hiba nélkül kell átesnie.