Takéunit testing, unit testsPokročilý

Definice

Unit test je automatizovaný test malé části programu, typicky jedné funkce, metody nebo třídy, který ověřuje její chování izolovaně od zbytku systému. Pomáhá rychle odhalit regresi, zpřesňuje návrh rozhraní a dává vývojářům jistotu při refaktoringu i změnách závislého kódu v týmu.

Kategorie: Softwarový vývojAktualizováno

Co jednotkový test skutečně ověřuje

Jednotkový test ověřuje malou jednotku programu podle očekávaného chování, ne podle aktuální implementace. Jednotkou může být čistá funkce, metoda služby, validační pravidlo nebo malý objekt. Dobrý test říká: pro daný vstup má kód vrátit určitý výsledek, vyvolat konkrétní výjimku nebo zavolat závislost správným způsobem.

Hodnota jednotkového testu roste hlavně tam, kde je rozhodování v kódu nenápadné: okrajové hodnoty, prázdné vstupy, zaokrouhlování, oprávnění nebo převody formátů. Test pak slouží jako pojistka proti regresi i jako živá dokumentace domluveného chování.

Izolace od databáze, sítě a času

Unit test nemá být závislý na dostupnosti databáze, platební brány, souborového systému ani skutečného času. Externí závislosti se obvykle nahrazují testovací dvojníkem, například stubem nebo mock objektem. Cílem není předstírat celý svět, ale odstranit náhodu a zúžit příčinu případného selhání.

Izolace má praktický dopad na diagnostiku. Když jednotkový test spadne, vývojář má vědět, která malá část logiky porušila očekávání. Pokud test zároveň čeká na síť, mění data v databázi a spoléhá na pořadí běhu, chyba už nemusí být v testované jednotce. Takový test může být užitečný, ale patří spíš mezi integrační testy.

Rychlost jako součást návrhu testů

Jednotkové testy se mají spouštět často: při ukládání změn, před commitem i v kontinuální integraci. Rychlost proto není pohodlný bonus, ale konstrukční požadavek. Pomalé testy tým postupně přestane spouštět lokálně, takže ztratí největší výhodu: okamžitou zpětnou vazbu.

Rychlý test bývá krátký, deterministický a čitelný. Typický zápis používá strukturu arrange, act, assert: připrav data, proveď testovanou operaci, ověř výsledek. Test by měl selhat z jednoho jasného důvodu. Příliš mnoho nesouvisejících kontrol v jednom testu sice sníží počet souborů, ale zhorší hledání příčiny.

Proč jednotkové testy nenahradí ostatní testování

Unit test dobře chrání vnitřní logiku, ale neověří, že aplikace správně komunikuje s reálnou databází, prohlížečem, frontou zpráv nebo externím API. Integrace může selhat i tehdy, když všechny malé části prošly samostatně. Proto se jednotkové testy kombinují s integračními, end-to-end a ručním průzkumným testováním.

Největší přínos jednotkových testů bývá u kódu, který se bude měnit. Refaktoring je bezpečnější, protože testy popisují chování, které má zůstat zachované. Slabý přínos mají testy, které jen kopírují implementaci, kontrolují privátní detaily nebo vyžadují přepis při každé nevýznamné úpravě struktury kódu.

Příklady z praxe

  1. Sleva v košíku e-shopu

    E-shop počítá cenu po slevě a vývojář přidá jednotkový test pro běžný i neplatný vstup. Když později někdo změní pravidla zaokrouhlování nebo omylem povolí slevu nad 100 %, test spadne ještě před nasazením. Chyba se najde v malé funkci, ne až v objednávkovém procesu.

    import unittest
    
    
    def apply_discount(price, percent):
        if percent < 0 or percent > 100:
            raise ValueError("percent must be between 0 and 100")
        return price * (100 - percent) / 100
    
    
    class DiscountTest(unittest.TestCase):
        def test_applies_percentage_discount(self):
            self.assertEqual(apply_discount(200, 25), 150)
    
        def test_rejects_invalid_discount(self):
            with self.assertRaises(ValueError):
                apply_discount(200, 120)
    
    
    if __name__ == "__main__":
        unittest.main()
  2. Oprávnění v administraci

    Redakční systém povoluje publikování jen aktivním editorům. Jednotkový test ověří rozhodovací funkci bez databáze, přihlášení a administrace. Pokud refaktoring oprávnění omylem pustí neaktivního uživatele, selhání ukáže přímo na pravidlo, které se změnilo.

    import test from 'node:test';
    import assert from 'node:assert/strict';
    
    function canPublish(user) {
      return user.role === 'editor' && user.active === true;
    }
    
    test('active editor can publish', () => {
      assert.equal(canPublish({ role: 'editor', active: true }), true);
    });
    
    test('inactive editor cannot publish', () => {
      assert.equal(canPublish({ role: 'editor', active: false }), false);
    });

Časté omyly

MýtusUnit test musí mít každá metoda ve třídě.
Ve skutečnostiJednotkový test má chránit důležité chování, ne mechanicky kopírovat strukturu kódu. Některé metody jsou jen implementační detail a dávají větší smysl testovat přes veřejné rozhraní.
MýtusKdyž máme hodně unit testů, aplikace je otestovaná.
Ve skutečnostiUnit testy neověří celé propojení systému. Aplikace může mít výborně pokrytou logiku a přesto selhat na migraci databáze, konfiguraci, síti nebo chování prohlížeče.

Časté dotazy

Má unit test kontrolovat privátní metody?
Unit test má testovat veřejně pozorovatelné chování malé části kódu: návratovou hodnotu, vyvolanou chybu, změnu stavu nebo komunikaci s jasně definovanou závislostí. Jednotkový test obvykle nemá opisovat každý řádek implementace. Test privátní metody často prozrazuje, že se test příliš váže na vnitřní strukturu a bude křehký při refaktoringu.
Které části aplikace dávají pro unit test největší smysl?
Unit test je vhodný pro business logiku, validační pravidla, výpočty, parsování a rozhodovací větve. Uživatelské rozhraní, databázové dotazy a komunikace mezi službami často potřebují jiné druhy testů. Jednotkové testování samo o sobě nezaručí, že celek funguje v produkčním prostředí, ale výrazně snižuje počet chyb v izolované logice.
Kdy má unit test používat mock?
Unit test může používat mock, když testovaná jednotka potřebuje závislost, která je pomalá, nedeterministická nebo mimo proces aplikace. Mock se nehodí jako náhrada za každou spolupracující třídu. Přehnané mockování vede k testům, které potvrzují implementační detaily místo užitečného chování, takže se rozbíjejí při bezpečném refaktoringu.
Jak poznat dobrý unit test v praxi?
Unit test se v týmu pozná podle toho, že běží rychle, selhává deterministicky, nevyžaduje sdílené prostředí a má jasný důvod existence. Samotný počet testů není dobré měřítko. Užitečnější je sledovat, zda testy chrání důležité chování, zjednodušují změny a dávají srozumitelnou chybovou zprávu při porušení očekávání.

Zdroje

  1. unittest — Unit testing framework(otevře se v novém okně)Python Software Foundation
  2. Test runner(otevře se v novém okně)Node.js
  3. Unit testing best practices(otevře se v novém okně)Microsoft
  4. Unit testing(otevře se v novém okně)Wikipedia

Související pojmy

Potřebujete to vyřešit v praxi?

Poradíme, jak na to ve vašem projektu

Vysvětlit pojem je jedna věc, navrhnout kolem něj funkční řešení druhá. Ozvěte se a probereme, co dává smysl u vás.