Test řízené vývojové války: Detroit vs Londýn, klasicista vs Mockist

Pamatuji si, když jsem se poprvé začal učit programovat a jeden z mých učitelů mi vysvětlil svět vývoje softwaru v jedné větě:

"Je to jen banda lidí v místnosti, hádající se mezi sebou"

Dále popsal, jak nikdy nedosáhnete konsensuální dohody v některých klíčových otázkách, jako je testování a design. Jeden starší vývojář může kázat jeden pohled a druhý kázat protichůdný pohled. Jeden bude trvat na tom, že napíšete nejprve specifikaci funkce, další popře vaši existenci, dokud nezačnete na úrovni jednotky.

V opačném pohledu by bylo užitečné věnovat více pozornosti opozičním kmenům testování a jejich různým neshodám. Procházení webu a hledání četných článků, které se navzájem protichůdně protínají, může být otevření mysli, ale je nepochybně matoucí. Jaký postup uplatňuji ve svém každodenním životě? Co když mě klasický pohled potěší a dává intuitivní smysl, ale rozzlobí ty v mém týmu?

Co je to klasicista a co je Mockist?

Tyto dva tábory se běžně označují jako Detroit School of TDD (nebo Classicist, státní testování, Inside-out, black-box testování) a London School of TDD (nebo Mockist, Interaction testování, Out-in testování, white- testování krabic). Oba souhlasí s tím, že TDD je účinný nástroj pro návrh, ale způsob, jakým používají TDD, se liší natolik, že je lze klasifikovat do dvou myšlenkových škol. Po dobu trvání tohoto článku budu tyto pojmy používat zaměnitelně.

Možná jste slyšeli o slavných praktikujících klasického TDD, včetně strýce Boba a Kent Beck. Pokud chcete příklad Mockistu, nehledejte dále než Sandi Metz, J.B Rainsberger nebo Steve Freeman.

Detroitská škola TDD začíná interním přístupem k testování. Testování začíná na úrovni jednotky a návrh má „vycházet“ z testů. Přiznám se, že kdykoli jsem to četl, trochu jsem se krčil. Jen proto, že píšete testy, neznamená to, že se váš návrh rozkvěte v záviděníhodné dílo technického umění. Chcete-li napsat dobrý design, musíte se naučit, dobře, design.

O strategiích a teoriích testování se můžete dozvědět vše, co potřebujete, ale bez nějakého základu v designu nelze očekávat vybudování dobře definovaného a rozšiřitelného systému, který bude imunní vůči budoucímu obchodnímu vývoji.

Klíčovým rysem Detroitovy školy je vyhýbání se falešným názorům. Teprve po přečtení tohoto jsem si uvědomil, že jsem se roky učil pouze londýnskou školu TDD (přece jen žiji v Londýně). Vždy jsem předpokládal, že to byla cesta. Řekněme, že máte třídu knih, která provádí nějakou obchodní logiku, a na konci je metoda výpočtu, která deleguje na jiný objekt:

def calc_total_balance (x, y)
 # komplexní obchodní logika, která mutuje xay
 some_calculator_object.sum (x, y)
konec

Klasici by to vyzkoušeli tvrzením o metodě Calc_total_balance a za předpokladu, že x a y jsou 2 a 5, závěrečný test by očekával hodnotu 7. Takže Detroitská škola se nebojí testování spolupracovníků instance nepřímo prostřednictvím rozhraní jiné třídy. Nebyly by zde představeny žádné zesměšňování.

Pokud by praktik londýnské školy testoval tuto individuální metodu, očekávání by nebylo 7, ale měli bychom něco jako

očekávat (any_instance_of (Kalkulačka)). získat (: součet) .s (2,5)

Argument Mockists je, že metoda sum v instanci Kalkulačky bude testována jinde, a my bychom nechtěli, aby se jednotkový test pro naši třídu Ledger přerušil kvůli změně implementace Kalkulačky. Testování, zda se zpráva dostane mezi objekty, je dostatečné. Přestože jsme tímto jednotkovým testem nepotvrdili, že chování skutečně funguje, jsme si jistí, že tomu tak je, protože jsme otestovali interakci mezi spolupracovníky a že dojde k dalšímu testu jednotek, který ve skutečnosti vytvoří tvrzení v instanci Sumář kalkulačky. metoda.

