pondělí 30. července 2012

Tell, Don't Ask

... aneb snižujte závislosti mezi třídami

Jedna z možných definic návrhového principu Tell, Don't Ask (TDA) zní takto:

"Každé rozhodování zcela závislé na vnitřním stavu objektu by mělo být prováděno uvnitř tohoto objektu."

Princip hovoří o tom, že bychom měli navrhovat třídy tak, aby se volající strana nemusela dotazovat na záležitosti týkající se vnitřního stavu volané třídy.

Ukázka porušení TDA

Mějme zjednodušený autobusový rezervační systém:

class Bus
{
    private int numberOfSeats;
    private IList<Passenger> passengers = new List<Passenger>();

    public Bus(int numberOfSeats)
    {
        this.numberOfSeats = numberOfSeats;
    }

    public bool HasFreeSeat
    {
        get
        {
            return numberOfSeats > passengers.Count;
        }
    }

    public void AddPassenger(Passenger passenger)
    {
        passengers.Add(passenger);
    }
}

class BusReservation
{
    public void AddPassengerToBus(Bus bus, Passenger passenger)
    {
        if (bus.HasFreeSeat)
        {
            bus.AddPassenger(passenger);
        }
    }
}

Proč je uvedené řešení problematické:

  • Základním principem OOP je zapouzdřenost interních dat objektu a jeho chování. Třída Bus však zbytečně zveřejňuje informaci o volných sedadlech a nutí volající stranu, aby s touto informací pracovala a zohledňovala ji před voláním metody AddPassenger.
  • Třída BusReservation je závislá na třídě Bus na dvou místech. Dotazováním na vlastnost HasFreeSeat a voláním metody AddPassenger. Každá nadbytečná závislost mezi třídami zvyšuje komplexitu návrhu a zhoršuje vlastnosti systému.
  • Třída Bus nutí volající stranu, aby měla znalost o tom, že před zavoláním AddPassenger si musí nejprve sama ověřit splnění kontraktů přidání cestujícího. S tím souvisí i závislost na správném pořadí volání. Samostatné volání HasFreeSeat nedává smysl.
  • Co když se v budoucnu změní podmínky, za kterých je možné přidat cestujícího? Nyní je přidání závislé pouze na volném sedadle, ale nově může přibýt podmínka typu "je autobus pojízdný". Pak bude nutné doplnit test na vlastnost IsMobile na všechna místa volání AddPassenger.
  • Každá nadbytečná závislost zvyšuje komplexitu jednotkových testů. Pokud chceme testovat třídu BusReservation v izolaci, musíme mockovat třídu Bus (nebo lépe rozhraní). V našem problematickém případě musíte přidat chování mocku pro vlastnost HasFreeSeats a metodu AddPassenger.

Vhodnější řešení

Odstraníme závislost volající třídy na dotazování se na volné sedadlo. Veškeré testy na proveditelnost akce přidání cestujícího jsou zapouzdřeny uvnitř metody AddPassenger. Pokud některá z podmínek není splněna, je vrácena výjimka, kterou zpracuje volající strana. Volající straně se situace zjednoduší.

class Bus
{
    private int numberOfSeats;
    private IList<Passenger> passengers = new List<Passenger>();

    public Bus(int numberOfSeats)
    {
        this.numberOfSeats = numberOfSeats;
    }

    private bool HasFreeSeat
    {
        get
        {
            return numberOfSeats > passengers.Count;
        }
    }

    public void AddPassenger(Passenger passenger)
    {
        bool isFull = !HasFreeSeat;

        if (isFull)
        {
            throw new Exception("Bus is full.");
        }

        passengers.Add(passenger);
    }
}

class BusReservation
{
    public void AddPassengerToBus(Bus bus, Passenger passenger)
    {
        bus.AddPassenger(passenger);
    }
}

Vezměte si na pomoc Adapter

Pokud využíváte rozhraní, které nemůžete měnit (komponenta třetí strany) a které porušuje TDA, můžete si pomoci návrhovým vzorem Adapter (Wrapper). Např. v jazyce C# je za příkazem foreach schován adaptér, který zjednodušuje práci se vším, co zveřejňuje metodu IEnumerator GetEnumerator(). Z IEnumerator pak postupně volá metodu bool MoveNext() a dotazuje se na vlastnost object Current { get; }. Více na stackoverflow.com.

Závěrem

