Testovaný vývoj - Test-driven development

Test-driven development ( TDD ) je proces vývoje softwaru, který spoléhá na to, že softwarové požadavky budou před úplným vývojem softwaru převedeny na testovací případy , a sledování veškerého vývoje softwaru opakovaným testováním softwaru proti všem testovacím případům. To je v rozporu s tím, že se nejprve vyvíjí software a testovací případy se vytvářejí později.

Softwarový inženýr Kent Beck , kterému se připisuje zásluha na vývoji nebo „znovuobjevení“ této techniky, v roce 2003 uvedl, že TDD podporuje jednoduchý design a vzbuzuje důvěru.

Testově řízený vývoj souvisí s testovacími prvními programovacími koncepty extrémního programování , které byly zahájeny v roce 1999, ale v poslední době si vytvořily obecnější zájem o vlastní práva.

Programátoři také uplatňují koncept na vylepšování a ladění staršího kódu vyvinutého staršími technikami.

Testovací vývojový cyklus

Grafické znázornění životního cyklu vývoje řízeného testy

Následující sekvence vychází z knihy Test-Driven Development by Example :

1. Přidejte test
Přidání nové funkce začíná napsáním testu, který projde, pokud jsou splněny specifikace funkce. Vývojář může objevit tyto specifikace dotazem na případy použití a příběhy uživatelů . Klíčovou výhodou vývoje založeného na testování je, že se vývojář soustředí na požadavky před psaním kódu. To je v kontrastu s obvyklou praxí, kdy se jednotkové testy zapisují pouze za kód.
2. Spusťte všechny testy. Nový test by měl z očekávaných důvodů selhat
To ukazuje, že pro požadovanou funkci je skutečně potřeba nový kód. Ověřuje, že testovací svazek funguje správně. Vylučuje možnost, že nový test bude chybný a vždy projde.
3. Napište nejjednodušší kód, který projde novým testem
Nelegantní nebo pevný kód je přijatelný, pokud projde testem. V kroku 5 bude kód stejně vybroušen. Kromě testované funkce by neměl být přidán žádný kód.
4. Všechny testy by nyní měly projít
Pokud některý selže, musí být nový kód revidován, dokud neprojdou. Tím je zajištěno, že nový kód splňuje požadavky testu a neporušuje stávající funkce.
5. Podle potřeby refaktorujte pomocí testů po každém refaktoru, abyste zajistili zachování funkčnosti
Kód je přepracován tak, aby byl čitelný a udržovatelný. Zejména by měla být odstraněna pevně zakódovaná testovací data. Spuštění testovací sady po každém refaktoru pomůže zajistit, že nebudou poškozeny žádné stávající funkce.
Opakovat
Výše uvedený cyklus se opakuje pro každou novou funkci. Testy by měly být malé a přírůstkové a měly by se provádět často. Tímto způsobem, pokud nový kód v některých testech selže, může programátor jednoduše vrátit zpět nebo vrátit, než nadměrně ladit . Při používání externích knihoven je důležité nepisovat testy, které jsou tak malé, aby účinně testovaly pouze samotnou knihovnu, pokud neexistuje nějaký důvod domnívat se, že je knihovna buggy nebo není dostatečně bohatá na funkce, aby vyhovovala všem potřebám software ve vývoji.

Styl vývoje

Existují různé aspekty používání vývoje založeného na testování, například zásady „udržujte to jednoduché, hloupé“ ( KISS ) a „ Nebudete to potřebovat “ (YAGNI). Zaměřením se na psaní pouze kódu nezbytného pro úspěšné absolvování testů mohou být návrhy často čistší a jasnější, než je dosaženo jinými metodami. V Test-Driven Development by Example Kent Beck také navrhuje zásadu „ Fake it until you make it “.

Aby se dosáhlo nějakého pokročilého konceptu návrhu, jako je návrhový vzor , jsou napsány testy, které tento design generují. Kód může zůstat jednodušší než cílový vzor, ​​ale přesto projít všemi požadovanými testy. Zpočátku to může být znepokojující, ale vývojáři se mohou soustředit pouze na to, co je důležité.

