Miroslav Holec

Software & Cloud Architect

miroslavholec.cz / blog / jiny-pohled-na-testovani-a-unit-testing

Jiný pohled na testování a unit testing

Miroslav Holec

Miroslav Holec

Publikován 6. srpna 2015 , aktualizace: 29. března 2016

Tento článek je starší 18 měsíců a je proto možné, že popisuje postupy nebo technologie, které v uplynulé době mohly doznat výraznějších změn. Názory a myšlenky v tomto článku již nemusí vyjadřovat současné stanovisko autora nebo autorů. Článek byl napsán 6. srpna 2015.

Přiznám se, že mi stále leží v žaludku odpor řady vývojářů k unit testům. Dost možná je to způsobeno tím, že unit testy a manuální testování debugováním se od sebe odděluje místo toho, aby se hledala mezi těmito metodikami určitá spojitost.

Aplikační kód testuje každý vývojář

Pokud vývojář napíše jakýkoliv kus kódu, nakonec ho musí otestovat (v praxi to tak samozřejmě často nefunguje). Představme si příklad webové aplikace.

public interface IExampleRepository
{
	List<Example> GetExamples();
}

public interface IExampleService
{
	ObjectResponse<ExampleViewModel> GetExamples();
}

public interface IExampleMap
{
	ExampleViewModel ToViewModel(Example example);
}

public class ExampleMap : IExampleMap
{
	public ExampleViewModel ToViewModel(Example example)
	{
		...
		viewModel.MyProperty = example.MyProperty.MyExtensionMethod();
		...
}

Napíšu si repositář a potřebuji vědět, zda vrací očekávaná data. Jenomže ještě potřebuji službu, abych ho měl odkud volat. Mám kolekci, kterou budu chtít ze služby vracet, ale ještě si napíšu extension metodu pro přeformátování stringu. Službu mám hotovou ale zjistím, že ještě potřebuju ideálně controller, kde si službu zavolám.

Udělám si tedy controller - v lepším případě ne testovací ale takový, který skutečně zůstane součástí produkčního kódu. Pokud controller nebudu potřebovat, tak si prostě službu zavolám z jiného už existujícího controlleru a pak ten kód smažu. Tak a teď controller zavolám a budu doufat, že všechno zafunguje. Samozřejmě už při prvním volání controlleru tuším, že něco nedopadne dle očekávání.

Masochistické testování

A teď přichází na řadu debugging. Ten mám rád. Protože se stalo něco neočekávaného, začnu debugovat všechny vrstvy a všechen kód, který jsem dopoledne napsal. Chybu nakonec najdu a opravím. Nezbývá než poslat dalších 10 requestů na controller, abych otestoval zbývající scénáře. U sedmého requestu zjistím, že nějaká extension metoda mi vyhořela, protože do ní přijela null hodnota. Oukej, opravím , zajdu na oběd a pak začnu "testovat" znova. Pošlu dalších 10 requestů na controller a budu doufat, že teď už to všechno vyjde.

Nejlépe dvakrát do týdne

Venku se stmívá, vše se zadařilo, kód je v produkci. Po dvou dnech přichází projekťák a s tvrdým výrazem ve tváři oznamuje, že stránka kterou jsem sestavil se bude muset změnit, jelikož klient volal, že [cokoliv si doplňte]. Jo a musí to být ASAP.

Tak jednoduše sáhnu na repositář, službu nebo úplně jinam a poté se pustím opět do masochistického testování odstřelováním controlleru. Vlastně ne. Má to být ASAP. Jsem přece profík a změnil jsem jen jednu hodnotu. To bude fungovat. Nasadím to.

Nešlo by to všechno snadněji?

Co kdybych si různé části kódu otestoval tak, abych místo neustálého debugování mohl jít třeba na oběd? A abych nemusel vytvářet controller a deset dalších tříd jen proto, že se potřebuju requestem prosekat až k extension metodě? Jednoduše si vytvořím šablonu v ReSharperu nebo ve Visual Studiu a založím si test. Nebo prostě napíšu 11 řádků kódu.

[TestFixture]
public class MyTests
{
    [Test]
    public void MyMethodName()
    {
        string original = "abc";
		string result = original.MyExtensionMethod();
		Assert.AreEquals("a b c", original);
    }
}

Otestuju to rychleji

Scénáře se díky unit testům dají řešit mnohem snadněji. Vytvořím parametrický test a pošlu do něj X testovacích hodnot. Nebo vymyslím cokoliv jiného a můžu být klidný, že si testuju "na svém písku", aniž bych ovlivňoval produkční kód. Pomocí unit testu získám nad aplikačním kódem kontrolu a zároveň budu cítit určitou svobodu v podobě možnosti cokoliv bezpečně změnit.

Až to bude fungovat, můžu to vylepšit

Když už mám testy, které si můžu spustit a za 2 sekundy vidět výsledek, můžu věnovat čas tomu, že můj kód zrefaktoruju. Až to dokončím, jen si otestuju, zda pořád vše funguje. Za 2 vteřiny. A pokud mám plugin NCrunch, tak ani nemusím nic spouštět a neustále vidím, že vše funguje. Bez námahy. Najednou mám čas psát lepší kód, protože v hlavně se mi už nehoní myšlenka "když to teď přepíšu, budu to muset zase otestovat".

Možná odhalím i špatný návrh

Když budu mít pocit, že se něco testuje špatně, možná mě to donutí napsat aplikační kód lépe. Tak nějak mi dojde, že asi nedodržuji určité principy objektově orientovaného návrhu. A skutečně z mého pohledu jeden z nejdůležitějších principů vývoje aplikací, Separation of Concerns, dnes notoricky dodržuji hlavně díky pozitivnímu přístupu k unit testům.

Nebojím se to předělat

Až totiž přijde projekťák, že má stránka vypadat jinak a že to musí být ASAP, tak si jenom upravím testy tak, aby odpovídaly zadání a poté doladím kód tak, aby vše zezelenalo. Unit testy mi opět pomáhají a svým způsobem činí práci i pestřejší a zábavnější. No a co když klient přijde se sekerou v ruce s tím, že na stránce je další velmi specifická chyba? Pak jen dopíšu scénář mezi ostatní testy a spustím to. S testy chybu odhalím rychleji a jakoukoliv změnu okamžitě můžu otestovat na novém scénáři. Celou dobu přitom běží i všechny dosavadní testy a já mám jistotu, že řešením nového problému nerozbiju to, co ještě včera fungovalo.

Jakou cestou se vydat?

Nemusím ani vědět, co je to Test First nebo Test Driven Development. I s přístupem test after si usnadním práci a ušetřím plno času. Jediné co musím udělat, je založit si testovací projekt a sázet do něj testy jeden za druhým. Ne proto, abych něco někde pokryl. Ne proto, že TDD nebo Test First je cool. Ale proto, abych si usnadnil v určitých situacích čas. Unit resty nejsou náboženství nebo spása vývojářského světa. Jsou ale dobrým pomocníkem. Stačí si uvědomit, jakou přidanou hodnotu a potenciál napsaný test pro vývojáře má.

Potřebujete pomoci?

Líbil se Vám článek? Máte dotaz nebo chcete v této oblasti s něčím pomoci? Neváhejte se na mě obrátit.

mirek@miroslavholec.cz

  • Řešení vývojářských problémů
  • Konzultace
  • Firemní školení a workshopy