Návod: Vytváření a spouštění testů jednotek pro spravovaný kód

Tento článek vás provede vytvořením, spuštěním a přizpůsobením řady testů jednotek pomocí architektury Testování jednotek od Microsoftu pro spravovaný kód a Průzkumníka testů sady Visual Studio. Začnete projektem jazyka C#, který je ve vývoji, vytvoříte testy, které prověří jeho kód, spustí testy a prověří výsledky. Pak změníte kód projektu a znovu spustíte testy. Pokud chcete koncepční přehled těchto úloh před provedením těchto kroků, přečtěte si základní informace o testování částí.

Vytvoření projektu k otestování

  1. Otevřete sadu Visual Studio.

  2. V úvodním okně zvolte Vytvořit nový projekt.

  3. Vyhledejte a vyberte šablonu projektu konzolové aplikace C# pro .NET a potom klikněte na Tlačítko Další.

    Poznámka:

    Pokud šablonu konzolové aplikace nevidíte, můžete ji nainstalovat z okna Vytvořit nový projekt. Ve zprávě Nenajděte, co hledáte? Zvolte odkaz Instalovat další nástroje a funkce. Potom v Instalační program pro Visual Studio zvolte úlohu vývoje desktopových aplikací .NET.

  4. Pojmenujte projekt Bank a klepněte na tlačítko Další.

    Zvolte buď doporučenou cílovou architekturu, nebo .NET 8, a pak zvolte Vytvořit.

    Projekt Banky se vytvoří a zobrazí v Průzkumník řešení s otevřeným souborem Program.cs v editoru kódu.

    Poznámka:

    Pokud program.cs není v editoru otevřený, poklikejte na soubor Program.cs v Průzkumník řešení jej otevřete.

  5. Obsah souboru Program.cs nahraďte následujícím kódem jazyka C#, který definuje třídu BankAccount:

    using System;
    
    namespace BankAccountNS
    {
        /// <summary>
        /// Bank account demo class.
        /// </summary>
        public class BankAccount
        {
            private readonly string m_customerName;
            private double m_balance;
    
            private BankAccount() { }
    
            public BankAccount(string customerName, double balance)
            {
                m_customerName = customerName;
                m_balance = balance;
            }
    
            public string CustomerName
            {
                get { return m_customerName; }
            }
    
            public double Balance
            {
                get { return m_balance; }
            }
    
            public void Debit(double amount)
            {
                if (amount > m_balance)
                {
                    throw new ArgumentOutOfRangeException("amount");
                }
    
                if (amount < 0)
                {
                    throw new ArgumentOutOfRangeException("amount");
                }
    
                m_balance += amount; // intentionally incorrect code
            }
    
            public void Credit(double amount)
            {
                if (amount < 0)
                {
                    throw new ArgumentOutOfRangeException("amount");
                }
    
                m_balance += amount;
            }
    
            public static void Main()
            {
                BankAccount ba = new BankAccount("Mr. Bryan Walton", 11.99);
    
                ba.Credit(5.77);
                ba.Debit(11.22);
                Console.WriteLine("Current balance is ${0}", ba.Balance);
            }
        }
    }
    
  6. Přejmenujte soubor na BankAccount.cs tak, že kliknete pravým tlačítkem a zvolíte Přejmenovat v Průzkumník řešení.

  7. V nabídce Sestavení klikněte na Sestavit řešení (nebo stiskněte kombinaci kláves Ctrl + SHIFT + B).

Teď máte projekt s metodami, které můžete testovat. V tomto článku se testy zaměřují na metodu Debit . Metoda Debit se volá, když se peníze stáhnou z účtu.

Vytvoření projektu testů jednotek

  1. V nabídce Soubor vyberte Přidat>nový projekt.

    Tip

    Můžete také kliknout pravým tlačítkem na řešení v Průzkumník řešení a zvolit Přidat>nový projekt.

  2. Do vyhledávacího pole zadejte test, vyberte jazyk C# a pak vyberte projekt testů jednotek JAZYKA C# MSTest pro šablonu .NET a potom klikněte na tlačítko Další.

    Poznámka:

    V sadě Visual Studio 2019 verze 16.9 je šablona projektu MSTest projekt unit test.

  3. Pojmenujte projekt BankTests a klepněte na tlačítko Další.

  4. Zvolte buď doporučenou cílovou architekturu, nebo .NET 8, a pak zvolte Vytvořit.

    Projekt BankTests se přidá do řešení banky .

  5. V projektu BankTests přidejte odkaz na projekt Bank.

    V Průzkumník řešení vyberte Závislosti v projektu BankTests a v nabídce pravým tlačítkem myši zvolte Přidat odkaz (nebo Přidat odkaz na projekt).

  6. V dialogovém okně Správce odkazů rozbalte položku Projekty, vyberte Řešení a pak zaškrtněte položku Banka .

  7. Vyberte OK.

