Miroslav Holec

Software & Cloud Architect

miroslavholec.cz / blog / jak-zacit-psat-unit-testy

Jak začít psát unit testy

Miroslav Holec

Miroslav Holec

Publikován 7. dubna 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 7. dubna 2015.

Psaní unit testů na platformě .NET není žádná extra věda. Předpokladem je samozřejmě schopnost psát software dodržující všechny doporučované principy vývoje. Za takového předpokladu lze jednotkové testy označit jen za příjemnou formalitu. O smyslu a užitečnosti unit testů jsem psal v článku proč je důležité psát unit testy. V tomto článku popíšu jak začít psát unit testy.

Co je potřeba k psaní unit testů

Aby bylo možné psát všestranné unit testy, jsou k tomu potřeba 3 klíčové komponenty:

  1. testovací framework
  2. runner
  3. mockovací framework

Často se to všechno háže do jednoho pytle ale je dobrý mít trochu pořádek v pojmech. Tedy:

Testovací framework

Slouží k samotnému testování. Po založení testovacího projektu ve Visual Studiu lze najít v referencích testovací framework přímo do Microsoftu. Jedná se o Microsoft.VisualStudio.TestTools.UnitTesting. Testovací framework nám umožňuje označit (nebo vyloučit) třídy a metody k testování, případně označit metody, které se spustí před testem, po testu nebo před celou či po celé třídě. To se všechno děje pomocí datových anotací nad třídami a metodami. V neposlední řadě poskytuje testovací framework řadu assertů, které se používají pro porovnání očekávaného a skutečného výsledku a pomáhají tak určit, zda test prošel či nikoliv.

Testovacích frameworků existuje celá řada a nejedná se zrovna o nijak sofistikovaný kus software. Je prakticky jedno, který si vyberete, nicméně doporučuji dát přednost podvědomě známým frameworkům, které mají větší podporu runnerů. Obecně asi nejpoužívanější je NUnit, MsTest od Microsoftu nebo xUnit. Já budu všechno popisovat na NUnit.

  • Testovací framework NUnit ke stažení
  • Testovací framework xUnit ke stažení

Test runner

Úkolem test runneru je vyhledat v testovacím projektu všechny testy a ty následně spustit. Na základě výsledku assertů nebo chyb uvnitř metod tento runner vrací stav stacku, na základě kterého lze chyby snáze opravovat. Test runner má v sobě zabudované přímo Visual Studio ale stejně tak lze použít i jiný test runner. Některé testovací frameworky jsou dodávány i s test runnerem (například zmíněný NUnit) a takový runner se dá spouštět i mimo Visual Studio nad zkompilovaným kódem (assemblies).

Já mám osobně nejraději test runner od JetBrainsu, který se integruje přímo do Visual Studia a podporuje NUnit, xUnit i MsTest. Najít se dá buď v rozšíření ReSharper (nástroj určený primárně pro refactoring) nebo v dotCover (nástroj určený primárně pro zjednodušení testování). Za mě se klaním spíše k všestrannějšímu ReSharperu.

Mockovací framework

Poslední komponenta není teoreticky nutná ale její využití je široké (= neobejdete se bez ní). Mockovací framework umožňuje realizovat různá rozhraní a metody tříd nějakým definovaným chováním. Pokud testujeme metodu MethodA(), která využívá jinou závislost, pak často takovou závislost mockujeme, tedy nastavíme ji předpokládané chování na základě vstupu a díky tomu můžeme regulérně testovat aplikační kód vybrané testované metody MethodA(). V konečném důsledku toho, aniž bychom byli ovlivněny jinými částmi aplikačního kódu. Klíčová praktika v této oblasti je Dependency Injection a blíže se této tématice budu věnovat v některém z dalších článků.

Mockovacích frameworků je celá řada a tady už se vyplatí hodně pouvažovat nad výběrem. Osobně mám nejraději Moq, jelikož má velmi dobrou dokumentaci, existují pro něj návody, videotutoriály i knihy. - Mockovací framework Moq - Mockovací framework Rhino Mocks

Občas není jiná možnost, než použít více mockovacích frameworků. Důvodem může být to, že obecný mockovací framework (např.: Moq) neřeší nějakou konkrétní problematiku. Osobně občas doplňuji Moq o NSubstitute, který je použitelnější při mockování DbContextu (v případě použití Includes). Obecně je ale lepší usilovat o "přežítí" s jedním frameworkem.

Instalace všeho dohromady

