Testování v rozhraní .NET Core 2.0

Jednotkové a integrační testy s xUnit

Ahoj!

Zde je náš nový příspěvek o .NET Core.

V předchozím jsme se naučili, jak nasadit naši .NET Core aplikaci pomocí Docker. Nezapomeňte to zkontrolovat!

V tomto příspěvku budeme diskutovat o tom, jak vytvořit automatizované testy pro naši aplikaci. Automatizované testy jsou velmi důležitou součástí vývoje softwaru obecně a tento koncept se vztahuje také na .NET Core. Zjednodušuje provádění jednotkových a integračních testů, což vývojářům ušetří spoustu času.

Tento příspěvek vám poskytne představu o tom, jak implementovat testy vaší aplikace .NET Core.

Osobní zkušenost

Ve společnosti Wolox testujeme naše .NET Core projekty pomocí xUnit a testovacího příkazu dostupného v rozhraní .NET Core CLI. Toto není jediný způsob testování pro tento konkrétní rámec, ale je poměrně rychlé jej nastavit a pokrývá základy, jak začít na vaší cestě k produktivitě.

Je důležité, aby byl zdrojový kód naší aplikace připraven k testování. V tomto příkladu použijeme tento projekt, který je k dispozici na GitHubu.

Abychom udrželi strukturu čistou, rozdělíme náš kód do dvou složek:

  • Jeden pro zdrojový kód (src) a,
  • Jeden pro testy (test).

Měli bychom vytvořit nový testovací projekt ve zkušební složce.

Pro každou část tohoto příspěvku vytvoříme testovací projekt pomocí příkazu dotnet new, který vygeneruje nový projekt xUnit (dotnet new xunit). Jakmile máme testovací projekt, musíme odkazovat na zdrojový kód naší aplikace do souboru projektu. Můžeme tak učinit pomocí následujícího příkazu:

dotnet přidat odkaz ROUTE_TO_CSPROJ.csproj

To nám umožní použít jakékoli metody nebo třídy definované v našem hlavním projektu.

Jednotkové testy

Testování jednotek je docela jednoduché. To nám umožňuje testovat konkrétní moduly a komponenty našich aplikací. Cílem těchto druhů testů není funkčnost aplikace jako celku, ale konkrétní práce jednotek, které tvoří náš systém.

Tyto jednotky jsou obvykle specifické třídy nebo funkce, vyhodnocené, aby se zjistilo, zda očekávaný výsledek při použití jejich metod odpovídá tomu, co ve skutečnosti dostaneme.

V tomto příkladu vytvoříme třídu Helper (MathHelper.cs), která zapouzdří funkce, které budeme testovat. Bude to statická třída.

Pro testování těchto tříd vytvoříme soubor v našem testovacím projektu nazvaný UnitTestMathHelper.cs. Zde definujeme třídu se stejným názvem jako soubor a metodu nazvanou TestSum.

Značky [Fact] oznámí testovacímu projektu, že kódujeme testovací metody. Pro tuto aplikaci budeme testovat pouze dvě metody dostupné na našem pomocníkovi. Jeden způsob, jak to udělat, je pomocí následujícího kódu:

Zde nejprve použijeme značku [Fact], takže tato metoda bude identifikována jako test.

  • Poté pomocí několika proměnných stanovíme naše testovací data (řádky 4 a 5) a očekávaný výsledek (řádek 6).
  • Následující věc, kterou musíme udělat, je skutečně zavolat metodu, kterou budeme testovat (v tomto případě metodu Sum v řádku 7).
  • Nakonec musíme zkontrolovat, zda je získaný výsledek stejný jako ten, který jsme očekávali (řádek 8). Jakmile je náš testovací případ implementován, musíme použít funkci „Appert.Equal“, aby aplikace mohla určit výsledek testu.

To vrátí hodnotu na základě podmínky, kterou jsme nastavili jako požadavek na úspěšnost testu. Třída Assert má různé metody, které se vztahují na různé situace.

Můžeme také použít značku [Theory], spolu s [InlineData], pokud chceme testovat metodu s různými vstupy, jak je ukázáno v následujícím kódu.

Chcete-li spustit náš test jednotek, stačí se vydat do hlavní složky pomocí našeho terminálu a zadat příkaz dotnet test. Měla by nám poskytnout výsledek našich testů. Zde provádíme 4 testy. Jeden pro metodu Sum a jeden pro každou z hodnot testovaných v metodě multiplikace.

Zkusit to! Zkuste vytvořit test jedné z metod v OperationsController. Měli bychom být schopni provést instanci přímo ve vaší aplikaci.

Testujte server

Testovací server nám umožňuje otestovat funkčnost různých součástí naší aplikace, které spolupracují. Jsou o něco složitější než testy jednotek, hlavně proto, že vyžadují, abychom pro naši aplikaci nastavili server.

V tomto příkladu budeme testovat novou třídu a řadič: Hrdina. Kód pro tuto novou třídu, její řadič a další soubory, které je třeba změnit, najdete zde.

