Testování posunu doleva s testy jednotek

Testování pomáhá zajistit, aby kód fungoval podle očekávání, ale čas a úsilí při sestavování testů trvá mimo jiné úlohy, jako je vývoj funkcí. S touto cenou je důležité extrahovat maximální hodnotu z testování. Tento článek popisuje principy testování DevOps, které se zaměřují na hodnotu testování jednotek a strategii testování posunu doleva.

Vyhrazené testery používané k psaní většiny testů a mnoho vývojářů produktů se nenaučilo psát testy jednotek. Psaní testů se může zdát příliš obtížné nebo příliš mnoho práce. Může existovat pochybnosti o tom, jestli strategie testování jednotek funguje, špatné zkušenosti s špatně napsanými testy jednotek, nebo se obáváte, že testy jednotek nahradí funkční testy.

Graphic that describes arguments about adopting unit testing.

Pokud chcete implementovat testovací strategii DevOps, buďte praktická a zaměřte se na budování dynamiky. I když můžete trvat na testech jednotek pro nový kód nebo existující kód, který lze čistě refaktorovat, může být vhodné, aby starší verze základu kódu umožňovala nějakou závislost. Pokud velké části kódu produktu používají SQL, což umožňuje testům jednotek využívat závislost na poskytovateli prostředků SQL místo napodobování této vrstvy, může být krátkodobý přístup k pokroku.

S tím, jak organizace DevOps zraly, je pro vedení snazší zlepšit procesy. I když může dojít k nějaké odolnosti proti změnám, agilní organizace hodnoty změny, které jasně platí dividendy. Měli byste snadno prodat vizi rychlejších testovacích běhů s menším počtem selhání, protože znamená více času investovat do generování nové hodnoty prostřednictvím vývoje funkcí.

Taxonomie testů DevOps

Definování taxonomie testů je důležitým aspektem procesu testování DevOps. Taxonomie testů DevOps klasifikuje jednotlivé testy podle jejich závislostí a doby jejich spuštění. Vývojáři by měli rozumět správným typům testů, které se mají použít v různých scénářích a které testy vyžadují různé části procesu. Většina organizací kategorizuje testy napříč čtyřmi úrovněmi:

  • Testy L0 a L1 jsou testy jednotek nebo testy, které závisí na kódu v sestavení v rámci testu a nic jiného. L0 je široká třída rychlých testů jednotek v paměti.
  • L2 jsou funkční testy , které mohou vyžadovat sestavení a další závislosti, jako je SQL nebo systém souborů.
  • Funkční testy L3 běží na testovatelných nasazeních služeb. Tato testovací kategorie vyžaduje nasazení služby, ale může použít zástupné procedury pro klíčové závislosti služby.
  • Testy L4 jsou omezenou třídou integračních testů , které běží v produkčním prostředí. Testy L4 vyžadují úplné nasazení produktu.

I když by to bylo ideální pro všechny testy, aby běžely vždy, není to možné. Týmy můžou vybrat, kde se v procesu DevOps spustí každý test, a pomocí strategií posunu doleva nebo doprava posunete různé typy testů dříve nebo později v procesu.

Očekává se například, že vývojáři před potvrzením testů L2 vždy projdou testy L2, žádost o přijetí změn se automaticky nezdaří, pokud se testovací běh L3 nezdaří a nasazení může být zablokováno, pokud testy L4 selžou. Konkrétní pravidla se můžou lišit od organizace po organizaci, ale vynucování očekávání pro všechny týmy v organizaci přesune všechny směrem ke stejným cílům vize kvality.

Pokyny pro testování jednotek

Nastavte přísné pokyny pro testy jednotek L0 a L1. Tyto testy musí být velmi rychlé a spolehlivé. Například průměrná doba provádění na test L0 v sestavení by měla být menší než 60 milisekund. Průměrná doba provádění na test L1 v sestavení by měla být menší než 400 milisekund. Žádný test na této úrovni by neměl překročit 2 sekundy.

