it-swarm-eu.dev

Existuje něco jako mít příliš mnoho testů jednotek?

Mám za úkol psát testy jednotek pro existující aplikaci. Po dokončení prvního souboru mám 717 řádků testovacího kódu pro 419 řádků původního kódu.

Bude tento poměr nezvládnutelný, protože zvyšujeme pokrytí kódem?

Mé chápání testování jednotek bylo otestovat každou metodu ve třídě, aby se zajistilo, že každá metoda funguje podle očekávání. Avšak v požadavku tahu můj technický vedoucí poznamenal, že bych se měl zaměřit na testování na vyšší úrovni. Navrhl testování 4–5 případů použití, které se nejčastěji používají s danou třídou, spíše než důkladné testování každé funkce.

Věřím, že můj technický komentář je. Má více zkušeností než já a má lepší instinkty, pokud jde o navrhování softwaru. Jak ale tým pro více lidí píše testy na takový nejednoznačný standard; to je, jak poznám své vrstevníky a sdílím stejný nápad pro „nejčastější případy použití“?

Podle mě je pokrytí 100% jednotkových testů vznešeným cílem, ale i kdybychom dosáhli pouze 50%, věděli bychom, že 100% z těchto 50% bylo pokryto. Jinak psaní testů pro část každého souboru ponechává spoustu prostoru pro podvádění.

143
user2954463

Ano, se 100% pokrytím budete psát několik testů, které nepotřebujete. Bohužel jediným spolehlivým způsobem, jak určit, které testy nepotřebujete, je napsat je všechny a poté počkat asi 10 let, abyste zjistili, které z nich nikdy selhaly.

Udržování mnoha testů není obvykle problematické. Mnoho týmů má automatizovanou integraci a testy systému na 100% pokrytí testem jednotek.

Nejste však ve fázi údržby testu, hrajete dohání. Je mnohem lepší mít 100% vašich kurzů při 50% testovacím pokrytí než 50% vašich kurzů při 100% testovacím pokrytí a zdá se, že váš náskok se snaží přimět vás, abyste odpovídajícím způsobem přidělili svůj čas. Poté, co máte tuto základní linii, pak dalším krokem je obvykle tlačení o 100% u souborů, které se v budoucnu změní.

180
Karl Bielefeldt

Pokud jste pracovali na velkých kódových základech vytvořených pomocí testu řízeného vývoje, už byste věděli, že může existovat něco jako příliš mnoho testů jednotek. V některých případech většina vývojového úsilí spočívá v aktualizaci testů nízké kvality, které by se nejlépe prováděly jako invariantní, předběžné a postconditionové kontroly v příslušných třídách za běhu (tj. Testování jako vedlejší účinek testu vyšší úrovně). ).

Dalším problémem je vytváření nekvalitních návrhů, které využívají konstrukční techniky řízené nákladem, jejichž výsledkem je proliferace věcí k testování (více tříd, rozhraní atd.). V tomto případě se může zdát, že zátěž je aktualizace testovacího kódu, ale skutečným problémem je nízká kvalita designu.

68
Frank Hileman

Odpovědi na vaše otázky

Existuje něco jako mít příliš mnoho testů jednotek?

Jistě ... Mohli byste mít například několik testů, které se na první pohled zdají být odlišné, ale ve skutečnosti testovat stejnou věc (logicky závisí na stejných řádcích testovaného „zajímavého“ kódu aplikace).

Nebo byste mohli vyzkoušet interní části vašeho kódu, které se nikdy nedostanou ven (tj. Nejsou součástí jakékoli smlouvy o rozhraní), kde by se dalo hádat, zda to vůbec dává smysl. Například přesné znění zpráv interního protokolu nebo cokoli jiného.

Mám za úkol psát testy jednotek pro existující aplikaci. Po dokončení prvního souboru mám 717 řádků testovacího kódu pro 419 řádků původního kódu.

To mi připadá celkem normální. Vaše testy utrácí spoustu řádků kódu na nastavení a roztržení na vrcholu skutečných testů. Poměr se může zlepšit nebo nemusí. Já sám jsem docela test těžký, a často investovat více l-o-c a čas na testy, než skutečný kód.

Bude tento poměr nezvládnutelný, protože zvyšujeme pokrytí kódem?

Tento poměr tolik nezohledňuje. Existují další vlastnosti testů, které je činí neovladatelnými. Pokud při provádění poměrně jednoduchých změn v kódu musíte pravidelně testovat celou řadu testů, měli byste se dobře podívat na důvody. A to není to, kolik řádků máte, ale jak přistupujete k kódování testů.