První psaní testů: Testy by měly být napsány před funkčností, která má být testována. To bylo prohlašoval, že má mnoho výhod. Pomáhá zajistit, aby byla aplikace napsána pro testovatelnost, protože vývojáři musí zvážit, jak aplikaci testovat od samého začátku, než aby ji přidávali později. Rovněž zajišťuje, že testy pro každou funkci budou zapsány. Navíc psaní testů nejprve vede k hlubšímu a dřívějšímu pochopení požadavků na produkt, zajišťuje účinnost testovacího kódu a udržuje neustálé zaměření na kvalitu softwaru . Při psaní kódu založeného na funkcích mají vývojáři a organizace tendenci tlačit vývojáře na další funkci, a to i zcela opomíjet testování. První test TDD se zprvu nemusí ani kompilovat, protože požadované třídy a metody ještě nemusí existovat. První test však funguje jako začátek spustitelné specifikace.

Každý testovací případ selže na začátku: Tím je zajištěno, že test opravdu funguje a může dojít k chybě. Jakmile se to ukáže, lze implementovat základní funkce. To vedlo k „testovací vývojové mantře“, což je „červená/zelená/refaktor“, kde červená znamená neúspěch a zelená znamená splnění . Testově řízený vývoj neustále opakuje kroky přidání testovacích případů, které selžou, jejich předání a refaktorování. Příjem očekávaných výsledků testů v každé fázi posiluje vývojářský mentální model kódu, zvyšuje důvěru a zvyšuje produktivitu.

Udržujte jednotku malou

U TDD je jednotka nejčastěji definována jako třída nebo skupina souvisejících funkcí často nazývaná modul. Udržování jednotek relativně malých údajně poskytuje zásadní výhody, včetně:

  • Snížené úsilí při ladění - Když jsou detekovány chyby testu, menší jednotky pomáhají při sledování chyb.
  • Testy s vlastní dokumentací-Malé testovací případy jsou snáze čitelné a srozumitelné.

Pokročilé postupy vývoje založeného na testování mohou vést k vývoji a řízení založenému na přejímce (ATDD) a ke specifikaci na příkladu, kde jsou kritéria stanovená zákazníkem automatizována do přejímacích testů, které pak pohánějí tradiční proces vývoje řízeného jednotkovým testem (UTDD). Tento proces zajišťuje, že zákazník má automatizovaný mechanismus, který rozhoduje, zda software splňuje jejich požadavky. Díky ATDD má nyní vývojový tým konkrétní cíl, který musí splnit - přejímací testy - díky čemuž se neustále soustředí na to, co zákazník od každého uživatelského příběhu skutečně chce.

Osvědčené postupy

Zkušební struktura

Efektivní rozložení testovacího případu zajišťuje dokončení všech požadovaných akcí, zlepšuje čitelnost testovacího případu a vyhlazuje průběh provádění. Konzistentní struktura pomáhá při vytváření testovacího případu s vlastním dokumentem. Běžně používaná struktura pro testovací případy má (1) nastavení, (2) provedení, (3) ověření a (4) vyčištění.

  • Nastavení: Umístěte testovanou jednotku (UUT) nebo celkový testovací systém do stavu potřebného ke spuštění testu.
  • Provedení: Spustit/řídit UUT, aby provedlo cílové chování a zachytilo veškerý výstup, jako jsou návratové hodnoty a výstupní parametry. Tento krok je obvykle velmi jednoduchý.
  • Ověření: Zajistěte, aby výsledky testu byly správné. Tyto výsledky mohou zahrnovat explicitní výstupy zachycené během provádění nebo změny stavu v UUT.
  • Vyčištění: Obnovte UUT nebo celkový testovací systém do stavu před testem. Toto obnovení umožňuje provést další test bezprostředně po tomto. V některých případech by za účelem uchování informací pro možnou analýzu selhání testu mělo vyčištění spustit test těsně před spuštěním instalace testu.