Jeden tým Microsoftu spouští paralelně 60 000 testů jednotek za méně než šest minut. Jejich cílem je zkrátit tuto dobu na méně než minutu. Tým sleduje dobu provádění testů jednotek pomocí nástrojů, jako je následující graf, a zaznamenává chyby proti testům, které překračují povolený čas.

Chart that shows continuous focus on test execution time.

Pokyny pro funkční testy

Funkční testy musí být nezávislé. Klíčovým konceptem testů L2 je izolace. Správně izolované testy se můžou spolehlivě spouštět v libovolné sekvenci, protože mají úplnou kontrolu nad prostředím, ve kterých běží. Stav musí být znám na začátku testu. Pokud jeden test vytvořil data a nechal je v databázi, mohl by poškodit spuštění jiného testu, který závisí na jiném stavu databáze.

Starší testy, které potřebují identitu uživatele, se k získání identity můžou volat externí zprostředkovatelé ověřování. Tento postup představuje několik výzev. Externí závislost může být momentálně nespolehlivý nebo nedostupný, protože test přeruší. Tento postup také porušuje princip izolace testu, protože test může změnit stav identity, například oprávnění, což vede k neočekávanému výchozímu stavu pro jiné testy. Zvažte zabránění těmto problémům tím, že v rámci testovací architektury investujte do podpory identit.

Principy testování DevOps

Pokud chcete pomoct s přechodem testovacího portfolia na moderní procesy DevOps, představte si kvalitní vizi. Týmy by při definování a implementaci strategie testování DevOps měly dodržovat následující zásady testování.

Diagram that shows an example of a quality vision and lists test principles.

Přechod doleva k otestování dříve

Spuštění testů může trvat delší dobu. S tím, jak se projekty škálují, se čísla a typy testů výrazně zvětšují. Když testovací sady rostou tak, aby trvaly hodiny nebo dny, můžou se posunout dál, dokud neběží v poslední chvíli. Výhody testování kvality kódu se neuskuteční až dlouho po potvrzení kódu.

Dlouhotrvající testy můžou také způsobit selhání, která jsou časově náročná k prozkoumání. Týmy můžou vytvářet odolnost proti chybám, zejména v raných sprintech. Tato tolerance podkopává hodnotu testování jako přehled o kvalitě základu kódu. Dlouhotrvající testy za poslední minutu také přidávají neprediktovatelnost k očekáváním na konci sprintu, protože kvůli odeslání kódu musí být zaplaceno neznámé množství technického dluhu.

Cílem posunu testování doleva je přesunout kvalitu směrem nahoru, a to provedením testovacích úloh dříve v kanálu. Kombinace vylepšení testů a procesů zkracuje posun doleva jak čas potřebný ke spuštění testů, tak dopad selhání později v cyklu. Posun doleva zajišťuje, že se většina testování dokončí před sloučením změn do hlavní větve.

Diagram that shows the move to shift-left testing.

Kromě posunu některých zodpovědností za testování doleva ke zlepšení kvality kódu můžou týmy posunout další testovací aspekty doprava nebo později v cyklu DevOps, aby zlepšily konečný produkt. Další informace najdete v tématu Shift doprava k otestování v produkčním prostředí.

Psaní testů na nejnižší možné úrovni

Napište další testy jednotek. Upřednostňování testů s nejmenšími externími závislostmi a zaměřte se na spouštění většiny testů v rámci sestavení. Zvažte paralelní systém sestavení, který může spouštět testy jednotek pro sestavení ihned po vyřazení sestavení a přidružených testů. Není možné testovat všechny aspekty služby na této úrovni, ale principem je použití lehčích testů jednotek, pokud mohou produkovat stejné výsledky jako těžší funkční testy.

Cílem je spolehlivost testů

