Úvod do testovania kódu Pythonu pomocou PyTestu
PyTest je populárna testovacia knižnica pre Python. Je to jednoduchý, ľahko použiteľný testovací rámec, ktorý vám umožňuje písať a vykonávať testy pre váš kód v jazyku Python. Tu je stručný úvod do používania PyTestu.

Test je kód, ktorý vykonáva kód. Keď začnete vyvíjať novú funkciu pre svoj projekt v jazyku Python, môžete jej požiadavky formalizovať ako kód. Keď to urobíte, nielenže zdokumentujete spôsob, akým sa má kód vašej implementácie používať, ale môžete tiež automaticky spustiť všetky testy, aby ste sa vždy uistili, že váš kód zodpovedá vašim požiadavkám. Jedným z takýchto nástrojov, ktorý vám pri tom pomáha, je pytest
a je to pravdepodobne najpopulárnejší testovací nástroj vo vesmíre Pythonu.
Je to všetko o assert
Predpokladajme, že ste napísali funkciu, ktorá overuje e-mailovú adresu. Všimnite si, že tu zostaneme jednoduchí a na overovanie e-mailových adries nepoužijeme regulárne výrazy ani testovanie DNS. Namiesto toho sa len uistíme, že sa v testovanom reťazci nachádza presne jeden znak @
a iba znaky latinky, čísla a znaky .
, -
a _
.
|
|
Teraz máme v našom kóde niekoľko potvrdení. Napríklad tvrdíme, že tieto e-mailové adresy sú platné:
Na druhej strane by sme očakávali, že naša funkcia vráti False pre e-mailové adresy ako:
not [email protected]
- obsahuje medzerujohn.doe
chýbajúci znak @john,[email protected]
obsahuje čiarku
Môžeme skontrolovať, či sa naša funkcia skutočne správa tak, ako očakávame:
|
|
Tieto príklady e-mailových adries, ktoré sme vymysleli, sa nazývajú testovacie prípady. Pre každý testovací prípad očakávame určitý výsledok. Nástroj ako pytest
môže pomôcť automatizovať testovanie týchto tvrdení. Zapísanie týchto tvrdení vám môže pomôcť:
- zdokumentovať, ako sa bude váš kód používať
- uistiť sa, že budúce zmeny nerozbijú iné časti vášho softvéru
- premýšľať o možných okrajových prípadoch vašich funkcií
Aby sme to dokázali, stačí vytvoriť nový súbor pre všetky naše testy a vložiť doň niekoľko funkcií.
|
|
Spustenie testov
Jednoduchý príklad
V adresári projektu máme dva súbory: validator.py
a test_validator.py
.
Teraz môžeme jednoducho spustiť pytest
z príkazového riadku. Jeho výstup by mal vyzerať približne takto:
|
|
Tu nás pytest
informuje, že našiel tri testovacie funkcie vo vnútri súboru test_validator.py
a že všetky tieto funkcie boli odovzdané (ako je označené tromi bodkami ...
).
Indikátor 100%
nám dáva dobrý pocit, pretože sme si istí, že náš validátor funguje podľa očakávania. Ako sme však načrtli v úvode, funkcia validátora má ďaleko od dokonalosti. Rovnako ako naše testovacie prípady. Aj bez testovania DNS by sme e-mailovú adresu ako [email protected]
označili za platnú, zatiaľ čo adresa ako [email protected]
by bola označená za neplatnú.
Pridajme teraz tieto testovacie prípady do nášho súboru test_validator.py
|
|
Ak znovu spustíme pytest
, uvidíme neúspešné testy:
|
|
Všimnite si, že okrem troch bodiek ...
sme dostali aj dve FF
, ktoré znamenajú, že dve testovacie funkcie zlyhali.
Okrem toho sme vo výstupe získali novú časť FAILURES
, ktorá podrobne vysvetľuje, v ktorom bode náš test zlyhal. To je dosť užitočné pri ladení.
Navrhovanie testov
Náš malý príklad validátora je dôkazom dôležitosti navrhovania testov.
Najprv sme napísali našu funkciu validátora a potom sme pre ňu vymysleli niekoľko testovacích prípadov. Čoskoro sme si všimli, že tieto testovacie prípady nie sú v žiadnom prípade komplexné. Naopak, vynechali sme niektoré podstatné aspekty validácie e-mailovej adresy.
Možno ste už počuli o Test Driven Development (TDD), ktorý presadzuje presný opak: TDD je princíp, ktorý hovorí o správnom nastavení požiadaviek tým, že najprv napíšete testovacie prípady a nezačnete implementovať funkciu skôr, než budete mať pocit, že ste pokryli všetky testovacie prípady. Tento spôsob myslenia bol vždy dobrou myšlienkou, ale postupom času nadobudol ešte väčší význam, pretože softvérové projekty sa stali zložitejšími.
O TDD napíšem čoskoro ďalší blogový príspevok, v ktorom sa mu budem venovať podrobnejšie.
Konfigurácia
Nastavenie projektu je zvyčajne oveľa zložitejšie ako len jeden súbor s funkciou validátora.
Možno máte pre svoj projekt štruktúru balíkov Python alebo váš kód závisí od externých závislostí, napríklad od databázy.
Fixtures
Pojem fixture ste možno použili v rôznych kontextoch. Napríklad v prípade webového frameworku Django sa fixtures vzťahujú na kolekciu počiatočných údajov, ktoré sa majú načítať do databázy. V kontexte pytestu
sa však fixtures vzťahujú len na funkcie spúšťané pomocou pytestu
pred a/alebo po skutočných testovacích funkciách.
Nastavenie a zrušenie
Takéto funkcie môžeme vytvoriť pomocou dekorátora pytest.fixture()
. Zatiaľ to robíme vo vnútri súboru test_validator.py
.
|
|
Všimnite si, že nastavenie databázy a jej zrušenie prebieha v tom istom prídavnom zariadení. Kľúčové slovo yield
označuje časť, v ktorej pytest
vykonáva skutočné testy.
Ak chcete, aby bol fixture skutočne použitý niektorým z vašich testov, stačí pridať názov fixture ako argument, napríklad takto (stále v súbore test_validator.py
):
|
|
Získavanie údajov zo zariadení
Namiesto použitia funkcie yield
môže funkcia fixture vrátiť ľubovoľné hodnoty:
|
|
Opäť platí, že vyžiadanie tohto prípravku z testovacej funkcie sa vykoná zadaním názvu prípravku ako parametra:
|
|
Konfiguračné súbory
pytest
môže čítať svoju konfiguráciu špecifickú pre projekt z jedného z týchto súborov:
pytest.ini
tox.ini
setup.cfg
Ktorý súbor použijete, závisí od toho, aké ďalšie nástroje môžete vo svojom projekte použiť. Ak ste svoj projekt zabalili, mali by ste použiť súbor setup.cfg
. Ak používate tox na testovanie vášho kódu v rôznych prostrediach, môžete umiestniť konfiguráciu pytest
do súboru tox.ini
. Súbor pytest.ini
sa môže použiť, ak nechcete využívať žiadne ďalšie nástroje, ale pytest
.
Konfiguračný súbor vyzerá väčšinou rovnako pre každý z týchto troch typov súborov:
Používanie súborov pytest.ini a tox.ini
|
|
Ak používate súbor setup.cfg, jediný rozdiel spočíva v tom, že sekciu [pytest]
musíte predradiť slovom tool:
:
|
|
conftest.py
Každý priečinok obsahujúci testovacie súbory môže obsahovať súbor conftest.py
, ktorý načíta pytest
. Toto je dobré miesto na umiestnenie vlastných prípravkov, pretože by sa mohli zdieľať medzi rôznymi testovacími súbormi.
Súbor(-y) conftest.py
môže(-ú) meniť správanie nástroja pytest
na základe jednotlivých projektov.
Okrem zdieľaných fixtures by ste mohli umiestniť externé háčiky a zásuvné moduly alebo modifikátory pre PATH
, ktoré používa pytest
na zisťovanie testov a implementačného kódu.
CLI / PDB
Počas vývoja, hlavne keď píšete testy pred implementáciou, môže byť pytest
užitočným nástrojom na ladenie.
Pozrieme sa na najužitočnejšie možnosti príkazového riadka.
Spustenie iba jedného testu
Ak chcete spustiť len jeden konkrétny test, môžete sa naň odvolať prostredníctvom súboru test_
, v ktorom sa nachádza, a názvu funkcie:
|
|
Iba zber
Niekedy chcete mať k dispozícii len zoznam testovacej kolekcie, a nie vykonávať všetky testovacie funkcie.
|
|
Ukončenie pri prvej chybe
Môžete prinútiť pytest
, aby po neúspešnom teste zastavil vykonávanie ďalších testov:
|
|
Spustite iba posledný neúspešný test
Ak chcete spustiť len testy, ktoré naposledy zlyhali, môžete to urobiť pomocou príznaku --lf
:
|
|
Spustite všetky testy, ale najprv spustite posledné neúspešné testy
|
|
Zobrazenie hodnôt lokálnych premenných vo výstupe
Ak nastavíme zložitejšiu testovaciu funkciu s niektorými lokálnymi premennými, môžeme príznakom -l
dať príkaz pytest
, aby tieto lokálne premenné zobrazil.
Prepíšeme našu testovaciu funkciu takto:
|
|
Potom,
|
|
nám poskytne tento výstup:
|
|
Používanie pytestu s debuggerom
V Pythone je zabudovaný debugger príkazového riadku s názvom pdb
. Pomocou pytest
môžete ladiť kód svojej testovacej funkcie.
Ak spustíte pytest
s príkazom --pdb
, spustí sa relácia ladenia pdb
hneď po vyvolaní výnimky vo vašom teste. Väčšinou to nie je veľmi užitočné, pretože možno budete chcieť skontrolovať každý riadok kódu pred vyvolanou výnimkou.
Ďalšou možnosťou je príznak --trace
pre pytest
, ktorý nastaví bod prerušenia na prvom riadku každej funkcie testu. To sa môže stať trochu nepohodlné, ak máte veľa testov. Takže na účely ladenia je dobrá kombinácia --lf --trace
, ktorá spustí reláciu ladenia s pdb
na začiatku posledného testu, ktorý zlyhal:
|
|
CI / CD
V moderných softvérových projektoch sa softvér vyvíja podľa princípov Test Driven Development a dodáva prostredníctvom kontinuálnej integrácie / kontinuálneho nasadenia, ktoré zahŕňa automatizované testovanie.
Typické nastavenie je také, že revízie do vetvy main/master
sú zamietnuté, pokiaľ všetky testovacie funkcie neprejdú.
Ak sa chcete dozvedieť viac o používaní pytestu
v prostredí CI/CD, zostaňte naladení, pretože na túto tému plánujem nový článok.
Dokumentácia
Oficiálna dokumentácia pre pytest
je tu: https://docs.pytest.org
Krátka poznámka:
Toto je repost pôvodného článku od Bas Steins, ktorý bol vytvorený s jeho súhlasom. Ďalšie články nájdete na jeho stránke a/alebo ho sledujte na Twitteri: @bascodes