Individuální doporučené postupy

Některé osvědčené postupy, které by jednotlivec mohl dodržovat, by bylo oddělit společnou logiku nastavení a rozebírání na služby podpory testování využívané příslušnými testovacími případy, aby se každé testovací věštec soustředilo pouze na výsledky nezbytné k ověření jeho testu a navrhnout testy související s časem, aby byla umožněna tolerance pro provádění v operačních systémech, které nejsou v reálném čase. Běžná praxe umožňující 5-10 procentní rezervu pro pozdní provedení snižuje potenciální počet falešných negativ při provádění testu. Rovněž se doporučuje zacházet se zkušebním kódem se stejným respektem jako s produkčním kódem. Testovací kód musí fungovat správně pro pozitivní i negativní případy, musí trvat dlouho a musí být čitelný a udržovatelný. Týmy se mohou scházet a kontrolovat testy a testovací postupy, sdílet efektivní techniky a chytat špatné návyky.

Postupy, kterým je třeba se vyhnout, nebo „anti-vzory“

  • Mít testovací případy závisí na stavu systému zpracovaném z dříve provedených testovacích případů (tj. Vždy byste měli spustit test jednotky ze známého a předem nakonfigurovaného stavu).
  • Závislosti mezi testovacími případy. Testovací sada, kde jsou testovací případy na sobě závislé, je křehká a složitá. Exekuční příkaz by neměl být předpokládán. Základní refaktorování počátečních testovacích případů nebo struktury UUT způsobuje spirálu stále všudypřítomnějších dopadů v souvisejících testech.
  • Závislé testy. Vzájemně závislé testy mohou způsobit kaskádové falešné negativy. Selhání v časném testovacím případě přeruší pozdější testovací případ, i když v UUT neexistuje žádná skutečná chyba, což zvyšuje analýzu defektů a úsilí o ladění.
  • Testování přesného načasování chování nebo výkonu.
  • Budování „vševědoucích věštců“. Věštec, který kontroluje více, než je nutné, je časem dražší a křehčí. Tato velmi častá chyba je nebezpečná, protože způsobuje jemný, ale všudypřítomný pokles času v celém složitém projektu.
  • Testování podrobností implementace.
  • Pomalu běžící testy.

Výhody

Studie z roku 2005 zjistila, že používání TDD znamenalo psaní dalších testů a naopak programátoři, kteří psali více testů, měli tendenci být produktivnější. Hypotézy týkající se kvality kódu a přímější korelace mezi TDD a produktivitou byly neprůkazné.

Programátoři používající čistě TDD na nových („ zelených “) projektech uvedli, že jen zřídka cítili potřebu vyvolat debugger . Používá se ve spojení se systémem správy verzí , když testy neočekávaně selžou, návrat kódu na poslední verzi, která prošla všemi testy, může být často produktivnější než ladění.

Testovaný vývoj nabízí více než jen jednoduché ověření správnosti, ale může také vést k návrhu programu. Tím, že se nejprve zaměříme na testovací případy, je třeba si představit, jak tuto funkci používají klienti (v prvním případě testovací případy). Programátor se tedy zabývá rozhraním před implementací. Tato výhoda je doplňková k návrhu podle smlouvy, protože přistupuje ke kódu prostřednictvím testovacích případů, nikoli prostřednictvím matematických tvrzení nebo předsudků.

Testovaný vývoj nabízí možnost v případě potřeby provádět malé kroky. Umožňuje programátorovi soustředit se na daný úkol, protože prvním cílem je projít testem. Výjimečné případy a zpracování chyb nejsou původně brány v úvahu a testy k vytvoření těchto cizích okolností jsou implementovány samostatně. Testově řízený vývoj tímto způsobem zajišťuje, že veškerý psaný kód je pokryt alespoň jedním testem. To dává programovacímu týmu a dalším uživatelům větší míru důvěry v kód.