Nespolehlivý test je organizace nákladný na údržbu. Takový test funguje přímo proti cíli technické efektivity tím, že ztěžuje provádění změn s jistotou. Vývojáři by měli být schopni provádět změny kdekoli a rychle získat jistotu, že nic nebylo přerušeno. Udržujte vysoký pruh pro spolehlivost. Nedoporučujeme používat testy uživatelského rozhraní, protože jsou obvykle nespolehlivé.

Psaní funkčních testů, které se dají spustit kdekoli

Testy můžou používat specializované integrační body navržené speciálně k povolení testování. Jedním z důvodů této praxe je nedostatek testovatelnosti samotného produktu. Podobné testy bohužel často závisejí na interních znalostech a používají podrobnosti implementace, které z hlediska funkčního testu nezáleží. Tyto testy jsou omezené na prostředí, která mají tajné kódy a konfiguraci potřebné ke spuštění testů, což obecně vylučuje produkční nasazení. Funkční testy by měly používat pouze veřejné rozhraní API produktu.

Navrhování produktů pro testovatelnost

Organizace v procesu zužujícího devOps mají úplný přehled o tom, co znamená dodávat kvalitní produkt v cloudovém tempu. Posun rovnováhy silně ve prospěch testování jednotek oproti funkčnímu testování vyžaduje, aby týmy udělaly volby návrhu a implementace, které podporují testovatelnost. Existují různé myšlenky na to, co představuje dobře navržený a dobře implementovaný kód pro testovatelnost, stejně jako existují různé styly kódování. Principem je, že návrh pro testovatelnost musí být primární součástí diskuze o kvalitě návrhu a kódu.

Zacházení s testovacím kódem jako kódem produktu

Explicitně hlásí, že testovací kód je kód produktu, aby bylo jasné, že kvalita testovacího kódu je stejně důležitá pro expedici jako kód produktu. Týmy by měly zacházet s testovacím kódem stejným způsobem jako s kódem produktu a používat stejnou úroveň péče na návrh a implementaci testů a testovacích architektur. Toto úsilí se podobá správě konfigurace a infrastruktury jako kódu. Pro dokončení by kontrola kódu měla zvážit testovací kód a držet ho na stejném panelu kvality jako kód produktu.

Použití sdílené testovací infrastruktury

Snižte panel pro použití testovací infrastruktury ke generování důvěryhodných signálů kvality. Zobrazení testování jako sdílené služby pro celý tým Uložte testovací kód jednotek společně s kódem produktu a sestavte ho s produktem. Testy, které se spouští jako součást procesu sestavení, musí běžet také v rámci vývojových nástrojů, jako je Azure DevOps. Pokud se testy můžou spouštět v každém prostředí z místního vývoje prostřednictvím produkčního prostředí, mají stejnou spolehlivost jako kód produktu.

Nastavení vlastníků kódu zodpovědných za testování

Testovací kód by se měl nacházet vedle kódu produktu v úložišti. Kód, který se má testovat na hranici komponenty, může posílat odpovědnost za testování osobě, která kód komponenty píše. Nespoléhejte na ostatní, kteří komponentu testují.

Případová studie: Posun doleva s testy jednotek

Tým Microsoftu se rozhodl nahradit starší testovací sady moderními testy jednotek DevOps a procesem posunu doleva. Tým sledoval průběh napříč triweekly sprinty, jak je znázorněno v následujícím grafu. Graf popisuje sprinty 78–120, které představují 42 sprintů za 126 týdnů nebo přibližně dva a půl roku úsilí.

Tým začal v 27K starších testech ve sprintu 78 a dosáhl nulového počtu starších testů na S120. Sada testů jednotek L0 a L1 nahradila většinu starých funkčních testů. Nové testy L2 nahradily některé testy a mnoho starých testů bylo odstraněno.

Diagram that shows a sample test portfolio balance over time.