Klasici budou trvat na tom, že Mockistův přístup neudělá nic k potvrzení pracovního stavu aplikace, a také spojí testy s implementací. Pokud změníme naši metodu výše tak, aby používala, řekněme, CalculatorService, pak by chování zůstalo stejné a stále by nám bylo vráceno číslo 7, ale náš test by nyní vyvolal falešný poplach navzdory všemu, co funguje dobře.

Mockisté se vracejí a říkají, že protože by naše testy jednotek měly být izolované, nechtěli bychom, aby zlom v jednom spolupracovníkovi (řekněme v kalkulačce) vedl k selhání testů mezi jejich volajícími. Ano, aplikace je rozbitá, ale raději bychom raději jeden test neuspěli, než několik testů. Také to jsou integrované testy; k testování integrace mezi více objekty

Dalším způsobem, jak popsat rozdíly mezi klasickým a Mockistovým pohledem na testování, je použití státních testů a interakčních testů. Jak vidíte na příkladu Mockistu, londýnská škola by zdůraznila testování interakce mezi objekty a zajištění správného zasílání zpráv. Škola Detroit tvrdí, že mít více stavovou testovací architekturu by umožnilo nemilosrdné refactorování, a nadměrně zesměšňujete svázání svých objektů s rozhraními jejich spolupracovníků, a proto vytváříte flexibilnější testovací sadu.

Mocks rozbijí starou mantru, kterou by měl testovat rozhraní, ne implementace. Jakákoli změna povahy hovorů ke spolupracovníkům by testy přerušila bez ohledu na to, zda funkce byla v provozním stavu. Toto je jedna z běžných kritik londýnské školy testování.

Často budete slyšet o testování černé skříňky vs. testování bílé skříňky. Testování černé skříňky je spojeno se školou Detroit, zatímco druhé je spojeno s londýnskou školou. Takže stejně jako náš výše uvedený příklad knihy, klasicisté by neměli zesměšňovat objekt kolaborátora naší třídy knihy, ale místo toho považovali celé volání metody za černou skříňku. Volám metodu a očekávám, že se tento výsledek vrátí. Je mi to jedno.

Mockisté by raději vyzkoušeli testování v bílé krabici slovy: volám metodu a nestarám se o obecnou správnost metody, protože to komunikuje s jiným objektem, že testuji návratovou hodnotu jinde. Vše, na čem mi záleží, je to, že komunikuje efektivně.

Přál bych si, abych byl dost chytrý na to, abych ukončil tento blogový příspěvek poskytnutím solidního doporučení, který testovací přístup je lepší. Nicméně, stejně jako mnoho věcí v softwaru, existují kompromisy.

Kdybychom klasifikovali užitečné, vysoce cenné testy, které mohou přinést skutečnou obchodní hodnotu, učinil bych případ, že efektivní testy:

  1. Mají velkou šanci chytit regrese
  2. Mají nízkou šanci na výrobu falešných pozitiv
  3. Poskytněte rychlou zpětnou vazbu

Často je velmi obtížné maximalizovat každý jeden z nich, aniž by obětoval jednoho z ostatních. I když téměř všechny testy jednotek poskytují rychlou zpětnou vazbu a nastavení testů Mockist i Classicist poskytují pěknou bezpečnostní síť k zachycení regresí, je to druhý bod, který je často sporný. Architektura testů navržená londýnským školním praktikem s rozsáhlou sadou falešných příznaků pravděpodobně povede k mnoha falešným pozitivům a znemožní jakékoli budoucí refaktorské úsilí. Zatímco klasicistní testovací sada bude zahrnovat méně izolované jednotkové testy, které by se rozbily kvůli žádné chybě konkrétního testovaného subjektu. Redundantní pokrytí je anti-vzor, ​​kde je část výrobního kódu závislá na několika testech a je to něco, co je běžně spojeno se školou Detroit.

Měl jsem zábavný čas zkoumat různé myšlenkové vlaky mezi těmito nepřátelskými tábory. Od doby, kdy jsem se učil programovat, jsem byl vystaven hlavně testovacím sadám inspirovaným Mockistem a Londýnským školním praktikům. Měl jsem lidi, aby mi řekli, že je diabolské nepřímo testovat návratovou hodnotu spolupracovníka vyhýbáním se falešným falešům. Mít znalosti o protichůdných názorech a kompromisech mezi jednotlivými přístupy je neocenitelné a zajišťuje, že když uvidím kódovou základnu bez falešných, neměla bych být tak rychle soudit. A neměli byste také.