Mé chápání testování jednotek bylo otestovat každou metodu ve třídě, aby se zajistilo, že každá metoda funguje podle očekávání.

To je správné pro „jednotkové“ testy v přísném smyslu. Zde je „jednotka“ něco jako metoda nebo třída. Smyslem testování jednotky je otestovat pouze jednu konkrétní jednotku kódu, ne celý systém. V ideálním případě byste odstranili celý zbytek systému (pomocí čtyřhry nebo co jiného).

Avšak v požadavku tahu můj technický vedoucí poznamenal, že bych se měl zaměřit na testování na vyšší úrovni.

Pak jste upadli do pasti předpokládat, že lidé skutečně znamenali testy jednotek, když řekl testy jednotek. Potkal jsem mnoho programátorů, kteří říkají „test jednotky“, ale znamenají něco úplně jiného.

Navrhl testování 4–5 případů použití, které se nejčastěji používají s danou třídou, spíše než důkladné testování každé funkce.

Jistě, soustředění se na nejlepších 80% důležitých kódů také snižuje zatížení ... Oceňuji, že si myslíte o svém nadřízeném vysoce, ale tohle mě nezdá jako optimální volba.

Podle mě je pokrytí 100% jednotkových testů vznešeným cílem, ale i kdybychom dosáhli pouze 50%, věděli bychom, že 100% z těchto 50% bylo pokryto.

Nevím, co je „test jednotkových testů“. Předpokládám, že máte na mysli „pokrytí kódu“, tj. Že po spuštění testovací sady byl každý řádek kódu (= 100%) proveden alespoň jednou.

Jedná se o metriku pěkného ballparku, ale zdaleka ne nejlepší standard, na který by se mohl střílet. Pouhé provedení řádků kódu není celý obrázek; toto nezohledňuje různé cesty například složitými vnořenými větvemi. Je to spíše metrika, která ukazuje prstem na kousky kódu, které jsou testovány příliš málo (samozřejmě, pokud je třída jako 10% nebo 5% pokrytí kódu, pak je něco špatně); na druhé straně 100% pokrytí vám neřekne, zda jste dostatečně testovali, nebo zda jste testovali správně.

Integrační testování

Je mi nepříjemné, když lidé neustále mluví o nit ​​testování dnes, ve výchozím nastavení. Podle mého názoru (a zkušeností) nit ​​testování je skvělé pro knihovny/API; v oblastech více zaměřených na podnikání (kde hovoříme o případech použití, jako je tomu v dané otázce), nemusí být nutně tou nejlepší volbou.

Pro obecný aplikační kód a v průměrném podnikání (kde je důležité vydělávat peníze, zasáhnout termíny a uspokojit spokojenost zákazníka a hlavně se chcete vyhnout chybám, které jsou buď přímo v obličeji uživatele, nebo které by mohly vést k skutečným katastrofy - nemluvíme zde o spuštění rakety NASA), integrační testy nebo testy funkcí jsou mnohem užitečnější.

Tito jdou ruku v ruce s vývojem řízeným chováním nebo vývojem zaměřeným na rysy; ty nepracují s (přísnými) jednotkovými testy, podle definice.

Aby byl krátký (ish), test integrace/funkce provede celý zásobník aplikací. Ve webové aplikaci by to fungovalo jako prohlížeč, který klikne na aplikaci (a ne, zjevně to není mít, aby byl tak zjednodušující, existují velmi silné rámce, aby to provedly - zkontrolujte out http://cucumber.io pro příklad).

Ach, abych odpověděl na vaše poslední otázky: dostanete celý tým, aby měl vysoké pokrytí testem tím, že se ujistíte, že nová funkce je naprogramována až po provedení a selhání testu funkce. A ano, to znamená každý funkce. Toto záruky vám 100% (pozitivní) pokrytí funkcí. Podle definice zaručuje, že funkce vaší aplikace nikdy „neodejde“. Nezaručuje 100% pokrytí kódem (například pokud aktivně nenaprogramujete negativní funkce, nebudete se zabývat zpracováním chyb/zpracováním výjimek).

Nezaručuje vám aplikaci bez chyb; samozřejmě budete chtít psát funkční testy pro zjevné nebo velmi nebezpečné situace v buggy, špatný vstup uživatele, hackerství (například správa relací, zabezpečení apod.) atd .; ale i programování pozitivních testů má obrovský přínos a je docela proveditelné pomocí moderních a výkonných rámců.

Testy funkcí/integrace zjevně mají svou vlastní plechovku červů (např. Výkon; redundantní testování rámců třetích stran; protože obvykle nepoužíváte čtyřhry, podle mých zkušeností také bývají těžší psát)), ale d každý den provádějte 100% aplikaci testovanou na pozitivní funkce přes 100% aplikaci testovanou na kódové pokrytí (nikoliv knihovnu!).

