Programování

Psaní testů s AI – pytest a Jest, které opravdu něco testují

Jak nechat AI generovat unit testy, aby nebyly jen pro pokrytí. Prompty, parametrizace, okrajové případy, mutační testování a typické chyby AI testů.

12. 10. 2026 · 4 min čtení

AI umí vygenerovat stovky řádků testů za pár sekund. Problém je, že spousta z nich testuje, že kód dělá to, co dělá – včetně chyb. Taková sada zvýší pokrytí, ale chybu nechytí. Tady je postup, jak z AI dostat testy, které mají hodnotu.

Hlavní past: testy opsané z implementace

Když AI dostane funkci a pokyn „napiš testy“, často vezme aktuální chování jako správné:

def discount(price, percent):
    return price - price * percent / 10   # chyba: má být / 100

# AI test odvozený z implementace
def test_discount():
    assert discount(200, 10) == 0   # "prošlo" – a test chybu zabetonoval

Řešení: dejte AI specifikaci, ne jen kód. Napište, co funkce má dělat, a nechte testy vycházet z toho.

Prompt, který funguje

Napiš testy v pytest pro funkci discount(price, percent).

Specifikace:
- price je Decimal >= 0, percent je int 0–100
- vrací cenu po slevě zaokrouhlenou na 2 desetinná místa (ROUND_HALF_UP)
- percent mimo rozsah 0–100 → ValueError
- záporná cena → ValueError

Požadavky:
- testy odvozuj ze specifikace, ne z implementace
- použij @pytest.mark.parametrize pro sadu vstupů
- pokryj okrajové hodnoty (0, 100, 0.005 zaokrouhlení) a chybové stavy
- každý test testuje jednu věc a má popisný název
- nepoužívej mocky, funkce je čistá

Jak vypadá dobrý výsledek

from decimal import Decimal
import pytest
from shop.pricing import discount

@pytest.mark.parametrize("price, percent, expected", [
    (Decimal("200"), 10, Decimal("180.00")),
    (Decimal("99.99"), 0, Decimal("99.99")),
    (Decimal("50"), 100, Decimal("0.00")),
    (Decimal("0.05"), 50, Decimal("0.03")),   # 0.025 → 0.03 (HALF_UP)
])
def test_discount_valid(price, percent, expected):
    assert discount(price, percent) == expected

@pytest.mark.parametrize("percent", [-1, 101])
def test_discount_rejects_percent_out_of_range(percent):
    with pytest.raises(ValueError):
        discount(Decimal("100"), percent)

def test_discount_rejects_negative_price():
    with pytest.raises(ValueError):
        discount(Decimal("-1"), 10)

Očekávané hodnoty si ověřte ručně. Právě u nich AI chybuje nejčastěji – špatně spočítá zaokrouhlení nebo datum.

Ekvivalent v Jestu

import { discount } from '../src/pricing';

describe('discount', () => {
  test.each([
    [200, 10, 180],
    [99.99, 0, 99.99],
    [50, 100, 0],
  ])('discount(%p, %p) = %p', (price, percent, expected) => {
    expect(discount(price, percent)).toBeCloseTo(expected, 2);
  });

  test('throws for percent > 100', () => {
    expect(() => discount(100, 101)).toThrow(RangeError);
  });
});

U floatů v JS používejte toBeCloseTo, ne toBe – 0.1 + 0.2 není přesně 0.3.

Na co AI testy nejčastěji kazí

Problém Jak poznat Oprava
Testy z implementace Očekávané hodnoty „sedí“ i na zjevné chybě Dát specifikaci
Přemockování Mockuje se i testovaná funkce nebo vše kolem Mockovat jen hranice (síť, čas, DB)
Test bez asserce Volá kód, ale nic neověřuje Ke každému testu konkrétní assert
Neexistující API pytest.raises(..., msg=), vymyšlené matchery Spustit a opravit
Křehké testy Závisí na čase, pořadí, náhodě freezegun, fixní seed, sorted()
Jeden obří test 20 assertů v jedné funkci Rozdělit / parametrizovat

Ověřte, že testy něco chytí

Pokrytí kódu (pytest --cov, jest --coverage) říká jen, které řádky se spustily, ne že se ověřily. Lepší kontrola je mutační testování: nástroj záměrně rozbije kód (změní < na <=, + na -) a sleduje, zda testy selžou.

# Python
pip install mutmut
mutmut run
mutmut results

# JavaScript / TypeScript
npx stryker init
npx stryker run

Přeživší mutanti = místa, kde testy nic nehlídají. Ty pak dejte AI se zadáním „napiš test, který tento mutant zabije“.

Rychlejší ruční varianta: v kódu schválně udělejte chybu a spusťte testy. Pokud projdou, něco chybí.

Testy k chybě: nejdřív červená

Při opravě chyby postupujte takto:

  1. Požádejte AI o test, který chybu reprodukuje.
  2. Spusťte ho – musí selhat. Pokud projde, netestuje danou chybu.
  3. Opravte kód.
  4. Test projde → máte ochranu proti návratu chyby.

Co testovat ručně psaným testem

AI je silná v generování variant vstupů a okrajových případů. Slabší je v testech, které vyžadují pochopení byznysu – „uživatel s prošlým předplatným nesmí stáhnout export“. Tyto testy napište nebo aspoň zadejte sami, AI pak doplní varianty.

V ColdHost AI můžete v Projektu nahrát kód i specifikaci (třeba jako PDF nebo text) a v režimu Programování nechat vygenerovat testy přímo do souborů projektu.