Tak jako většina principů a doporučení objektového návrhu, tak i TDA není možné bez rozmyslu aplikovat dogmaticky ve všech situacích. Záleží na zodpovědnosti navrhované třídy, zda-li poskytuje příkazy (commands) k vykonání nějaké akce nebo dotazy (queries) vracející vnitřní stavy objektu. V případě příkazů byste však měli o dodržování principu TDA usilovat.

pondělí 9. července 2012

Peníze až na čtvrtém místě

Richard Florida ve své knize The Rise of the Creative Class zveřejnil zajímavé výsledky výzkumu o motivování lidí. Více jak 20 000 pracovníků z IT mělo z celkem 38 různých faktorů vybrat ty, které je nejvíce ovlivňují a motivují v jejich práci. Top 10 vypadá takto:

  1. Náročnost úkolů a zodpovědnost
  2. Flexibilita
  3. Stabilní pracovní prostředí
  4. Peníze
  5. Profesní rozvoj
  6. Uznání kolegů
  7. Motivující spolupracovníci a nadřízení
  8. Vzušující náplň práce
  9. Firemní kultura
  10. Umístění a komunita

Pokud na výsledky pohlížíte z perspektivy zaměstnance, snáze pochopíte, v jakém prostředí může vyniknout Váš kreativní potenciál. Máte-li na výběr, hledejte firmu, která nabízí zajištění co nejvíce motivátorů ze seznamu. Pokud ve Vaší stávající firmě není splněna většina věcí ze začátku seznamu, měli byste se vážně zamyslet, zda-li v takové firmě chcete nadále ztrácet svůj čas.

Průzkum by měl být přínosný také pro zaměstnavatele a vedoucí týmů. Pokud chtějí z lidí dostat maximum a zajistit jejich spokojený pracovní život, měli by realizovat opatření, která napomáhají motivovat. Nerespektování těchto faktů obvykle zabíjí inovaci, zvyšuje fluktaci lidí a v konečném důsledku snižuje úspěšnost firmy.

Florida nám předkládá potvrzení faktu, že peníze nejsou dostatečným dlouhodobým motivátorem u kreativních lidí. V určité fázi pracovního vývoje totiž můžete zjistit, že přestože vyděláváte slušný balík, nejste spokojeni. Dostali jste se zřejmě na úroveň, kdy základní potřeby včetně finančních jsou uspokojeny, ale potřebujete navíc uspokojit Vaše seberealizační potřeby nejvyšší úrovně (viz. 4. a 5. patro Maslowovy pyramidy potřeb).

Pokud Vás zajímá problematika podpory kreativity v současné éře inovativní ekonomiky, můžete si přečíst knížku Nepostradatelní od Jan Melvil publishing. Seth Godin na mně působil zpočátku trochu jako otravný provokatér, ale s postupem času jsem na jeho hru přistoupil a začalo se mi to líbit. Doporučuji.

sobota 19. května 2012

Produktivní rychlokodér

... aneb ovládněte základy Vašeho řemesla

Je součástí Vaší profese vytváření programového kódu? Píšete kód produktivním způsobem? Znáte a používáte nástroje, které Vám pomáhají produktivitu zvyšovat? Saháte často při psaní kódu na myš?

Stává se téměř denně, že objevím nějakou novou fintu, kterou se snažím využít pro zlepšení své produktivity. Může se jednat o novou klávesovou zkratku, nový nástroj, novou techniku, zrychlení často se opakujícího postupu, apod. Pokud chceme svoji práci dělat co nejlépe, je potřeba systematicky pracovat na zvyšování naší kodérské produktivity.

Tento příspěvek se týká aspektů rychlosti vytváření programového kódu. Rád bych shrnul elementární dovednosti, které jsou nutným základem pro práci kodéra. Příklady v textu se týkají platformy Visual Studia, kterou používám. Předpokládám však, že pro jiná IDE existují ekvivalentní nástroje.

Hbité kodérovy prsty

Kolika prsty píšete a jak rychle? Díváte se při psaní na klávesnici? Děláte často chyby a musíte se při psaní vracet o odmazávat?