36
AnoE

Ano, je možné provést příliš mnoho testů jednotek. Pokud máte 100% pokrytí jednotkovými testy a například žádné integrační testy, máte jasný problém.

Některé scénáře:

  1. Přepracováváte své testy na konkrétní implementaci. Pak musíte zahodit jednotkové testy, když rozhodujete, neříkáte, když změníte implementaci (velmi častý bod bolesti při provádění optimalizace výkonu).

    Dobrá rovnováha mezi testy jednotek a testy integrace tento problém snižuje, aniž by došlo ke ztrátě významného pokrytí.

  2. Při každém odevzdání byste mohli mít přiměřené pokrytí 20% testů, které máte, zbývajících 80% zůstane na integraci nebo alespoň samostatné testovací průchody; hlavní negativní účinky, které vidíte v tomto scénáři, jsou pomalé změny, protože musíte čekat dlouhou dobu na provedení testů.

  3. Upravujete příliš mnoho kódu, abyste jej mohli vyzkoušet; například jsem viděl mnoho zneužívání IoC u komponent, které nikdy nebudou vyžadovat, aby byly modifikovány, nebo je alespoň generování nákladných a nízkých priorit, ale lidé investují mnoho času zobecněním a refaktorizací, aby jim umožnili testování jednotek .

Obzvláště souhlasím s návrhem získat 50% pokrytí na 100% souborů, namísto 100% pokrytí na 50% souborů; zaměřte své počáteční úsilí na nejčastější pozitivní případy a na nejnebezpečnější negativní případy, neinvestujte příliš mnoho do řešení chyb a neobvyklých cest, ne proto, že nejsou důležité, ale proto, že máte omezený čas a nekonečný testovací vesmír, takže v každém případě musíte upřednostnit.

25
Bruno Guardia

Mějte na paměti, že každý test má cenu i výhodu. Nevýhody zahrnují:

  • musí být napsán test;
  • test trvá (obvykle velmi malé množství) času na spuštění;
  • test musí být udržován s kódem - testy se musí změnit, když se API, která testují, mění;
  • možná budete muset svůj design změnit, abyste mohli napsat test (i když tyto změny jsou obvykle k lepšímu).

Pokud náklady převažují nad přínosy, je lepší test nenapsaný. Například, pokud je obtížné testovat funkčnost, API se mění často, správnost je relativně nedůležité a šance na nalezení chyby v testu je nízká, pravděpodobně nebudete lepší ji nenapsat.

Pokud jde o váš konkrétní poměr testů k kódu, pokud je kód dostatečně logický, pak tento poměr může být zaručen. Pravděpodobně však nestojí za udržení tak vysokého poměru v typické aplikaci.

19

Ano, existuje něco jako příliš mnoho testů jednotek.

Zatímco testování je dobré, každý test jednotky je:

  • Potenciální náklady na údržbu, které jsou úzce spojeny s API

  • Čas, který lze strávit něčím jiným

  • Kousek času v sadě Unit Test
  • Nemusí být přidávána žádná skutečná hodnota, protože ve skutečnosti je to duplikát jiného testu, který má nepatrnou šanci, že některý jiný test projde a tento test selže.

Je moudré usilovat o 100% pokrytí kódu, ale to zdaleka neznamená sadu testů, z nichž každý nezávisle poskytuje 100% pokrytí kódem v určitém specifikovaném vstupním bodě (funkce/metoda/volání atd.).

I když vzhledem k tomu, jak obtížné je dosáhnout dobrého pokrytí a vyhnat chyby, je pravdou, že existuje něco jako „nesprávné testy jednotek“, stejně jako „příliš mnoho testů jednotek“.

Pragmatika pro většinu kódu označuje:

  1. Ujistěte se, že máte 100% pokrytí vstupních bodů (všechno se nějak otestuje) a snažte se být blízko 100% pokrytí kódem cest bez chyb.

  2. Otestujte všechny příslušné minimální/maximální hodnoty nebo velikosti

  3. Vyzkoušejte cokoli, co si myslíte, že je zvláštní vtipný případ, zejména „liché“ hodnoty.

  4. Když najdete chybu, přidejte test jednotky, který by tuto chybu odhalil a přemýšlejte o tom, zda by se měly přidat nějaké podobné případy.

Pro složitější algoritmy zvažte také:

  1. Provádím hromadné testování více případů.
  2. Porovnání výsledku s implementací „brutální síly“ a kontrolou invariantů.
  3. Použití některé metody vytváření náhodných testovacích případů a kontroly proti hrubé síle a po kondici, včetně invariantů.