I když je pravda, že s kódem jednotky je vyžadováno více kódu s TDD než bez TDD, celková doba implementace kódu by mohla být kratší podle modelu od Müllera a Padberga. Velký počet testů pomáhá omezit počet defektů v kódu. Časná a častá povaha testování pomáhá zachytit vady na začátku vývojového cyklu, což jim brání stát se endemickými a nákladnými problémy. Odstranění vad na začátku procesu obvykle zabrání zdlouhavému a únavnému ladění později v projektu.

TDD může vést k modularizovanějšímu, flexibilnějšímu a rozšiřitelnějšímu kódu. K tomuto efektu často dochází, protože metodika vyžaduje, aby vývojáři přemýšleli o softwaru v podobě malých jednotek, které lze nezávisle psát a testovat a později integrovat dohromady. To vede k menším, více zaměřeným třídám, volnějšímu propojení a čistším rozhraním. Použití falešného vzoru návrhu objektu také přispívá k celkové modularizaci kódu, protože tento vzor vyžaduje, aby byl kód zapsán tak, aby moduly bylo možné snadno přepínat mezi falešnými verzemi pro testování jednotek a „skutečnými“ verzemi pro nasazení.

Protože pro předání neúspěšného testovacího případu není zapsáno více kódu, než je nutné, automatizované testy obvykle pokrývají každou cestu kódu. Například pro vývojáře TDD, aby přidal elsevětev do existujícího ifpříkazu, by vývojář nejprve musel napsat neúspěšný testovací případ, který motivuje větev. V důsledku toho bývají automatizované testy vyplývající z TDD velmi důkladné: detekují jakékoli neočekávané změny v chování kódu. To detekuje problémy, které mohou nastat, pokud změna později ve vývojovém cyklu neočekávaně změní další funkce.

Madeyski poskytl empirické důkazy (prostřednictvím série laboratorních experimentů s více než 200 vývojáři) ohledně nadřazenosti praxe TDD oproti tradičnímu přístupu Test-Last nebo testování správnosti s ohledem na nižší propojení mezi objekty (CBO). Průměrná velikost účinku představuje střední (ale téměř velký) účinek na základě metaanalýzy provedených experimentů, což je podstatné zjištění. Navrhuje lepší modularizaci (tj. Modulárnější design), snazší opětovné použití a testování vyvinutých softwarových produktů díky programovací praxi TDD. Madeyski také měřil účinek praxe TDD na jednotkové testy pomocí pokrytí větví (BC) a indikátoru skóre mutace (MSI), což jsou indikátory důkladnosti a účinnosti detekce poruch jednotkových testů. Velikost účinku TDD na pokrytí větví byla střední velikosti, a proto je považována za podstatný účinek.

Omezení

Testově řízený vývoj neprovádí dostatečné testování v situacích, kdy jsou k určení úspěchu nebo neúspěchu vyžadovány úplné funkční testy, kvůli rozsáhlému používání jednotkových testů. Příkladem jsou uživatelská rozhraní , programy, které pracují s databázemi , a některá závisí na konkrétní konfiguraci sítě . TDD vývojářům doporučuje, aby minimální množství kódu do těchto modulů a maximalizovat logiku, která je v testovatelného kódu knihovny, za použití padělků a zesměšňuje reprezentovat okolnímu světu.

Podpora managementu je zásadní. Aniž by celá organizace věřila, že vývoj na základě testů povede ke zlepšení produktu, může mít management pocit, že čas strávený psaním testů je zbytečný.

Testy jednotek vytvořené ve vývojovém prostředí řízeném testy obvykle vytváří vývojář, který píše testovaný kód. Testy proto mohou sdílet slepá místa s kódem: pokud si například vývojář neuvědomí, že je třeba zkontrolovat určité vstupní parametry, s největší pravděpodobností test ani kód tyto parametry neověří. Další příklad: pokud vývojář nesprávně interpretuje požadavky na modul, který vyvíjí, kód a testy jednotek, které píše, budou chybné stejným způsobem. Testy proto projdou, což dává falešný pocit správnosti.

