## Pytest 101 #### Základy testovania v jazyku Python s rámcom pytest (nie len) pre učiteľov [Miroslav "mirek" Biňas](https://bletvaska.github.io) / [**Namakaný webinár**](http://www.namakanyden.sk)
## Čo je to test?
### Test je kód, ### ktorý sa spúšťa na overenie správnosti iného kódu. Notes: * a test is code that runs to check the validity of other code (https://www.youtube.com/watch?v=etosV2IWBF0)
## Prečo by som mal testovať? Notes: * dokázať, že kód pracuje podľa požiadaviek * ukázať iným, ako sa váš kód dá používať * vložiť do kódu bezpečnostnú poistku pre zmeny v budúcnosti
## Kvíz áno/nie pravda/lož
## 1. kolo všeobecné znalosti
Hlavné mesto Slovenska je Bratislava.
Pravda
Nulou sa nedá deliť.
Pravda
Písmeno "N" je samohláska.
Lož
$$ 1 + 2 \times 3^2 = 18 $$
Lož
## 2. kolo výrazy v jazyku Python
                
42 == 42
                
            
True
                
4 != 4.0
                
            
False
                
2022 > 21
                
            
True
                
10 >= 10
                
            
True
                
'Python' in 'Welcome to Python'
                
            
True
                
'Security' in 'IoT'
                
            
False
## Kvíz ```python 42 == 42 4 != 4.0 2022 > 21 10 >= 10 'Python' in 'Welcome to Python' 'Security' in 'IoT' ```
## pytest API ```python assert 42 == 42 assert 4 != 4.0 assert 2022 > 21 assert 10 >= 10 assert 'Python' in 'Welcome to Python' assert 'Security' in 'IoT' ```
```python assert ``` notes: * klucove slovo jazyka * netreba nic importovat
```python assert výraz ``` notes: * logický výraz alebo tvrdenie * výsledná hodnota môže byť `True` alebo `False` * ak je výraz `True`, nič sa nestane * ak je výraz `False`, dôjde k vyvolaniu výnimky `AssertionError`
```python assert výraz [, správa] ``` notes: * voliteľný parameter je správa * zobrazí sa pri vzniku výnimky `AssertionError`
## No boilerplate, ## no required API. notes: * http://pythontesting.net/framework/pytest/pytest-introduction/
> "Everybody is using pytest anyway..." > -- [Guido van Rosum](https://bugs.python.org/issue17908)
[![Pytest logo](images/logo-pytest.png)](https://docs.pytest.org)
## Inštalácia `pytest` ```bash $ pip install pytest ```
## Môj prvý test ;) notes: ```python def hello(): pass ```
## Ako písať dobré testy 1. Test má byť **atomický**. 2. Jeden test vždy testuje **jednu vec**. 3. V jednom teste vždy len **jeden `assert`**.
## when/if - then/expect notes: * KED zadas vek nizsi ako 18 rokov, TAK ta nepustim dalej * KED delitel bude 0, OCAKAVAJ vynimku ZeroDivisionError * KED bude vstupny parameter None, OCAKAVAJ vynimku TypeError * KED sa prvok nenachadza v zozname, TAK vrat False
## Arrange - Act -Assert (AAA pattern) notes: * Arrange-Act-Assert je vyborny sposob, ako strukturovat testy * predpisuje poradie operacii * BDD pouziva Given-When-Then
Časť **Arrange** nastaví testovacie objekty a pripraví podmienky pre test. notes: * Arrange steps should set up the test case. * Does the test require any objects or special settings? Does it need to prep a database? Does it need to log into a web app? Handle all of these operations at the start of the test.
Časť **Act** vykoná hlavné kroky pre otestovanie cieľa. notes: * Act on the target behavior. Act steps should cover the main thing to be tested. * This could be calling a function or method, calling a REST API, or interacting with a web page. Keep actions focused on the target behavior.
Časť **Assert** overí výsledok. notes: * Assert expected outcomes. Act steps should elicit some sort of response. Assert steps verify the goodness or badness of that response. Sometimes, assertions are as simple as checking numeric or string values. Other times, they may require checking multiple facets of a system. Assertions will ultimately determine if the test passes or fails.
## Príklad použitia AAA (na organizáciu testu) ```python def test_when_negative_nr_is_given_then_return_abs_value(): # Arrange negative = -5 # Act answer = abs(negative) # Assert assert answer == 5 ```
![Red-Green-Refactor](images/red.green.refactor.png)
## Fixtures * funkcie, ktoré sa spúšťajú pred/po teste * použitie: * príprava/vyčistenie prostredia (db, fs, ...) * sú vytvorené ako **generátory** * jeden test môže používať viacero fixtures * možné špecifikovať rozsah na *funkciu*, *triedu*, *modul* alebo *sedenie*
## Príklad fixture ```python @pytest.fixture def webdriver(): # setup part driver = webdriver.Chrome() yield driver # teardown part driver.close() ```
## Použitie fixture ```python def test_when_web_opens_then_dennik_in_title(webdriver): # arrange url = 'http://www.sme.sk' # act webdriver.get(url) # assert assert 'dennik' in webdriver.title ```
## Testovanie výnimiek * pomocou *context provider*-a: ```python def test_when_zero_is_given_then_raise_zerodivisionerror(): # arrange value = 0 # act with pytest.raises(ZeroDivisionError): 10 / value ```
## Parametrické testy * test je napísaný len jeden, ale vo výsledku sa spustí toľkokrát, koľko hodnôt parametrov má ```python @pytest.mark.parametrize("word", ['hello', 'World', '123', '']) def test_when_not_uppercase_word_is_given_then_false(word): assert word.isupper() == False ```
## Značkovanie testov * výhodné pri selektívnom spúšťaní testov * príklad: ```python @pytest.mark.wip def test_when_digits_are_given_then_return_true(): assert '123'.isdigit() == True ``` * následne je možné spustiť test so značkou `wip`: ```bash $ pytest -m wip ``` * pozor na upozornenie kvôli neznámej značke
## Výhody pre učiteľa * rovnaké podmienky pre testovaní pre všetkých * dôsledné otestovanie všetkých možných (aj nemožných) prípadov * napísaním testov sa zlepší aj znenie zadania úlohy * jednoduchšie a jasnejšie zdôvodnenie výsledného hodnotenia pre študentov * úspora času * keď odmyslíme prípravu testov notes: * pri písaní testov si uvedomíte, na čo všetko ste zabudli
## Otázky?
## Zdroje * [src.zip](src.zip) - kód vytvorený počas webinára * [pytest](https://docs.pytest.org/en/7.1.x/) - domovská stránka projektu * RealPython: [Effective Python Testing With Pytest](https://realpython.com/pytest-python-testing/) * YouTube: [Python Testing 101 with pytest](https://www.youtube.com/watch?v=etosV2IWBF0) * DZone: [7 Popular Unit Test Naming Conventions](https://dzone.com/articles/7-popular-unit-test-naming)
![qr code](https://api.qrserver.com/v1/create-qr-code/?data=https://bit.ly/3ydElMp&size=300x300) (**https://bit.ly/3ydElMp**)