Například zkontrolujte třídicí algoritmus s nějakým náhodným vstupem a ověření dat je na konci tříděno skenováním.

Řekl bych, že váš technický vedoucí navrhuje testování „minimálního holého zadku“. Nabízím „testování nejvyšší kvality“ a mezi tím existuje spektrum.

Možná váš senior ví, že komponenta, kterou stavíte, bude zabudována do nějakého většího kusu a jednotka bude po integraci důkladněji testována.

Klíčovou lekcí je přidání testů, když jsou nalezeny chyby. Což mě vede mou nejlepší lekcí o vývoji jednotkových testů:

Zaměřte se na jednotky, nikoli na dílčí jednotky. Pokud stavíte jednotku z dílčích jednotek, psejte velmi jednoduché testy pro dílčí jednotky, dokud nebudou hodnověrné, a dosáhnete lepšího pokrytí testováním dílčích jednotek prostřednictvím svých řídicích jednotek.

Takže pokud píšete kompilátor a potřebujete napsat tabulku symbolů (řekněme). Vezměte tabulku symbolů do provozu se základním testem a poté pracujte na (řekněme) analyzátoru deklarací, který vyplňuje tabulku. K samostatné jednotce tabulky symbolů přidejte další testy, pouze pokud v ní najdete chyby. Jinak zvýšíte pokrytí jednotkovými testy na analyzátoru deklarací a později na celém kompilátoru.

To dává nejlepší třesk za babku (jeden test celku testuje více komponent) a ponechává větší kapacitu pro přepracování a zdokonalení, protože v testech, které mají tendenci být stabilnější, se používá pouze „vnější“ rozhraní.

Ve spojení s podmínkami testování ladicího kódu, po podmínkách včetně invariantů na všech úrovních získáte maximální pokrytí testem od minimální implementace testu.

13
Persixty

Za prvé, není nutně problém mít více řádků testu než výrobního kódu. Testovací kód je (nebo by měl být) lineární a snadno pochopitelný - jeho nezbytná složitost je velmi, velmi nízká, ať už je či není výrobní kód. Pokud se složitost testů začne blížit výrobnímu kódu, pravděpodobně máte problém.

Ano, je možné mít příliš mnoho jednotkových testů - jednoduchý myšlenkový experiment ukazuje, že můžete pokračovat v přidávání testů, které neposkytují další hodnotu, a že všechny tyto přidané testy mohou inhibovat alespoň některá refaktorizace.

Podle mého názoru je doporučení k testování pouze nejběžnějších případů chybné. Ty mohou působit jako kouřové testy, aby se ušetřil čas na testování systému, ale skutečně cenné testy zachycují případy, které je v celém systému obtížné uplatnit. Například, řízené chybové injekce selhání alokace paměti mohou být použity k výkonu cest obnovy, které by jinak mohly být zcela neznámé kvality. Nebo předejte nulu jako hodnotu, kterou znáte, použije se jako dělitel (nebo záporné číslo, které bude mít druhou mocninu) a ujistěte se, že neobdržíte neošetřenou výjimku.

Další nejcennější testy jsou ty, které provádějí extrémní limity nebo hraniční body. Například funkce, která přijímá (na základě 1) měsíce v roce, by měla být testována s 0, 1, 12 a 13, takže víte, že platné neplatné přechody jsou na správném místě. Pro tyto testy je také příliš testování.

Jste v obtížné pozici, v níž musíte psát testy na existující kód. Je jednodušší identifikovat případy Edge, když píšete (nebo se chystáte psát) kód.

3
Toby Speight

Mé chápání testování jednotek bylo otestovat každou metodu ve třídě, aby se zajistilo, že každá metoda funguje podle očekávání.

Toto chápání je špatné.

Jednotkové testy ověřují chování z testovaná jednotka.

V tomto smyslu jednotka není nutně „metoda ve třídě“. Líbí se mi definice jednotky od Roy Osherove v The Art of Unit Testing:

Jednotka je veškerý výrobní kód, který má stejný důvod ke změně.

Na základě toho by test jednotky měl ověřit každé požadované chování vašeho kódu. Pokud je „touha“ víceméně převzata z požadavků.


Avšak v požadavku tahu můj technický vedoucí poznamenal, že bych se měl zaměřit na testování na vyšší úrovni.

Má pravdu, ale jinak, než si myslí.

Z vaší otázky chápu, že jste v tomto projektu „oddaný tester“.

