# Testování

Různé přístupy k testům:

pozitivní testy (testy splněním, test-to-pass)
  Provádějí verifikaci konkrétního chování za očekávaných podmínek. Cílem je ověřit správnou funkčnost při běžném používání.
negativní testy (testy selháním, test-to-fail)
  Ověřují chování v abnormálních/neočekávaných podmínkách. Cílem je ověřit, že aplikace vhodně zareaguje. Typicky ověřují „alternativní toky v kódu“.

Oba typy testů píšeme tak, aby prošly - v negativních zachytáváme očekávanou výjimku/chybovou hlášku apod. Tyto typy pak vhodně kombinujeme - typicky jeden nebo více pozitivních testů a několik negativních testů.

## Úrovně testování

Testy dělíme podle rozsahu testovaného kódu:

Jednotkové
  Testy nejmenších částí systému - třídy, metody, funkce.
Integrační
  Testování, že podsystémy (moduly) fungují správně dohromady.
Systémové
  Obsáhlé testovací scénáře, které procházejí celým systémem.
Akceptační
  Testy při převzetí zákazníkem, scénáře předem domluvené oběma stranami.

## Rozdělení podle toho, co je testováno

Funkční testy
  Testuje jednotlivé funkce z pohledu uživatele - vychází z funkčních požadavků.
Zátěžové testy
  Testuje chování systému pod zátěží, tedy například zda „ustojí“ očekávané množství uživatelů.
Bezpečnostní testy
  Název snad mluví za vše. :-)

## Anatomie testu

Testovací případ má typicky 3 fáze: ARRANGE - ACT - ASSERT

1. ARRANGE: Nastavení počátečních podmínek testu - vytvoření objektů, se kterými se bude pracovat, příprava dat, …
2. ACT:Provedení požadované akce.
3. ASSERT: Ověření správnosti výstupu.

Příklad:

    def test_sum():
        # 1. Arrange:
        test_data = [1, 2, 3, 4, 5]
        # 2. Act:
        result = sum(test_data)
        # 3. Assert:
        assert 15 == result

## Pokrytí kódu

Pokrytí kódu (Cove Coverage): počet elementů pokrytých testy / celkový počet elementů [%]

Různé druhy:

Line/Statement Coverage
  Množina řádek, které byly v průběhu testů vykonány. Tyto řádky kódu jsou tak pravděpodobně správné - pokud máme správné testy pokrývající dostatečné množství případů.
Branch Coverage
  Pokrytí každé větve podmínky - včetně přeskočení podmínky, která nemá větev else.
Condition Coverage
  Pokrytí každé části výrazu v podmínce.
Path Coverage
  Pokrytí všech možných cest kódem.

Ilustrativní příklad - vizte `p04_testing.intro`.

## pytest

Nástroj pro automatické testování, oproti `unittest` přímo v Pythonu je jednodušší na začátek a snáze se s jeho pomocí píší testy – není potřeba dědit třídy, stačí pouze příkaz `assert`.

Předpokládá určité konvence v pojmenování:

- Soubory obsahující testy se jmenují `test_*.py`, nebo `*_test.py`.
- Každý testovací případ je reprezentován funkcí/metodou s prefixem `test_`. V případě metody musí název třídy začínat na `Test`.