4. diel - Testovanie v Pythone - Unit testy - Test analyzeru tagov
V minulej lekcii, Testovanie v Pythone - PyHamcrest a best practices , sme si predstavili knižnicu PyHamcrest, vysvetlili si očakávané chyby a nakoniec spomenuli aj best practices pre testovanie.
Aby sme nezostali len pri testoch našej kalkulačky, ukážeme si v niekoľkých ďalších lekciách kódy unit testov z reálnych aplikácií. Pôjde o testy analyzátora správ, perzistentné vrstvy (ukladanie dát) ao testy generátora náhodných tokenov. Pomôžu vám pre lepšiu predstavu ako sa takéto veci testujú v praxi.
Pozn.: Príklady budú mať postupne zložitejší a zložitejší kód. Nelámte si hlavu s tým, pokiaľ nebudete rozumieť niečomu v ich implementácii. Mali by ste pochytiť najmä spôsob testovania, teda čo ktorý test overuje a ako to overuje.
Test analyzeru tagov
Nasledujúci test overuje správnu funkčnosť triedyTestTagAnalyzer
. Tá analyzuje správu a hľadá v nej hashtagy,
ako ich poznáte napr. z Facebooku ("Zas som zaspal. #pondelky").
Štruktúra testovacej triedy
Ukážme si základnú štruktúru testovacej triedy s inicializáciou a popíšme si ju nižšie:import unittest import re class TestTagAnalyzer(unittest.TestCase): msg_no_tags = "Nějaká zpráva standardní délky neobsahující žádné tagy." msg_single_tag = "Zpráva obsahující jeden #tag." msg_only_tags = "#zprava #sestavena #z #tagu." msg_hashes = "######################" dict_no_tags = {msg_no_tags: []} dict_single_tag = {msg_single_tag: ['tag']} dict_only_tags = {msg_only_tags: ['zprava', 'sestavena', 'z', 'tagu']} dict_hashes = {msg_hashes: []}
Vidíme, že trieda deklaruje 4 testovacie správy. Prvú úplne bez hashtagov, druhú s jedným hashtagom na konci, tretiu vytvorenú len z hashtagov a štvrtú zloženú iba z hashkrížov. Túto praktiku sme si už spomínali, ak by sme všetko testovali len na jednej obyčajnej správe, mohlo by sa stať, že by analyzer zle fungoval v medzných prípadoch. To sú prípady, keď v správe nie je žiadny hashtag alebo je naopak plná hashtagov. Tu počítame aj so situáciou, kedy sú použité znaky pre hashtagy, ale nejde o skutočný hashtag. Všetky tieto situácie by mal testovaný analyzer zvládnuť.
Pre každú správu si následne vytvoríme zoznam tagov, ktoré v nej má
analyzer nájsť. Na to slúžia slovníky. Ako kľúče v slovníkoch
použijeme jednoducho jednotlivé správy. A ako hodnoty k nim vytvoríme zoznam
tagov, ktoré by v nich analyzer mal nájsť. V prvej správe žiadne tagy nie
sú, v tej druhej je tag " tag
", v tretej sú tagy "
zprava
", " sestavena
", " z
", "
tagu
". V tej poslednej opäť žiadne tagy nie sú.
Testovacie metódy
To by bolo k inicializácii, presuňme sa k samotným testom. Opäť si najskôr ukážme zdrojový kód:def test_analyze_tags_no_tags(self): tag_list = re.findall(r'#([a-z0-9]+)', self.msg_no_tags) expected = self.dict_no_tags[self.msg_no_tags] assert tag_list is not None assert tag_list == [] def test_analyze_tags_single_tag(self): tag_list = re.findall(r'#([a-z0-9]+)', self.msg_single_tag) expected = self.dict_single_tag[self.msg_single_tag] self.assertEqual(tag_list, expected) assert tag_list is not None def test_analyze_tags_none(self): with self.assertRaises(TypeError): tag_list = re.findall(r'#([a-z0-9]+)', None) def test_analyze_tags_only_tags(self): tag_list = re.findall(r'#([a-z0-9]+)', self.msg_only_tags) expected = self.dict_only_tags[self.msg_only_tags] self.assertEqual(tag_list, expected) assert tag_list is not None def test_analyze_tags_hashes(self): tag_list = re.findall(r'#([a-z0-9]+)', self.msg_hashes) expected = self.dict_hashes[self.msg_hashes] assert tag_list is not None assert tag_list == []
Máme tu 5 testovacích metód. Popíšme si ich:
test_analyze_tags_no_tags()
- Nechá zanalyzovať prvú správu. Nesmie vrátiťNone
. List, ktorý vráti, musí byť prázdny.test_analyze_tags_single_tag()
- Metóda si nechá získať tagy z druhej vety a následne porovná, či je list nájdených tagov totožný sexpected
ako vo vzorovom slovníku. Kontroluje tiež, či nevráti hodnotuNone
.test_analyze_tags_none()
- Otestuje, že analyzer vyvolá výnimku v prípade, ak mu namiesto reťazca so správou príde hodnotaNone
. Ošetrovanie hodnôtNone
je v Pythone veľmi dôležité, ušetrí vám veľa nepríjemností v budúcnosti, kde sa nejakým nedopatrenímNone
do analyzeru napríklad dostane. Keďže vyvolá okamžite výnimku, problém rýchlo odhalíte. Časom zistíte, že aj keď tieto "impossible" kontroly nemôžu vyskočiť, tak aj tak občas vyskočia.test_analyze_tags_only_tags()
- Metóda funguje úplne rovnako ako druhá metóda.test_analyze_tags_hashes()
- Funguje rovnako ako prvá metóda.
Pozn.: Určite ste si všimli, že je test trochu redundantný. V podstate sa tu opakujú 2 metódy. Ak by bol ešte dlhší, vyplatilo by sa vytvoriť pre tieto 2 akcie vlastné metódy. Tu bol úmyselne ponechaný rozpísaný príklad, aby počet metód zodpovedal počtu testov.
Test si môžeme vyskúšať nám už známym príkazom:
python -m unittest
Alebo lepšie podrobnejším príkazom:
python -m unittest -v nazev_souboru_s_testem.py
A je hotovo. Teraz môžeme analyzer tagov ľubovoľne prepisovať a pokiaľ test opäť prejde, môžeme si byť takmer istí, že sme ho nerozbili.
Z testu by sme si mali odniesť:
- Testujeme či objekt reaguje korektne na hodnoty
None
- Testujeme medzné hodnoty
- Akokoľvek komplikované požadované výstupy vytvárame vopred ako referenčné hodnoty a tie potom porovnávame so skutočným výstupom metódy
- Píšeme impossible asserty av objektoch vyvolávame impossible výnimky
Tieto prvé testy boli pomerne jednoduché. Ako už bolo povedané v úvode, čakajú nás ešte dvaja rozsiahlejší.
Mal si s čímkoľvek problém? Stiahni si vzorovú aplikáciu nižšie a porovnaj ju so svojím projektom, chybu tak ľahko nájdeš.
Stiahnuť
Stiahnutím nasledujúceho súboru súhlasíš s licenčnými podmienkami
Stiahnuté 7x (668 B)
Aplikácia je vrátane zdrojových kódov v jazyku Python