Vysoký počet absolvovaných testů jednotek může přinést falešný pocit bezpečí, což má za následek méně aktivit dalšího testování softwaru , jako je testování integrace a testování shody .

Testy se stávají součástí režie údržby projektu. Špatně napsané testy, například ty, které obsahují pevně kódované chybové řetězce, jsou samy o sobě náchylné k selhání a jejich údržba je nákladná. To platí zejména pro křehké testy . Existuje riziko, že testy, které pravidelně generují falešná selhání, budou ignorovány, takže když dojde ke skutečnému selhání, nemusí být detekováno. Je možné psát testy pro nízkou a snadnou údržbu, například opětovným použitím chybových řetězců, a to by mělo být cílem během výše popsané fáze refaktorování kódu .

Psaní a údržba nadměrného počtu testů stojí čas. Také flexibilnější moduly (s omezenými testy) mohou přijímat nové požadavky bez nutnosti změny testů. Z těchto důvodů lze testování pro extrémní podmínky nebo malý vzorek dat upravit snáze než sadu vysoce podrobných testů.

Úroveň pokrytí a podrobnosti testování dosažené během opakovaných cyklů TDD nelze snadno znovu vytvořit později. Proto jsou tyto původní nebo rané testy s postupem času stále vzácnější. Taktika je opravit to brzy. Pokud také špatná architektura, špatný design nebo špatná testovací strategie vede k pozdní změně, kvůli které desítky stávajících testů selžou, je důležité, aby byly jednotlivě opraveny. Pouhé jejich odstranění, deaktivace nebo zbrklá změna může vést k nezjistitelným otvorům v pokrytí testu.

Práce řízená testem

Testem řízený vývoj byl přijat mimo vývoj softwaru, v produktových i servisních týmech, jako testem řízená práce. Podobně jako u TDD vyvíjejí nesoftwarové týmy kontroly řízení kvality (QC) (obvykle manuální testy spíše než automatizované testy) pro každý aspekt práce před zahájením. Tyto kontroly QC se pak používají k informování návrhu a ověření souvisejících výsledků. Šest kroků sekvence TDD je aplikováno s menšími sémantickými změnami:

  1. „Přidat šek“ nahrazuje „Přidat test“
  2. „Spustit všechny kontroly“ nahrazuje „Spustit všechny testy“
  3. „Do práce“ nahrazuje „Napište nějaký kód“
  4. „Spustit všechny kontroly“ nahrazuje „Spustit testy“
  5. „Vyčistit práci“ nahrazuje „Kód refaktoru“
  6. "Opakovat"

TDD a ATDD

Testovaný vývoj souvisí s vývojem řízeným přejímacím testem (ATDD) , ale liší se od něj. TDD je především nástrojem vývojáře, který pomáhá vytvářet dobře napsanou jednotku kódu (funkce, třída nebo modul), která správně provádí sadu operací. ATDD je komunikační nástroj mezi zákazníkem, vývojářem a testerem, který zajišťuje, že požadavky jsou dobře definovány. TDD vyžaduje automatizaci testů. ATDD ne, ačkoli automatizace pomáhá s regresním testováním. Testy používané v TDD lze často odvodit z testů ATDD, protože kódové jednotky implementují určitou část požadavku. Testy ATDD by měly být pro zákazníka čitelné. Testy TDD nemusí být.

TDD a BDD

BDD ( behavior-driven development ) kombinuje postupy z TDD a z ATDD. Zahrnuje nejprve psaní testů, ale zaměřuje se spíše na testy, které popisují chování, než na testy, které testují jednotku implementace. Nástroje jako JBehave , Cucumber , Mspec a Specflow poskytují syntaxe, které majitelům produktů, vývojářům a testovacím technikům umožňují společně definovat chování, které lze následně převést do automatizovaných testů.

Viditelnost kódu