Vytvoření testovací třídy

Vytvořte testovací třídu pro ověření BankAccount třídy. Můžete použít soubor UnitTest1.cs vygenerovaný šablonou projektu, ale dát souboru a třídě popisnější názvy.

Přejmenování souboru a třídy

  1. Pokud chcete soubor přejmenovat, vyberte v Průzkumník řešení soubor UnitTest1.cs v projektu BankTests. V nabídce, která se zobrazí po kliknutí pravým tlačítkem myši, zvolte Přejmenovat (nebo stiskněte klávesu F2) a pak soubor přejmenujte na BankAccountTests.cs.

  2. Pokud chcete třídu přejmenovat, umístěte kurzor do UnitTest1 editoru kódu, klikněte pravým tlačítkem myši a zvolte Přejmenovat (nebo stiskněte klávesu F2). Zadejte BankAccountTests a stiskněte Enter.

Soubor BankAccountTests.cs teď obsahuje následující kód:

// The 'using' statement for Test Tools is in GlobalUsings.cs
// using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace BankTests
{
    [TestClass]
    public class BankAccountTests
    {
        [TestMethod]
        public void TestMethod1()
        {
        }
    }
}

Přidání příkazu using

Přidejte do testovací třídy příkaz, using který bude moci volat do projektu v rámci testu bez použití plně kvalifikovaných názvů. V horní části souboru třídy přidejte:

using BankAccountNS;

Požadavky na testovací třídu

Minimální požadavky pro testovací třídu jsou:

  • Atribut [TestClass] je vyžadován u jakékoli třídy, která obsahuje metody testování jednotek, které chcete spustit v Průzkumníku testů.

  • Každá testovací metoda, kterou má Průzkumník testů rozpoznat, musí mít [TestMethod] atribut.

V projektu testování jednotek můžete mít další třídy, které nemají [TestClass] atribut, a můžete mít další metody v testovacích třídách, které nemají [TestMethod] atribut. Tyto další třídy a metody můžete volat z testovacích metod.

Vytvoření první testovací metody

V tomto postupu napíšete metody testování jednotek k ověření chování Debit metody BankAccount třídy.

Je potřeba zkontrolovat aspoň tři chování:

  • Metoda vyvolá ArgumentOutOfRangeException , pokud je částka inkasa větší než zůstatek.

  • Metoda vyvolá ArgumentOutOfRangeException , pokud je inkasní částka menší než nula.

  • Pokud je částka inkasa platná, metoda odečte debetní částku od zůstatku účtu.

Tip

Výchozí metodu TestMethod1 můžete odstranit, protože ji v tomto návodu nebudete používat.

Vytvoření testovací metody

První test ověří, že platná částka (tj. částka, která je menší než zůstatek účtu a větší než nula), stáhne správnou částku z účtu. Do této BankAccountTests třídy přidejte následující metodu:

[TestMethod]
public void Debit_WithValidAmount_UpdatesBalance()
{
    // Arrange
    double beginningBalance = 11.99;
    double debitAmount = 4.55;
    double expected = 7.44;
    BankAccount account = new BankAccount("Mr. Bryan Walton", beginningBalance);

    // Act
    account.Debit(debitAmount);

    // Assert
    double actual = account.Balance;
    Assert.AreEqual(expected, actual, 0.001, "Account not debited correctly");
}

Metoda je jednoduchá: nastaví nový BankAccount objekt s počátečním zůstatkem a pak stáhne platnou částku. Používá metodu Assert.AreEqual k ověření, že koncový zůstatek je očekávaný. Metody, jako Assert.AreEqualje , Assert.IsTruea další se často používají při testování jednotek. Další koncepční informace o zápisu testu jednotek najdete v tématu Psaní testů.

Požadavky na testovací metodu

Testovací metoda musí splňovat následující požadavky:

  • Je zdoben atributem [TestMethod] .

  • voidVrátí .

  • Nemůže mít parametry.