Někdo nepovažuje rychlost psaní u kodéra za příliš důležitou. Sami však tušíte, že je rozdíl mezi datlováním dvěma prsty a symfonií všech deseti. Rychlost se uvádí v úhozech (keystrokes) za minutu nebo v počtu napsaných slov za minutu (WPM). Změřte si svou rychlost např. na http://10fastfingers.com. Průměr je mezi 50 a 70 wpm. Pokud se dostanete nad 100 wpm, patříte mezi 20% nejrychlejších psavců. Raději nebudu uvádět kolik jsem naměřil sobě. :)

A jak tuto dovednost zlepšovat? Zkuste se naučit hmatovou metodu, která využívá všech deseti prstů. Pořiďte si ergonomickou klávesnici, která Vám bude vyhovovat.

Můžete si také přečíst, co si o dovednostech pro psaní textu myslí respektovaný Jeff Atwood v příspěvku We Are Typists First, Programmers Second.

Učte se klávesové zkratky a nesahejte na myš

Důležitost konkrétní klávesové zkratky pochopíte v momentě, kdy se ji naučíte. Od tohoto okamžiku se bez ní neobejdete. Zkratka většinou supluje akci, kterou můžete udělat myší nebo posloupností více klávesových akcí. Obě metody jsou obvykle pomalejší než zkratka (od toho je to zkratka :). Základní sadu klávesových zkratek má vaše IDE, další dodají dodatečná rozšíření. Pro Visual Studio platí, že základ je sice ok, ale teprve s rozšířením typu CodeRush nebo ReSharper povýšíte z akumulační vrtačky na pořádnou příklepovku! Investice do kvalitních rozšíření se určitě vyplatí.

Doporučuji vytisknout cheat sheety s přehledem klávesových zkratek Vašeho IDE a rozšíření. Zdroje pro Visual Studio (Microsoft, DoFactory), CodeRush a ReSharper. Postup učení pak může být takový, že si nejprve přečtete referenční přehled zkratek, abyste dostali do podvědomí, co všechno se dá "zkracovat". Pak se snažíte před každou požadovanou akcí vzpomenout si na příslušnou zkratku. Několikrát požádáte papír o nápovědu a podle konkurenceschopnosti vaší střednědobé paměti si zkratku zapamatujete. Zkratek bývá velké množství a jsou strukturovány do menších oblastí. Zřejmě i zde platí Paretovo pravidlo, že 20% zkratek budete využívat v 80% případů. Naučte se tedy alespoň těch 20%.

Automatické doplňování a kontextový našeptávač

Ve VS je k dispozici nástroj IntelliSense. Podle aktuálního kontextu, části zadaného jména a s využitím reflexe, Vám například nabídne rychlé vložení příslušného jména identifikátoru. Předpokládám, že není nikdo, kdo by nabízenou pomoc od IntelliSense odmítal. Ne každý však umí IntelliSense vyvolat explicitně (Ctrl + J), zobrazit si informace o metodě a jejích parametrech (Ctrl + Shift + Spacebar), apod.

Vkládání bloků kódu

Psaní kódu není psaní beletrie, ale má charakter kompozice jednoduchých opakujících se bloků kódu do složitějších celků. Nabízí se tedy s těmito bloky pracovat efektivněji. Ve většině IDE je k dispozici podpora code snippetů. Jedná se o předpřipravené kusy kódu s možností definice parametrických částí. Vložení těchto kusů kódu provedete zadáním zkratky snippetu a odesláním řídícího znaku (ve VS tabulátoru). Napište např. foreach a stiskněte tabulátor. Editor v IDE Vám doplní celý blok příkazu foreach s možností změnit názvy parametrizovatelných částí.

V základu vašeho IDE je k dispozici množina předdefinovaných snippetů. Zajímavé jsou však i snippety, které si vytvoříte sami. Pokud používáte nějakou typickou sekvenci nebo blok kódu, určitě si pro něj vytvořte snippet. VS nemá ideální podporu pro vytváření vlastních snippetů a proto musíte vzít zavděk některými externími editory. Např. Snippy nebo Snippet Editor. Doporučuji vytvořit snippety pro Váš projekt a spravovat je centrálně v repository. Budou je mít k dispozici všichni členové týmu.

Rozšíření CodeRush nabízí aparát šablon. V daném kontextu je k dispozici zkratka, která odpovídá klíčovému slovu, názvu datového typu nebo nějaké složitější sekvenci. Stačí pak zadat např. t a po stisku mezerníku bude doplněno true. Šablony jsou inteligentní a jajich použití je variabilní a uživatelsky rozšiřitelné.