Vycházejme z toho, že máme například obyčejnou knihovnu C# tříd, pro kterou chceme sestavit testovací projekt. Tato knihovna bude pro jednoduchost obsahovat jednu třídu, například BubbleSort pro celkem pomalé třídění polí. Algoritmus jsem si půjčil někde ze StackOverflow a nevím tedy, jestli je tato implementace funkční.

Výchozí situace

Založím si testovací projekt, tedy ve Visual Studiu si kliknu na solution a zvolím Add > New Project. Z možností si pak vyberu Unit Test Project a pojmenuji si ho například SortingArrays.Test. Ukončení testovacího projektu suffixem .Test je doporučená konvence.

Založení testovacího projektu

Dále přidám reference na projekty, které chci testovat. V mém případě je to jediná knihovna SortingArrays.Lib.

Nainstaluji si testovací framework, tedy v mém případě NUnit. Použiju Package Manager konzoli (View -> Other Windows > Package Manager Console) a odpálím příkaz nad testovacím projektem:

Install-Package NUnit -Version 2.6.4

V době psaní tohoto článku je k dispozici i beta verze, nicméně já chci instalovat konkrétní stabilní verzi 2.6.4.

Instalace NUnit

Teď ještě nainstaluji mockovací framework, abych měl do budoucnosti vše připravené. Postup je totožný, jen se změní název balíčku:

Install-Package Moq

Poslední co potřebuji je test runner. K tomu si nainstaluji JetBrains ReSharper, který podporuje nainstalovaný testovací framework NUnit. Teď je všechno připravené a můžu napsat první test.

První test

Unit Test není nic jiného než anotovaná C# třída s testovací metodou. Nad příkladem se v tomto článku nebudu pozastavovat (mám to v plánu jindy). Vytvořím si tedy C# class s názvem BubbleSortTests.cs:

using NUnit.Framework;
using SortingArrays.Lib;

namespace SortingArrays.Test
{
    [TestFixture]
    public class BubbleSortTests
    {
        [Test]
        public void Sort_ShouldSortNumbers()
        {
            BubbleSort bubbleSort = new BubbleSort();
            int[] array = {9, -7, 1, 5, 6, 1};

            int[] result = bubbleSort.Sort(array);

            Assert.AreEqual(-7, result[0]);
            Assert.AreEqual(1, result[1]);
            Assert.AreEqual(1, result[2]);
            Assert.AreEqual(5, result[3]);
            Assert.AreEqual(6, result[4]);
            Assert.AreEqual(9, result[5]);
        }
    }
}

Test pouze předá pole čísel do připravené metody a nakonci porovná, zda jsou čísla na správném místě.

Spuštění testu pomocí ReSharper test runneru

Test spustím například pomocí ikonky po levé straně od testu. Právě to považuji za velký přínos ReSharperu oproti chudším možnostem čistého Visual Studia.

Run tests

Následně se otevře okno Unit Test Session a test by měl být zelený.

Výsledky testu ve Visual Studiu

Spuštění mimo Visual Studio

Další možnost, jak testy spustit je mimo samotné Visual Studio. Použiju k tomu grafický runner NUNit GUI Runner (konkrétně stabilní verzi 2.6.4 / msi balíček).

Runner pak spustím z cesty c:\Program Files (x86)\NUnit 2.6.4\bin\nunit.exe. Editor je primitivní a celkem intuitivní.

  1. založím si nový projekt File > New Project
  2. přidám assembly pomocí Project > Add Assembly a vyberu SortingArrays.Test.dll
  3. zvolím Run

Po spuštění by měl jediný nalezený test opět zezelenat.

NUnit GUI runner

Tady bych upozornil na jedinou logickou odlišnost od Visual Studia. Zatímco Visual Studio si implicitně buildí assemblies před spouštěním testů, v případě externího spouštění test runneru na toto musí myslet vývojář a projekty si sám před testováním sestavovat.

Závěr

To je celá věda. Nainstalovaný mockovací framework ani nebyl potřeba a ani žádným způsobem neovlivňuje tento základní postup. Jakmile je jednou testovací projekt založen, stačí vytvářet jen nové testovací třídy a metody. Zda-li je během testu použit mockovací framework je pak vedlejší. Pokud nemáte rádi ReSharper, pak můžete místo frameworku NUnit používat ten od Microsoftu. Není potřeba ho ani instalovat, protože je součástí Visual Studia. Projekt nabízím volně ke stažení a obsahuje i variantu testu s MSTest.

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