Kód testovací sady musí mít zjevně přístup k testovanému kódu. Na druhé straně by neměla být ohrožena běžná kritéria návrhu, jako je skrývání informací , zapouzdření a oddělení obav . Proto je testovací kód jednotky pro TDD obvykle zapsán ve stejném projektu nebo modulu jako testovaný kód.

V objektově orientovaném designu to stále neposkytuje přístup k soukromým datům a metodám. Pro jednotkové testy proto může být zapotřebí více práce. V Javě a dalších jazycích může vývojář použít reflexi pro přístup k soukromým polím a metodám. Alternativně lze k uložení jednotkových testů použít vnitřní třídu , aby měli viditelnost členů a atributů uzavírající třídy. V rozhraní .NET Framework a některých dalších programovacích jazycích lze k odhalení soukromých metod a dat pro přístup k testům použít částečné třídy .

Je důležité, aby takové testovací hacky nezůstaly v produkčním kódu. V jazyce C a dalších jazycích se direktivy kompilátoru, jako například, #if DEBUG ... #endifmohou umisťovat kolem takových dalších tříd a vlastně všech ostatních kódů souvisejících s testem, aby se zabránilo jejich kompilaci do uvolněného kódu. To znamená, že uvolněný kód není úplně stejný jako to, co bylo testováno jednotkou. Pravidelné spouštění méně, ale komplexnějších integračních testů typu end-to-end na finální verzi vydání může zajistit (mimo jiné), že neexistuje žádný produkční kód, který by se rafinovaně spoléhal na aspekty testovacího svazku.

Mezi praktiky TDD probíhá diskuse, zdokumentovaná v jejich blozích a dalších spisech, zda je moudré testovat soukromé metody a data tak jako tak. Někteří tvrdí, že soukromí členové jsou pouhým detailem implementace, který se může změnit, a mělo by jim to být umožněno, aniž by došlo k porušení počtu testů. Mělo by tedy stačit otestovat jakoukoli třídu prostřednictvím jejího veřejného rozhraní nebo prostřednictvím rozhraní podtřídy, kterému některé jazyky říkají „chráněné“ rozhraní. Jiní říkají, že zásadní aspekty funkčnosti mohou být implementovány v soukromých metodách a jejich přímé testování nabízí výhodu menších a přímějších jednotkových testů.

Software pro TDD

V TDD existuje mnoho testovacích rámců a nástrojů.

Rámce xUnit

Vývojáři mohou k vytváření a automatickému spouštění testovacích případů použít rámce testování pomocí počítače , běžně souhrnně pojmenované xUnit (které jsou odvozeny od SUnit, vytvořeného v roce 1998). Rámce xUnit poskytují možnosti ověřování testů ve stylu tvrzení a hlášení výsledků. Tyto funkce jsou pro automatizaci zásadní, protože přesouvají zátěž ověřování provádění z nezávislé činnosti následného zpracování na aktivitu, která je součástí provádění testu. Prováděcí rámec poskytovaný těmito testovacími rámci umožňuje automatické provádění všech testovacích případů systému nebo různých podmnožin spolu s dalšími funkcemi.

Výsledky TAP

Testovací rámce mohou přijímat výstup jednotkového testu v jazykově agnostickém protokolu Test Anything Protocol vytvořeném v roce 1987.

Padělky, falešné a integrační testy

Testy jednotek jsou pojmenovány tak, že každý testuje jednu jednotku kódu. Složitý modul může mít tisíc testů jednotek a jednoduchý modul může mít jen deset. Testy jednotek používané pro TDD by nikdy neměly překročit hranice procesu v programu, natož připojení k síti. Pokud tak učiníte, dojde ke zpoždění, které způsobí, že testy běží pomalu, a odradí vývojáře od spuštění celé sady. Představení závislost na externích modulů nebo dat lze také zapnout unit testy do integračních testů . Pokud se jeden modul chová špatně v řetězci vzájemně souvisejících modulů, není tak hned jasné, kde hledat příčinu poruchy.