Dogenerování chybějícího kódu

Poměrně často používám klávesovou zkratku Ctrl + ., která podle aktuálního kontextu doplňuje chybějící kód. Umí doplnit using pro relativně odkazovanou třídu, vygenerovat pole nebo vlastnost třídy, vytvořit kostru neexistující metody (při použití metody shora-dolů), provést implementaci rozhraní, apod. Bez této funkce (klávesové zkratky) bych se už neobešel.

Vylepšování kódu pomocí refaktorizace

Znalost refaktorizačních technik by měla být v repertoáru každého kodéra. Mezi základní techniky patří přejmenování, vyčlenění kódu do samostatné metody, práce s argumenty metody, apod. Další typy refaktorizací mohou přidat rozšíření. Refaktorizaci použijete v situaci, kdy chcete stávající kód vylepšit (zlepšit čitelnost a udržovatelnost). Pěkné příklady jsou například na sourcemaking.com.

Generování kódu

Ke generování větších a složitějších bloků kódu můžete využít podporu T4 šablony. Generovat se dá z logických DSL modelů, z databázových dotazů a dalších kolekcí. Jedná se o efektivní a dobře použitelný nástroj. Můžete mrknout na ukázku.

Navigace v kódu

Umět se rychle dostat na určité místo kódu je neméně důležité jako umět kód vytvářet. Čím je projekt rozsáhlejší, tím jsou nároky na navigaci v kódu vyšší. Pokud však ovládáte klávesové zkratky pro přechod k deklaraci, na předchozí místo v kódu, do konkrétní třídy, apod. nebude pro Vás tato činnost problém. Některé techniky, jako například Test Driven Development, vyžadují cyklické provádění stejné posloupnosti akcí. V těchto případech mohou být rozdíly v produktivitě markantní.

Důležitá je i navigace mezi částmi IDE. Např. přechod do okna s chybami kompilace, do okna s testy, do Solution Exploreru, apod. Na většinu akcí by opět měly být k dispozici klávesové zkratky. Jen se je naučit.

Jak se dále zlepšovat?

  • Vyzkoušejte párové programování a pečlivě sledujte Vašeho spolukodéra. Snažte se pochytit jeho dobré návyky.
  • Sledujte blogy, které píší o používání Vašich nástrojů a zvyšování produktivity.
  • Pokud máte problém, snažte se jej vyřešit automatizací i za cenu (přiměřeně) vyšších startovních nákladů na naučení.
  • Účastněte se programátorských cvičení typu CodeRetreat.
  • Trénujte. ;)

čtvrtek 5. dubna 2012

Programová chyba jako test charakteru

Někdy je zajímavé sledovat, jak programátoři reagují na nahlášení chyby, za kterou jsou zodpovědní. Málo co odhalí lidský charakter tak, jako chování v relativně krizové situaci. Pokusil jsem se s mírnou nadsázkou popsat typologií programátorů právě podle jejich reakcí na chybu. Možná se poznáte nebo třeba někoho z vašich kolegů. :)

Já přeci chyby nedělám

Zastánce této techniky, pan Božský, se snaží za každou cenu zbavit zodpovědnosti za chybu. Případné přiznání chyby by mu narušilo vlastní pocit idealismu, který chová vůči své osobě.

"Chyba sice nastala v mojí třídě, ale vůbec jsem netušil, že ji budeš používat takto!
To je cílené chování aplikace dle specifikace."

Přestože se aplikace chová objektivně špatně a specifikace vůbec neexistuje. Dost času ztrácíte tím, že musíte dotyčného přesvědčit o jeho zodpovědnosti za chybu.

Hulk

Nahlásit chybu takovému programátorovi se obvykle trochu bojíte. Víte, že jeho počáteční reakce je dost agresivní. Zbledne, pak zezelená, natlakuje se, začne prskat a hledat nějaký cíl, na který by se mohla svalit část viny za vznik chyby.

"Sakra, zase to někdo pořádně neotestoval!
Přeci jsem upozorňoval, že úprava může způsobit problémy!
No a co, že jsem to dal k otestování těsně před uzavřením iterace!"

Na hrubý pytel, hrubá záplata :)

Hlavně nenápadně a zatloukat

Programátor se doslechne o chybě, rychle ji opraví a tváří se jako by o žádné chybě ani nevěděl.