Na cestě k softwaru, která trvá více než dva roky, se od samotného procesu hodně naučíte. Celkově bylo úsilím o úplné opakování testovacího systému za dva roky masivní investice. Ne každý tým funkcí pracoval současně. Mnoho týmů v celé organizaci investovalo čas do každého sprintu a v některých sprintech to byla většina toho, co tým udělal. I když je obtížné měřit náklady na směnu, jednalo se o neopomenutelný požadavek na kvalitu a výkonnostní cíle týmu.

Začínáme

Na začátku tým opustil staré funkční testy, označované jako testy TRA, sám. Tým chtěl, aby si vývojáři koupili představu o psaní testů jednotek, zejména pro nové funkce. Zaměření bylo na to, aby bylo co nejjednodušší vytvářet testy L0 a L1. Tým, který potřebuje k tomu, aby tuto schopnost vyvinul jako první, a vytvořil dynamiku.

Předchozí graf zobrazuje počet testů jednotek, který začíná brzy narůst, protože tým viděl výhodu vytváření testů jednotek. Testy jednotek byly snazší udržovat, rychleji se spouštět a měly méně selhání. Bylo snadné získat podporu pro spuštění všech testů jednotek v toku žádosti o přijetí změn.

Tým se nezaměřil na psaní nových testů L2 až do sprintu 101. Mezitím se počet testů TRA zpomalil z 27 000 na 14 000 z Sprintu 78 na Sprint 101. Nové testy jednotek nahradily některé testy TRA, ale mnohé byly jednoduše odstraněny na základě týmové analýzy jejich užitečnosti.

Testy TRA v sprintu 110 přeskočí z roku 2100 na 3800, protože ve zdrojovém stromu byly zjištěny další testy a přidány do grafu. Ukázalo se, že testy byly vždy spuštěné, ale nebyly sledovány správně. To nebyla krize, ale bylo důležité být upřímní a podle potřeby znovu posoudit.

Rychlejší

Jakmile měl tým signál kontinuální integrace (CI), který byl extrémně rychlý a spolehlivý, stal se důvěryhodným indikátorem pro kvalitu produktu. Následující snímek obrazovky ukazuje žádost o přijetí změn a kanál CI v akci a čas potřebný k procházení různých fází.

Diagram that shows the pull request and rolling CI pipeline in action.

Sloučení žádosti o přijetí změn trvá přibližně 30 minut, což zahrnuje spuštění 60 000 testů jednotek. Od sloučení kódu do sestavení CI je přibližně 22 minut. První signál kvality z CI, SelfTest, přichází asi po hodině. Pak se většina produktu testuje s navrženou změnou. Během dvou hodin od sloučení po SelfHost se testuje celý produkt a změna je připravená na přechod do produkčního prostředí.

Použití metrik

Tým sleduje přehled výkonnostních metrik jako v následujícím příkladu. Přehled výkonnostních metrik na vysoké úrovni sleduje dva typy metrik: stav nebo dluh a rychlost.

Diagram that shows a metrics scorecard for tracking test performance.

V případě metrik stavu živého webu tým sleduje čas, jak zjistit, čas zmírnit a kolik oprav položek tým nese. Položka opravy je práce, kterou tým identifikuje v retrospektivním živém webu, aby se zabránilo opakování podobných incidentů. Přehled výkonnostních metrik také sleduje, jestli týmy zavírají položky oprav v přiměřeném časovém rámci.

Pro technické metriky stavu tým sleduje aktivní chyby na vývojáře. Pokud má tým více než pět chyb na vývojáře, musí tým určit prioritu opravy těchto chyb před vývojem nových funkcí. Tým také sleduje chyby stárnutí ve speciálních kategoriích, jako je zabezpečení.

Metriky rychlosti přípravy měří rychlost v různých částech kanálu kontinuální integrace a průběžného doručování (CI/CD). Celkovým cílem je zvýšit rychlost kanálu DevOps: Od nápadu, získání kódu do produkčního prostředí a příjem dat od zákazníků.

Další kroky