Když se vyvíjený kód spoléhá na databázi, webovou službu nebo jakýkoli jiný externí proces nebo službu, vynucení oddělení testovatelných jednotek je také příležitostí a hybnou silou při navrhování více modulárního, testovatelnějšího a opakovaně použitelného kódu. Jsou nutné dva kroky:

  1. Kdykoli je v konečném návrhu potřeba externí přístup, mělo by být definováno rozhraní, které popisuje dostupný přístup. Diskuse o výhodách tohoto postupu bez ohledu na TDD najdete na principu inverze závislosti .
  2. Rozhraní by mělo být implementováno dvěma způsoby, z nichž jeden skutečně přistupuje k externímu procesu a druhý je falešný nebo falešný . Falešné objekty nemusí dělat nic jiného, ​​než přidat do protokolu trasování zprávu, jako například „Objekt osoby uložen“ , proti kterému lze pro ověření správného chování spustit testovací tvrzení . Falešné objekty se liší tím, že samy obsahují testovací tvrzení, díky nimž může test selhat, například pokud jméno osoby a další údaje nejsou podle očekávání.

Falešné a falešné objektové metody, které vracejí data, zdánlivě z úložiště dat nebo od uživatele, mohou procesu testu pomoci tím, že vždy vrátí stejná, realistická data, na která se testy mohou spolehnout. Lze je také nastavit do předdefinovaných poruchových režimů, aby bylo možné vyvíjet a spolehlivě testovat rutiny pro zpracování chyb. V chybovém režimu může metoda vrátit neplatnou, neúplnou nebo nulovou odpověď nebo může vyvolat výjimku . V TDD mohou být užitečné i falešné služby jiné než úložiště dat: Falešná šifrovací služba nemusí ve skutečnosti zašifrovaná data zašifrovat; služba falešných náhodných čísel se může vždy vrátit 1. Falešné nebo falešné implementace jsou příklady injekce závislosti .

Testovací dvojka je schopnost specifická pro test, která nahrazuje schopnost systému, obvykle třídu nebo funkci, na které závisí UUT. Existují dva časy, kdy lze do systému zavést testovací dvojníky: propojení a spuštění. Náhrada času propojení je, když je testovací dvojka zkompilována do zaváděcího modulu, který je proveden za účelem ověření testování. Tento přístup se obvykle používá při běhu v jiném než cílovém prostředí, které pro kompilaci vyžaduje kód hardwaru na úrovni hardwaru. Alternativou k substituci linkeru je substituce za běhu, při které se během provádění testovacího případu nahradí skutečná funkčnost. Tato náhrada se obvykle provádí prostřednictvím opětovného přiřazení známých ukazatelů funkcí nebo nahrazení objektu.

Testovací čtyřhra má několik různých typů a různé složitosti:

  • Dummy - Dummy je nejjednodušší forma testovacího dvojníka. Usnadňuje nahrazení času linkeru poskytnutím výchozí návratové hodnoty tam, kde je to požadováno.
  • Stub - pahýl přidává figuríně zjednodušující logiku a poskytuje různé výstupy.
  • Spy - špion zachycuje a zpřístupňuje informace o parametrech a stavu, publikuje přístupové objekty k testování kódu pro soukromé informace, což umožňuje pokročilejší ověření stavu.
  • Mock - Falešný je určen individuálním případě test k ověření zkušební specifického chování, kontrola hodnot parametrů a sekvenční volání.
  • Simulátor-Simulátor je komplexní komponenta poskytující vyšší věrnost aproximace cílové schopnosti (věc, která se zdvojnásobuje). Simulátor obvykle vyžaduje značné dodatečné úsilí při vývoji.

Důsledkem takovéto injekční závislosti je, že skutečná databáze nebo jiný externí přístupový kód není nikdy testován samotným procesem TDD. Abychom se vyhnuli chybám, které z toho mohou vzniknout, jsou zapotřebí další testy, které vytvoří instanci kódu řízeného testem pomocí „skutečných“ implementací výše popsaných rozhraní. Toto jsou integrační testy a jsou zcela oddělené od testů jednotek TDD. Je jich méně a musí se spouštět méně často než jednotkové testy. Lze je však implementovat pomocí stejného testovacího rámce.