"Mně se chybu nedaří navodit. Prosím prověř (testere) chování v aktuální verzi.
Vidíš, že se to chová správně!"

Přiznání, že tam chyba opravdu byla, se od něho dobrovolně nedočkáte. Po urgencích se možná přizná, ale pachuť neupřímnosti zůstává.

Sebemrskačství

"Hrozně mě ta chyba mrzí! To snad není možné! Jak se to mohlo stát?! Takový jsem si dával pozor!"

Každá chyba je pro něho stresovou záležitostí. Každé šlápnutí vedle ještě více sráží jeho již tak nízké sebevědomí. Pošlete jej na kurs asertivního chování!

Alibismus ukrytý v pseudosložitosti

Zaplavit kolegy hromadou nadbytečných informací, které navodí dojem toho, že prostě chyba v tak komplikované situaci musela zákonitě vzniknout.

"Databáze je taková a maková, nastavení bylo netypické, plán optimalizace nepředpokládatelný. S tím jsem sice mohl počítat, ale těch možných stavů je tolik, bla bla bla ..."

Prostě to oprav a neztrácej svůj ani můj čas zbytečným vysvětlováním!

Jsem z planety pokročilých uživatelů

"Proč se tohle UI uživatelům nelíbí, vždyť je tam tolik funkcí a všechny jsou pěkně vidět naráz?!
Spousta informací pěkně rozmístěná po velkém formuláři.
Barvy jsou dostatečně výrazné, aby upozornily na důležité části UI.
Proč by to nemohlo zobrazit vždy dialogovou zprávu o úspěšném ukončení zpracování."

Takový člověk podle sebe a svých subjektivních vjemů chybně předpokládá chování ostatních uživatelů. Pokud nezná nebo nechápe základní pravidla uživatelské použitelnosti (UX), zkuste mu je vysvětlit. Ale ať už nediskutuje a upraví to!

A jaká by měla být správná reakce?

Jedná se o velmi zjednodušený postup, ale můžete zkusit třeba:

  1. Zajistěte si kompletní informace o chybě. Potřebujete znát kontext spuštěné aplikace (zákazník, operační systém, typ prohlížeče, apod.), postup navození chyby, popis co je vlastně chybou a jak by se měla aplikace správně chovat. Vše by mělo být součástí hlášení o chybě ve vašem systému na sledování chyb.
  2. Někdo by měl chybu klasifikovat. Určit její závažnost a přiřadit jí prioritu, která ovlivní rychlost její opravy. Měl by také domyslet nápravná opatření, např. opravu dat v databázi, apod.
  3. Chyba je směrovaná na vás. Objektivně rozhodněte, zda-li je problém opravdu na vaší straně nebo ji směrujte na příslušného správce části aplikace, se kterou chyba souvisí. Zkuste omezit počet přehazování chyby mezi řešiteli. Ztrácíte čas váš i ostatních.
  4. V rámci řešení můžete získat další informace o důsledcích chyby (výši škody). Zveřejněte tyto informace pro ostatní zainteresované kolegy. Buďte transaparentní, upřímní a nic nezatloukejte. Zvýšíte tím efektivitu řešení problému.
  5. Odstraňte systémově příčiny problému tak, aby se chyba neopakovala. Přijměte nápravná opatření na související chyby. Napište programový test, který se bude provádět automaticky a upozorní na případné vrácení podobné chyby.
  6. Informujte o vyřešení chyby. Sdělte právě tolik informací, kolik postižená strana potřebuje vědět.

středa 21. března 2012

Automatické testování proti databázi

Proti databázi budete zřejmě spouštět testy pokrývající datovou vrstvu. U vyšších vrstev aplikace, použijete testovací databázi v situacích, kdy není vhodné datovou vrstvu mockovat. Testovací databáze se bude hodit v případě zátěžových a výkonnostních testů.

Dostupnost testovací databáze

Testy potřebujete spouštět na pracovních stanicích vývojářů, na buildovacím serveru nebo na jiném počítači, který nemusí být nutně připojen k počítačové síti. Je obvyklé, že databáze se zpřístupní v okamžiku spouštění testů a po jejich provedení se zahodí.

Není také vhodné, aby více běhových testovacích prostředí přistupovalo na stejnou instanci databáze. Mohly by se vzájemně ovlivňovat v operacích, které nejdou schovat do transakce (např. DDL příkazy).