Sestavení a spuštění testu

  1. V nabídce Sestavení zvolte Sestavit řešení (nebo stiskněte kombinaci kláves Ctrl + SHIFT + B).

  2. Pokud Průzkumník testů není otevřený, otevřete ho tak, že v horním řádku nabídek vyberete Průzkumník testů testů>(nebo Průzkumník testů windows>>) (nebo stisknete Ctrl + E, T).

  3. Zvolte Spustit vše a spusťte test (nebo stiskněte Ctrl + R, V).

    Během spuštění testu je stavový řádek v horní části okna Průzkumníka testů animovaný. Na konci testovacího spuštění se pruh změní na zelenou, pokud všechny testovací metody projdou, nebo červeně, pokud některý z testů selže.

    V tomto případě test selže.

  4. Výběrem metody v Průzkumníku testů zobrazíte podrobnosti v dolní části okna.

Oprava kódu a opětovné spuštění testů

Výsledek testu obsahuje zprávu, která popisuje selhání. Možná budete muset přejít k podrobnostem, abyste tuto zprávu viděli. AreEqual U metody zobrazí zpráva, co bylo očekáváno a co bylo skutečně přijato. Očekávali jste snížení zůstatku, ale místo toho se zvýšilo o částku výběru.

Test jednotek odhalil chybu: částka výběru se přidá do zůstatku účtu, když by se mělo odečíst.

Oprava chyby

Pokud chcete chybu opravit, nahraďte řádek v souboru BankAccount.cs :

m_balance += amount;

textem:

m_balance -= amount;

Opětovné spuštění testu

V Průzkumníku testů zvolte Spustit vše a spusťte test znovu (nebo stiskněte Ctrl + R, V). Červený/zelený pruh se změní na zelenou, aby značil, že test prošel.

Test Explorer in Visual Studio 2019 showing passed test

Test Explorer in Visual Studio 2019 showing passed test

Použití testů jednotek ke zlepšení kódu

Tato část popisuje, jak iterativní proces analýzy, vývoje testů jednotek a refaktoring vám může pomoct zajistit robustnější a efektivnější produkční kód.

Analýza problémů

Vytvořili jste testovací metodu, abyste potvrdili, že se v Debit metodě správně odečítá platná částka. Teď ověřte, že metoda vyvolá ArgumentOutOfRangeException jednu z následujících možností:

  • větší než zůstatek, nebo
  • menší než nula.

Vytvoření a spuštění nových testovacích metod

Vytvořte testovací metodu pro ověření správného chování, pokud je částka inkasa menší než nula:

[TestMethod]
public void Debit_WhenAmountIsLessThanZero_ShouldThrowArgumentOutOfRange()
{
    // Arrange
    double beginningBalance = 11.99;
    double debitAmount = -100.00;
    BankAccount account = new BankAccount("Mr. Bryan Walton", beginningBalance);

    // Act and assert
    Assert.ThrowsException<System.ArgumentOutOfRangeException>(() => account.Debit(debitAmount));
}

Použijte metodu ThrowsException k tvrzení, že byla vyvolána správná výjimka. Tato metoda způsobí selhání testu, pokud ArgumentOutOfRangeException není vyvolán. Pokud dočasně upravíte metodu v rámci testu tak, aby v ApplicationException případě, že je částka inkasa menší než nula, test se chová správně – to znamená, že selže.

Chcete-li otestovat případ, kdy je částka stažena větší než zůstatek, proveďte následující kroky:

  1. Vytvořte novou testovací metodu s názvem Debit_WhenAmountIsMoreThanBalance_ShouldThrowArgumentOutOfRange.

  2. Zkopírujte tělo metody z Debit_WhenAmountIsLessThanZero_ShouldThrowArgumentOutOfRange nové metody.

  3. debitAmount Nastavte hodnotu na číslo větší než zůstatek.

Spusťte dva testy a ověřte, že projdou.

Pokračovat v analýze

Testovanou metodu je možné dále vylepšit. S aktuální implementací nemáme žádný způsob, jak zjistit, která podmínka (amount > m_balance nebo amount < 0) vedla k výjimce vyvolané během testu. Jen víme, že byl ArgumentOutOfRangeException někde v metodě vyvolán. Bylo by lepší zjistit, která podmínka způsobila BankAccount.Debit vyvolání výjimky (amount > m_balance nebo amount < 0), abychom si mohli být jistí, že naše metoda správně kontroluje jeho argumenty.

Znovu se podívejte na testovanou metodu (BankAccount.Debit) a všimněte si, že oba podmíněné příkazy používají ArgumentOutOfRangeException konstruktor, který jako parametr jen přebírá název argumentu:

throw new ArgumentOutOfRangeException("amount");