Integrační testy, které mění jakékoli trvalé úložiště nebo databázi, by měly být vždy pečlivě navrženy s ohledem na počáteční a konečný stav souborů nebo databáze, i když jakýkoli test selže. Toho je často dosaženo kombinací následujících technik:

  • TearDownMetoda, která je nedílnou součástí mnoha testovacích rámců.
  • try...catch...finally struktury pro zpracování výjimek, jsou -li k dispozici.
  • Transakce databáze, kde transakce atomicky zahrnuje operaci zápisu, čtení a odpovídající odstranění.
  • Pořízení „snímku“ databáze před spuštěním jakýchkoli testů a vrácení zpět na snímek po každém testovacím běhu. To lze automatizovat pomocí rámce, jako je Ant nebo NAnt, nebo systému kontinuální integrace , jako je CruiseControl .
  • Inicializace databáze do čistého stavu před testy, místo úklidu po nich. To může být relevantní tam, kde úklid může ztížit diagnostiku selhání testu odstraněním konečného stavu databáze před provedením podrobné diagnostiky.

TDD pro komplexní systémy

Cvičení TDD na velkých náročných systémech vyžaduje modulární architekturu, dobře definované komponenty s publikovanými rozhraními a disciplinované vrstvení systému s maximalizací nezávislosti na platformě. Tyto osvědčené postupy přinášejí zvýšenou testovatelnost a usnadňují aplikaci automatizace sestavení a testování.

Navrhování pro testovatelnost

Složité systémy vyžadují architekturu, která splňuje řadu požadavků. Klíčová podmnožina těchto požadavků zahrnuje podporu pro úplné a efektivní testování systému. Efektivní modulární design poskytuje komponenty, které sdílejí vlastnosti nezbytné pro efektivní TDD.

  • Vysoká soudržnost zajišťuje, že každá jednotka poskytuje sadu souvisejících schopností, a usnadňuje údržbu testů těchto schopností.
  • Nízká vazba umožňuje účinně testovat každou jednotku izolovaně.
  • Publikovaná rozhraní omezují přístup ke komponentám a slouží jako kontaktní body pro testy, usnadňují vytváření testů a zajišťují nejvyšší věrnost mezi konfigurací testovací a produkční jednotky.

Klíčovou technikou pro vytváření efektivní modulární architektury je modelování scénářů, kde je sestavena sada sekvenčních grafů, z nichž se každý zaměřuje na jeden scénář spuštění na úrovni systému. Scénářový model poskytuje vynikající nástroj pro vytváření strategie interakcí mezi komponentami v reakci na konkrétní podnět. Každý z těchto modelů scénářů slouží jako bohatý soubor požadavků na služby nebo funkce, které musí komponenta poskytovat, a také určuje pořadí, ve kterém tyto komponenty a služby vzájemně spolupracují. Modelování scénářů může výrazně usnadnit konstrukci testů TDD pro komplexní systém.

Správa testů pro velké týmy

Ve větším systému je vliv nízké kvality komponent ještě umocněn složitostí interakcí. Toto zvětšení činí výhody TDD ještě rychleji v kontextu větších projektů. Složitost celkové populace testů se však může stát problémem sama o sobě, což narušuje potenciální zisky. Zní to jednoduše, ale klíčovým počátečním krokem je rozpoznat, že testovací kód je také důležitý software a měl by být vytvářen a udržován se stejnou přísností jako produkční kód.

Vytváření a správa architektury testovacího softwaru v rámci komplexního systému je stejně důležitá jako architektura hlavního produktu. Testovací ovladače interagují s UUT, testují dvojníky a rámec testů jednotek.

Konference

První konference TDD se konala v červenci 2021. Konference byly zaznamenány na YouTube

Viz také

Reference

externí odkazy