Osztályok és metódusok tesztelése
A tesztfüggvények írása mellett a Pytest osztályok használatát is lehetővé teszi. Ahogy már említettük, nincs szükség öröklésre, és a tesztosztályok néhány egyszerű szabályt követnek. Az osztályok használata nagyobb rugalmasságot és újrafelhasználhatóságot biztosít. Ahogy a következő látható, a Pytest elkerüli az utat, és elkerüli, hogy bizonyos módon írjon teszteket.
A függvényekhez hasonlóan az állítással assert is írhat állításokat.
Tesztosztály létrehozása
Használjunk egy valós forgatókönyvet, amelyből megtudhatjuk, hogyan segíthetnek a tesztosztályok. Az alábbi függvény ellenőrzi, hogy egy adott fájl tartalmaz-e igent a tartalmában. Ha igen, akkor visszaadja True. Ha a fájl nem létezik, vagy ha nemet tartalmaz a tartalmában, a visszaadja False. Ez a forgatókönyv gyakori azokban az aszinkron feladatokban, amelyek a fájlrendszert használják a befejezés jelzésére.
A függvény a következőképpen néz ki:
import os
def is_done(path):
if not os.path.exists(path):
return False
with open(path) as _f:
contents = _f.read()
if "yes" in contents.lower():
return True
elif "no" in contents.lower():
return False
Most az alábbi módon néz ki egy osztály két teszttel (mindegyik feltételhez egyet) egy test_files.py nevű fájlban:
class TestIsDone:
def test_yes(self):
with open("/tmp/test_file", "w") as _f:
_f.write("yes")
assert is_done("/tmp/test_file") is True
def test_no(self):
with open("/tmp/test_file", "w") as _f:
_f.write("no")
assert is_done("/tmp/test_file") is False
Figyelemfelhívás
A tesztmetódusok a /tmp elérési utat használják egy ideiglenes tesztfájlhoz, mert a példában könnyebben használható. Ha azonban ideiglenes fájlokat kell használnia, fontolja meg egy ilyen tempfile tár használatát, amely biztonságosan létrehozhatja (és eltávolíthatja) őket. Nem minden rendszer rendelkezik /tmp könyvtárral, és ez a hely nem lehet ideiglenes az operációs rendszertől függően.
A teszteknek a jelölővel való futtatása a -v részletesség növelése érdekében az átmenő teszteket mutatja:
pytest -v test_files.py
============================= 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_files.py::TestIsDone::test_yes PASSED [ 50%]
test_files.py::TestIsDone::test_no PASSED [100%]
============================== 2 passed in 0.00s ===============================
Bár a tesztek haladnak, ismétlődőnek tűnnek, és a teszt elvégzése után a fájlokat is elhagyják. Mielőtt megnéznénk, hogyan fejleszthetjük őket, a következő szakaszban foglalkozzunk segítő módszerekkel.
Segédmetenek
Egy tesztosztályban néhány módszer használható a teszt végrehajtásának beállítására és leállítására. A Pytest automatikusan végrehajtja őket, ha definiálva vannak. Ezeknek a módszereknek a használatához tudnia kell, hogy egy adott sorrendben és viselkedésben vannak.
-
setup: Egy osztály minden tesztje előtt egyszer hajtja végre. -
teardown: Egy osztály minden tesztje után egyszer hajtja végre. -
setup_class: Egy osztály összes tesztje előtt egyszer hajtja végre. -
teardown_class: Egy osztály összes tesztje után egyszer hajtja végre.
Ha a tesztekhez hasonló (vagy azonos) erőforrásokra van szükség, hasznos a beállítási módszerek írása. Ideális esetben a teszt nem hagyhatja el az erőforrásokat, amikor befejeződik, így a lebontási módszerek segíthetnek a tesztek megtisztításában ezekben a helyzetekben.
Felesleges tartalmak törlése
Tekintsünk meg egy frissített tesztosztályt, amely megtisztítja a fájlokat az egyes tesztek után:
class TestIsDone:
def teardown(self):
if os.path.exists("/tmp/test_file"):
os.remove("/tmp/test_file")
def test_yes(self):
with open("/tmp/test_file", "w") as _f:
_f.write("yes")
assert is_done("/tmp/test_file") is True
def test_no(self):
with open("/tmp/test_file", "w") as _f:
_f.write("no")
assert is_done("/tmp/test_file") is False
Mivel a módszert használtuk, ez a teardown() tesztosztály már nem hagy hátra / tmp/test_file .
Beállítás
Ebben az osztályban egy másik fejlesztés, ha hozzáadunk egy változót, amely a fájlra mutat. Mivel a fájl most már hat helyen deklarálva van, az elérési út módosítása azt jelentené, hogy az összes helyen módosítják. Ez a példa bemutatja, hogyan néz ki az osztály egy hozzáadott setup() metódussal, amely deklarálja az elérési út változót:
class TestIsDone:
def setup(self):
self.tmp_file = "/tmp/test_file"
def teardown(self):
if os.path.exists(self.tmp_file):
os.remove(self.tmp_file)
def test_yes(self):
with open(self.tmp_file, "w") as _f:
_f.write("yes")
assert is_done(self.tmp_file) is True
def test_no(self):
with open(self.tmp_file, "w") as _f:
_f.write("no")
assert is_done(self.tmp_file) is False
Egyéni segítő metódusok
Egyéni segédmetórát hozhat létre egy osztályban. Ezeket a metódusokat nem szabad a névvel test előtaggal elnevezni, és nem nevezhetők el beállítási vagy törlési metódusként. Az osztályban TestIsDone automatizálhatjuk az ideiglenes fájl létrehozását egy egyéni segédben. Az egyéni segédmetódus a következő példához hasonlóan nézhet ki:
def write_tmp_file(self, content):
with open(self.tmp_file, "w") as _f:
_f.write(content)
A Pytest nem hajtja végre automatikusan a write_tmp_file() metódust, és más metódusok közvetlenül meghívhatják az ismétlődő feladatok mentéséhez, például egy fájlba való íráshoz.
Az egész osztály a következő példához hasonlóan néz ki, miután frissítette a tesztelési módszereket az egyéni segéd használatára:
class TestIsDone:
def setup(self):
self.tmp_file = "/tmp/test_file"
def teardown(self):
if os.path.exists(self.tmp_file):
os.remove(self.tmp_file)
def write_tmp_file(self, content):
with open(self.tmp_file, "w") as _f:
_f.write(content)
def test_yes(self):
self.write_tmp_file("yes")
assert is_done(self.tmp_file) is True
def test_no(self):
self.write_tmp_file("no")
assert is_done(self.tmp_file) is False
Mikor érdemes osztályt használni függvény helyett?
Nincsenek szigorú szabályok arra, hogy mikor érdemes osztályt használni függvény helyett. Mindig érdemes követni az aktuális projektek és csapatok konvencióit, amelyekkel dolgozik. Íme néhány általános kérdés, amely segíthet meghatározni, hogy mikor érdemes osztályt használni:
- A tesztekhez hasonló beállítási vagy törlési segédkódra van szükség?
- Logikus értelme van a tesztek csoportosításának?
- Van legalább néhány teszt a tesztcsomagban?
- Hasznos lehet a teszteknek a segédfüggvények közös készlete?