Z uvedených důvodů se používají lokální databáze. V odůvodněných případech můžete použít i serverovou instanci databáze, ale toto řešení přináší jistá omezení plynoucí ze společného přístupu více testovacích klientů.

Rychlost vytvoření lokální databáze

Jeden z důležitých požadavků kladených na testy je jejich rychlost provádění. A databázové testy patří mezi ty nejpomalejší. Pokud používáte lokální databázi, musíte počítat s časovými režijemi na vytvoření instance databáze.

Nejrychleji startují paměťové (in-memory) databáze (např. SQLite) a databáze pracující nad datovými soubory. Pokud je vaše datová vrstva nezávislá na konkrétním typu databáze, můžete pro účely testů použít některou z rychlých variant, která neodpovídá produkční databázi. Např. u zákazníků běží vaše aplikace na MS SQL Serveru a na Oracle, ale testujete proti SQLite.

Jak to funguje u nás

V naší firmě jsme zvolili testovací databázi stejnou jako produkční a to MS SQL Server. Každý počítač, na kterém chceme spouštět testy, má instalován plnotučný MS SQL Server nebo alespoň MS SQL Server Express (na vývojářských stanicích). Při této variantě je nutné databázi obnovit (příkaz restore) z lokálního .bak souboru. Naše databáze má více jak 1000 tabulek a její obnovení trvá do 10 sekund. Optimalizací je to, že databázi obnovujeme pouze jednou, na začátku spouštění sady testů.

Soubor s databází je vytvářen ze serverové databázové instance, ke které je omezený přístup. Jsou na ní spouštěny pouze schválené změnové skripty a přímo na ní se netestuje. Soubor je uložen v systému pro správu zdrojových kódů a je synchronizován spolu se zdrojovými produkčními kódy a testy na počítač, kde se testy spouští.

Vývoj a spouštění testů probíhá nad více vývojovými větvemi. Pro každou větev je k dispozici kompatibilní databázový soubor s příslušnou strukturou.

Testovací data

Aby bylo možné validovat výsledek spuštění každého testu, musí být splněny vstupní podmínky. V případě testů proti databázi musí být k dispozici taková testovací data, která předpokládá test. Ideální situací je prázdná databáze před testem. Všechna data jsou pak v inicializaci testu do databáze vložena skriptem. Složitost databázových skriptů se liší podle testovaného problému a složitosti vazeb do podřízených tabulek.

Vyhněte se přípravě testovacích dat pomocí programových tříd. Může se stát, že test selže ve fázi právě této přípravy testovacích dat. Tím se celý test znehodnotí a chybně indikuje problém, který je zřejmě jinde než v testované části kódu. Navíc zbytečně zvyšujete složitost kódu testů.

Někdy může být výhodné mít v databázi část dat předvyplněných. Jedná se o data, která mají referenční charakter (jsou stejná na všech instalacích) nebo o data, která využívá většina testů - testovací aplikační uživatelé, testovací osoby, apod. Taková data musí být neměnná a testy s nimi musí počítat.

SQL skripty generující testovací data ukládejte do repository. Jeden skript může být použit pro celou sadu testů. Dokonce si dovedu představit, že skript, který generuje např. testovací objednávky, bude použit v testech datové vrstvy objednávek i funkcionality WCF služby pro práci s objednávkami.

Užitečné tipy

Uzavřete provádění celého testu do transakce, která vždy skončí příkazem rollback. Pro promítnutí změn do databáze použijte příslušnou funkci vašeho perzistentního frameworku. Např. pro (N)Hibernate je to funkce Flush() databázové relace.

Databázový uživatel, pod kterým spouštíte testy, by měl mít stejná oprávnění jako v produkčním prostředí. Vyhněte se uživatelům s DBA právy a uživateli, který je vlastníkem databázových struktur. Pod takovými uživateli může test projít, ale v produkci dojde k chybě.

Pokud se chcete vyhnout časově náročné obnově databáze před každým testem, můžete si pomoci "úklidem" databáze. Před nebo po každém testu spustíte skript, který smaže všechna data. V případě, že se vám daří provádět testy v transakci s rollbackem, nebude zřejmě úklid nutný.

Závěrem

Vyberte si vhodnou strategii, která bude vyhovovat vašim potřebám. Efektivní vytváření a spouštění testů zvýší vaši produktivitu práce a vnese potřebnou jistotu do udržovatelnosti aplikace.