Velkým nedorozuměním je, že očekává, že budete psát testy jednotek (na rozdíl od „testu pomocí rámce pro testování jednotek“). Psaní testů ynit je odpovědnost vývojářů, nikoli testerů (v ideálním světě, já vím ...). Na druhou stranu jste tuto otázku označili pomocí TDD, což přesně znamená.

Úkolem testera je psát (nebo provádět ručně) testy modulů a/nebo aplikací. A tento druh testů by měl především ověřit, že všechny jednotky spolupracují hladce. To znamená, že musíte vybrat své testovací případy tak, aby každá jednotka byla provedeno alespoň jedno. A ta kontrola je, že běží. Skutečný výsledek je méně důležitý, protože se může měnit s budoucími požadavky.

Chcete-li ještě jednou zdůraznit analogii automobilu s výpisem: Kolik testů se provádí s autem na konci montážní linky? Přesně jeden: musí jet na parkoviště sám ...

Tady je:

Musíme si být vědomi rozdílu mezi „jednotkovými testy“ a „automatizovanými testy pomocí rámce pro testování jednotek“.


Podle mě je pokrytí 100% jednotkových testů vznešeným cílem, ale i kdybychom dosáhli pouze 50%, věděli bychom, že 100% z těchto 50% bylo pokryto.

Jednotkové testy jsou bezpečnostní sítí. Poskytují vám jistotu refactor váš kód pro snížení technického dluhu nebo přidání nového chování, aniž by se obávali přerušit již implementované chování.

Nepotřebujete 100% pokrytí kódu.

Ale potřebujete 100% pokrytí chování. (Ano, pokrytí kódu a pokrytí chování nějak korelují, ale kvůli tomu nejsou totožné.)

Pokud máte méně než 100% pokrytí chování, úspěšný chod vaší testovací sady neznamená nic, protože jste mohli změnit některé z netestovaných chování. A klient si toho všimne den poté, co bylo vaše vydání online.


Závěr

Jen málo testů je lepší než žádný test. Bezpochyby!

Ale není nic takového jako mít příliš mnoho jednotkových testů.

Je to proto, že každý test jednotky ověřuje jediné očekávání o kódech chování. A nemůžete psát více jednotkových testů, než jste očekávali od kódu. A díra v bezpečnostním postroji je šance, že nechtěná změna poškodí výrobní systém.

3
Timothy Truckle

Rozhodně ano. Býval jsem SDET pro velkou softwarovou společnost. Náš malý tým musel udržovat testovací kód, který dříve ovládal mnohem větší tým. Kromě toho měl náš produkt určité závislosti, které neustále přinášely zlomové změny, což pro nás znamená neustálé udržování testu. Neměli jsme možnost zvětšit velikost týmu, takže jsme museli zahodit tisíce méně cenných testů, když selhaly. Jinak bychom nikdy nebyli schopni držet krok s vadami.

Než to odmítnete jako pouhý problém s řízením, zvažte, že mnoho projektů ve skutečném světě trpí snížením počtu zaměstnanců, protože se přiblíží ke starému stavu. Někdy se to dokonce stává hned po prvním vydání.

2
mrog

Mít více řádků testovacího kódu než kód produktu není nutně problém, za předpokladu, že testovací kód refaktorizujete, abyste eliminovali kopírování a vkládání.

Problém je v tom, že máte testy, které jsou zrcadly vaší implementace, a nemají žádný obchodní význam - například testy načtené pomocí falešných a útržků a pouze tvrzení, že metoda volá jinou metodu.

Skvělý citát v dokumentu „proč většina testování jednotek je plýtvání“ je, že testy jednotek by měly mít „širokou, formální, nezávislou Oracle správnosti a ... připisovatelnou obchodní hodnotu“

1
wrschneider

Jedna věc, kterou jsem neviděl, je, že vaše testy musí být rychlé a snadné, aby se kterýkoli vývojář mohl kdykoli spustit.

Nechcete se muset přihlásit ke kontrole zdroje a čekat hodinu nebo déle (v závislosti na velikosti vaší základny kódu) před dokončením testů, abyste zjistili, zda vaše změna něco zlomila - chcete to udělat na svůj vlastní stroj předtím, než se přihlásíte k ovládání zdroje (nebo alespoň před provedením změn). V ideálním případě byste měli být schopni spustit testy pomocí jediného skriptu nebo tlačítka Push.

A když tyto testy provedete lokálně, chcete, aby fungovaly rychle - v řádu sekund. Pomaleji a budete v pokušení je nespustit dostatečně nebo vůbec.

Takže mít tolik testů, které je povedou všechny trvá několik minut, nebo mít několik příliš složitých testů, by mohl být problém.

0
mmathis