K dispozici je konstruktor, který sestavuje mnohem bohatší informace: ArgumentOutOfRangeException(String, Object, String) zahrnuje název argumentu, hodnotu argumentu a uživatelem definovanou zprávu. Metodu v rámci testu můžete refaktorovat tak, aby používala tento konstruktor. Ještě lepší je určit chyby pomocí veřejně dostupných členů typu.

Refaktoring kódu pod testem

Nejprve definujte dvě konstanty pro chybové zprávy v oboru třídy. Umístěte definice do třídy pod test, BankAccount:

public const string DebitAmountExceedsBalanceMessage = "Debit amount exceeds balance";
public const string DebitAmountLessThanZeroMessage = "Debit amount is less than zero";

Potom v metodě upravte dva podmíněné příkazy Debit :

if (amount > m_balance)
{
    throw new System.ArgumentOutOfRangeException("amount", amount, DebitAmountExceedsBalanceMessage);
}

if (amount < 0)
{
    throw new System.ArgumentOutOfRangeException("amount", amount, DebitAmountLessThanZeroMessage);
}

Refaktoring testovacích metod

Refaktoring testovacích metod odebráním volání Assert.ThrowsException. Zabalte volání Debit() do bloku, zachyťte konkrétní očekávanou try/catch výjimku a ověřte její přidruženou zprávu. Metoda Microsoft.VisualStudio.TestTools.UnitTesting.StringAssert.Contains poskytuje možnost porovnat dva řetězce.

Debit_WhenAmountIsMoreThanBalance_ShouldThrowArgumentOutOfRange Teď může vypadat takto:

[TestMethod]
public void Debit_WhenAmountIsMoreThanBalance_ShouldThrowArgumentOutOfRange()
{
    // Arrange
    double beginningBalance = 11.99;
    double debitAmount = 20.0;
    BankAccount account = new BankAccount("Mr. Bryan Walton", beginningBalance);

    // Act
    try
    {
        account.Debit(debitAmount);
    }
    catch (System.ArgumentOutOfRangeException e)
    {
        // Assert
        StringAssert.Contains(e.Message, BankAccount.DebitAmountExceedsBalanceMessage);
    }
}

Opětovné otestování, přepsání a opětovné analyze

V současné době testovací metoda nezpracuje všechny případy, které by měla. Pokud je metoda pod testem Debit , metoda se nepovedla ArgumentOutOfRangeException vyvolat, když debitAmount byla větší než zůstatek (nebo menší než nula), testovací metoda by prošla. Tento scénář není dobrý, protože chcete, aby testovací metoda selhala, pokud není vyvolán žádná výjimka.

Tento výsledek je chyba v testovací metodě. Chcete-li tento problém vyřešit, přidejte Assert.Fail na konec testovací metody assert pro zpracování případu, kdy není vyvolán žádná výjimka.

Opětovné spuštění testu ukazuje, že test nyní selže , pokud je zachycena správná výjimka. Blok catch zachytí výjimku, ale metoda pokračuje ve spuštění a při novém Assert.Fail kontrolním příkazu selže. Chcete-li tento problém vyřešit, přidejte return příkaz za StringAssert blok catch . Opětovné spuštění testu potvrdí, že jste tento problém vyřešili. Konečná verze vypadá Debit_WhenAmountIsMoreThanBalance_ShouldThrowArgumentOutOfRange takto:

[TestMethod]
public void Debit_WhenAmountIsMoreThanBalance_ShouldThrowArgumentOutOfRange()
{
    // Arrange
    double beginningBalance = 11.99;
    double debitAmount = 20.0;
    BankAccount account = new BankAccount("Mr. Bryan Walton", beginningBalance);

    // Act
    try
    {
        account.Debit(debitAmount);
    }
    catch (System.ArgumentOutOfRangeException e)
    {
        // Assert
        StringAssert.Contains(e.Message, BankAccount.DebitAmountExceedsBalanceMessage);
        return;
    }

    Assert.Fail("The expected exception was not thrown.");
}

Závěr

Vylepšení testovacího kódu vedla k robustnějším a informativním testovacím metodám. Ale důležitější je, že také vylepšili kód, který se testuje.

Tip

Tento názorný postup používá rozhraní Microsoft Unit Test Framework pro spravovaný kód. Průzkumník testů může také spouštět testy z architektur testů jednotek třetích stran, které mají adaptéry pro Průzkumníka testů. Další informace naleznete v tématu Instalace rozhraní pro testování jednotek třetích stran.

Informace o spouštění testů z příkazového řádku naleznete v tématu VSTest.Console.exe možnosti příkazového řádku.