Jakmile je nastavena, můžeme začít psát testovací kód.

Prvním krokem je přidání balíčku Microsoft.AspNetCore.TestHost NuGet do našeho testovacího konfiguračního souboru. Náš soubor projektu by měl vypadat asi takto:

To nám poskytne potřebné knihovny pro vytvoření testovacího serveru pro naši aplikaci.

Vytvořme novou složku v naší testovací složce a nazveme ji Integrace a nový soubor, který iniciuje samotný server. Následující kód ukazuje jeden způsob, jak toho dosáhnout:

Pro tento test použijeme databázi v paměti, takže musíme změnit způsob nastavení databáze. K tomu je třeba přidat několik řádků v metodě ConfigureServices umístěné v souboru Startup.cs naší aplikace. Nový kód by měl vypadat takto:

S touto sadou budeme moci používat testovací server, jako by to byl běžný server. Server by měl fungovat stejným způsobem jako naše aplikace, ale umožňuje nám provádět naše testy s testovacími daty, abychom se vyhnuli ohrožení informací používaných na našich produkčních serverech. Funkce Assert, které jsme dříve používali, fungují stejně jako při provádění testů jednotek.

Pro tyto testy nejprve vytvoříme několik testovacích údajů, které naše testy použijí. V tomto případě vytvoříme několik 'Heroes' a uložíme je do seznamu, jak ukazuje následující kód:

Tento seznam bude použit v obou našich testech, i když ne stejným způsobem. Pojďme se podívat na první test:

Co tady tedy děláme?

  • Nejprve používáme značku [Theory], což znamená, že stejné testy provedeme několikrát s různými vstupy pro testování. Dále máme značku [MemberData]. To lze použít k načtení dat pro [Teorie] ze statické vlastnosti. Tento atribut má mnoho použití, v tomto případě ho používáme pouze pro informace z vlastnosti Heroes, kterou jsme dříve definovali.
  • Další věc, kterou uděláme, je dát naší metodě název a parametry. Jak jste možná uhodli, vložené parametry odpovídají parametrům třídy Hero, které budeme později instancovat (řádek 7), a přidají se do naší databáze v paměti (řádky 9 a 10).
  • Zbytek je docela jednoduchý. Žádáme naši aplikaci, přičemž jako parametr použijeme číslo Hero ID (řádek 12) a zkontrolujeme, zda je kód stavu odpovědi v pořádku (řádek 14).
  • Dále dostaneme 'Hero' z odpovědi, jako řetězec JSON (řádek 16) a převedeme jej na objekt hrdiny (řádek 18).
  • Nakonec můžeme zkontrolovat, zda vlastnosti vloženého hrdiny (ID a jméno) odpovídají vlastnostem hrdiny odpovědi (řádky 20 a 21).

Tento test bude spuštěn pro každého z hrdinů definovaných ve vlastnosti Heroes.

Pojďme se podívat na následující test:

Zde přistupujeme k našim hrdinům jinak:

  • Jak vidíte, místo značky [MemberData] nejprve používáme značku [Fact]. Je to proto, že tentokrát použijeme vlastnost 'Heroes' jako celek, namísto testování vložení každého hrdiny zvlášť.
  • Pomocí Linq můžeme převést tento seznam objektů [] na seznam hrdinů (řádky 5 až 10) a vložit celou věc do naší databáze (řádky 12 až 13).
  • Dalším krokem je určení očekávané hodnoty odezvy (v tomto případě hrdina s nejkratší výškou, viz řádek 15).
  • Ještě jednou požádáme naši aplikaci (řádek 17), zkontrolujeme kód stavu odpovědi (řádek 19), vyjmeme JSON z odpovědi (řádek 21) a převedeme jej na objekt Hrdina (řádek 23).
  • Konečné srovnání se provádí stejným způsobem a kontroluje se, zda vlastnosti hrdiny, které jsme dostali z odpovědi, jsou stejné jako ty, které očekáváme (řádky 25 a 26).

Nyní můžeme spustit testovací test pomocí dotnetového testu a zobrazit výsledek našich testů. Pokud je vše v pořádku, zobrazí se zpráva „Test Run Successful“. Pokud některý z našich testů selže, dostaneme zprávu „Test Failed“ spolu s informacemi o tom, co se stalo.

A je to!

Můžeme kombinovat testy jednotek a integrace pro náš projekt a nastavit je, jak chceme. Je důležité si uvědomit, že obvykle se doporučuje používat testovací databázi, aby nedošlo k ohrožení informací, které by se v případě poškození / přepisu nemusely obnovit. Zde vytváříme databázi v paměti, ale v případě potřeby můžete nastavit databázi tak, aby fungovala stejně jako běžná, aby nedošlo k ohrožení informací, které by v případě poškození / přepisu nemohly být obnoveny.

Nyní můžete vyvinout automatické testy pro vaše aplikace .NET Core. Dej tomu šanci! Pokud si chcete hrát, můžete vždy vyzkoušet ukázkovou aplikaci.

Zůstaňte naladěni na další příspěvek.

Happy testování!