Sdílet prostřednictvím


Použití pokrytí kódu pro testování jednotek

Důležité

Tento článek vysvětluje vytvoření ukázkového projektu. Pokud už projekt máte, můžete přeskočit k části Nástroje pokrytí kódu.

Testy jednotek pomáhají zajistit funkčnost a poskytnout způsob ověření pro refaktoring. Pokrytí kódu je měření množství kódu, které se spouští testy jednotek – buď řádky, větve nebo metody. Pokud máte například jednoduchou aplikaci s pouze dvěma podmíněnými větvemi kódu (větev a a větev b), test jednotek, který ověřuje podmíněnou větev a bude hlásit pokrytí kódu větve o 50 %.

Tento článek popisuje použití pokrytí kódu pro testování jednotek pomocí Coverletu a generování sestav pomocí ReportGeneratoru. I když se tento článek zaměřuje na C# a xUnit jako testovací architekturu, msTest i NUnit by také fungovaly. Coverlet je opensourcový projekt na GitHubu , který poskytuje architekturu pokrytí kódu pro různé platformy pro jazyk C#. Coverlet je součástí .NET Foundation. Coverlet shromažďuje data testovacích běhů pokrytí Cobertura, která se používají pro generování sestav.

Kromě toho tento článek podrobně popisuje použití informací o pokrytí kódu shromážděných z testovacího spuštění Coverletu ke generování sestavy. Generování sestav je možné pomocí jiného opensourcového projektu na GitHubu – ReportGenerator. ReportGenerator převádí sestavy pokrytí generované Cobertura mimo jiné na sestavy čitelné člověkem v různých formátech.

Tento článek je založený na projektu ukázkového zdrojového kódu, který je k dispozici v prohlížeči ukázek.

Systém pod testem

"Systém pod testem" odkazuje na kód, proti kterému píšete testy jednotek, může se jednat o objekt, službu nebo cokoli jiného, co zpřístupňuje testovatelné funkce. V tomto článku vytvoříte knihovnu tříd, která bude systémem pod testem, a dva odpovídající projekty testů jednotek.

Vytvoření knihovny tříd

Z příkazového řádku v novém adresáři s názvem UnitTestingCodeCoveragevytvořte novou knihovnu dotnet new classlib tříd .NET Standard pomocí příkazu:

dotnet new classlib -n Numbers

Následující fragment kódu definuje jednoduchou PrimeService třídu, která poskytuje funkce pro kontrolu, jestli je číslo prime. Zkopírujte níže uvedený fragment kódu a nahraďte obsah souboru Class1.cs , který se automaticky vytvořil v adresáři Numbers . Přejmenujte soubor Class1.cs na PrimeService.cs.

namespace System.Numbers
{
    public class PrimeService
    {
        public bool IsPrime(int candidate)
        {
            if (candidate < 2)
            {
                return false;
            }

            for (int divisor = 2; divisor <= Math.Sqrt(candidate); ++divisor)
            {
                if (candidate % divisor == 0)
                {
                    return false;
                }
            }
            return true;
        }
    }
}

Tip

Stojí za zmínku Numbers , že knihovna tříd byla záměrně přidána System do oboru názvů. To umožňuje System.Math přístup bez using System; deklarace oboru názvů. Další informace najdete v tématu obor názvů (referenční dokumentace jazyka C#).

Vytváření testovacích projektů

Pomocí příkazu vytvořte ze stejného příkazového řádku dotnet new xunit dvě nové šablony testovacího projektu xUnit (.NET Core):

dotnet new xunit -n XUnit.Coverlet.Collector
dotnet new xunit -n XUnit.Coverlet.MSBuild

Oba nově vytvořené projekty testů xUnit musí přidat odkaz na projekt knihovny tříd Numbers . To znamená, že testovací projekty mají přístup k PrimeService pro testování. Z příkazového řádku použijte dotnet add příkaz:

dotnet add XUnit.Coverlet.Collector\XUnit.Coverlet.Collector.csproj reference Numbers\Numbers.csproj
dotnet add XUnit.Coverlet.MSBuild\XUnit.Coverlet.MSBuild.csproj reference Numbers\Numbers.csproj

Projekt MSBuild se pojmenuje odpovídajícím způsobem, protože bude záviset na balíčku coverlet.msbuild NuGet. Přidejte tuto závislost balíčku spuštěním dotnet add package příkazu:

cd XUnit.Coverlet.MSBuild && dotnet add package coverlet.msbuild && cd ..

Předchozí příkaz efektivně změnil adresáře rozsahu na projekt testu MSBuild a pak přidal balíček NuGet. Až to bylo hotové, změnilo se adresáře a zkrotilo se o jednu úroveň výš.

Otevřete oba soubory UnitTest1.cs a nahraďte jejich obsah následujícím fragmentem kódu. Přejmenujte soubory UnitTest1.cs na PrimeServiceTests.cs.

using System.Numbers;
using Xunit;

namespace XUnit.Coverlet
{
    public class PrimeServiceTests
    {
        readonly PrimeService _primeService;

        public PrimeServiceTests() => _primeService = new PrimeService();

        [Theory]
        [InlineData(-1), InlineData(0), InlineData(1)]
        public void IsPrime_ValuesLessThan2_ReturnFalse(int value) =>
            Assert.False(_primeService.IsPrime(value), $"{value} should not be prime");

        [Theory]
        [InlineData(2), InlineData(3), InlineData(5), InlineData(7)]
        public void IsPrime_PrimesLessThan10_ReturnTrue(int value) =>
            Assert.True(_primeService.IsPrime(value), $"{value} should be prime");

        [Theory]
        [InlineData(4), InlineData(6), InlineData(8), InlineData(9)]
        public void IsPrime_NonPrimesLessThan10_ReturnFalse(int value) =>
            Assert.False(_primeService.IsPrime(value), $"{value} should not be prime");
    }
}

Vytvoření řešení

Na příkazovém řádku vytvořte nové řešení pro zapouzdření knihovny tříd a dvou testovacích projektů. dotnet sln Pomocí příkazu:

dotnet new sln -n XUnit.Coverage

Tím se v adresáři UnitTestingCodeCoverage vytvoří nový název XUnit.Coverage souboru řešení. Přidejte projekty do kořenového adresáře řešení.

dotnet sln XUnit.Coverage.sln add **/*.csproj --in-root

Sestavte řešení pomocí dotnet build příkazu:

dotnet build

Pokud je sestavení úspěšné, vytvořili jste tři projekty, správně odkazované projekty a balíčky a aktualizovali zdrojový kód správně. Hotovo!

Nástroje pro pokrytí kódu

Existují dva typy nástrojů pro pokrytí kódu:

  • DataCollectors: DataCollectors monitorují spouštění testů a shromažďují informace o testovacích spuštěních. Sestavují shromážděné informace v různých výstupních formátech, jako jsou XML a JSON. Další informace najdete v prvním dataCollectoru.
  • Generátory sestav: Pomocí dat shromážděných z testovacích běhů můžete generovat sestavy, často jako ve stylu HTML.

V této části se zaměřujeme na nástroje kolektoru dat.

.NET obsahuje integrovaný kolektor dat pokrytí kódu, který je k dispozici také v sadě Visual Studio. Tento kolektor dat generuje binární soubor .coverage , který lze použít ke generování sestav v sadě Visual Studio. Binární soubor není čitelný pro člověka a musí být převeden do čitelného formátu, aby bylo možné generovat sestavy mimo Visual Studio.

Tip

Tento dotnet-coverage nástroj je multiplatformní nástroj, který lze použít k převodu souboru výsledků binárního testu pokrytí do čitelného formátu člověka. Další informace najdete v tématu dotnet-coverage.

Coverlet je opensourcová alternativa k integrované kolekci. Generuje výsledky testů jako soubory CObertura XML čitelné člověkem, které lze pak použít ke generování sestav HTML. Pokud chcete použít Coverlet pro pokrytí kódu, musí mít existující projekt testování jednotek odpovídající závislosti balíčku nebo případně spoléhat na globální nástroje .NET a odpovídající balíček NuGet coverlet.console .

Integrace s testem .NET

Šablona projektu testu xUnit se už ve výchozím nastavení integruje s coverlet.collector . Na příkazovém řádku změňte adresáře na projekt XUnit.Coverlet.Collector a spusťte dotnet test příkaz:

cd XUnit.Coverlet.Collector && dotnet test --collect:"XPlat Code Coverage"

Poznámka:

Argument "XPlat Code Coverage" je popisný název, který odpovídá kolektorům dat z Coverletu. Tento název je povinný, ale nerozlišuje velká a malá písmena. Chcete-li použít . Integrovaná kolekce dat Pokrytí kódu NET, použijte "Code Coverage".

V rámci dotnet test spuštění je výsledný soubor coverage.cobertura.xml výstupem do adresáře TestResults . Soubor XML obsahuje výsledky. Jedná se o multiplatformní možnost, která spoléhá na rozhraní příkazového řádku .NET a je skvělá pro systémy sestavení, ve kterých není nástroj MSBuild k dispozici.

Níže je příklad souboru coverage.cobertura.xml .

<?xml version="1.0" encoding="utf-8"?>
<coverage line-rate="1" branch-rate="1" version="1.9" timestamp="1592248008"
          lines-covered="12" lines-valid="12" branches-covered="6" branches-valid="6">
  <sources>
    <source>C:\</source>
  </sources>
  <packages>
    <package name="Numbers" line-rate="1" branch-rate="1" complexity="6">
      <classes>
        <class name="Numbers.PrimeService" line-rate="1" branch-rate="1" complexity="6"
               filename="Numbers\PrimeService.cs">
          <methods>
            <method name="IsPrime" signature="(System.Int32)" line-rate="1"
                    branch-rate="1" complexity="6">
              <lines>
                <line number="8" hits="11" branch="False" />
                <line number="9" hits="11" branch="True" condition-coverage="100% (2/2)">
                  <conditions>
                    <condition number="7" type="jump" coverage="100%" />
                  </conditions>
                </line>
                <line number="10" hits="3" branch="False" />
                <line number="11" hits="3" branch="False" />
                <line number="14" hits="22" branch="True" condition-coverage="100% (2/2)">
                  <conditions>
                    <condition number="57" type="jump" coverage="100%" />
                  </conditions>
                </line>
                <line number="15" hits="7" branch="False" />
                <line number="16" hits="7" branch="True" condition-coverage="100% (2/2)">
                  <conditions>
                    <condition number="27" type="jump" coverage="100%" />
                  </conditions>
                </line>
                <line number="17" hits="4" branch="False" />
                <line number="18" hits="4" branch="False" />
                <line number="20" hits="3" branch="False" />
                <line number="21" hits="4" branch="False" />
                <line number="23" hits="11" branch="False" />
              </lines>
            </method>
          </methods>
          <lines>
            <line number="8" hits="11" branch="False" />
            <line number="9" hits="11" branch="True" condition-coverage="100% (2/2)">
              <conditions>
                <condition number="7" type="jump" coverage="100%" />
              </conditions>
            </line>
            <line number="10" hits="3" branch="False" />
            <line number="11" hits="3" branch="False" />
            <line number="14" hits="22" branch="True" condition-coverage="100% (2/2)">
              <conditions>
                <condition number="57" type="jump" coverage="100%" />
              </conditions>
            </line>
            <line number="15" hits="7" branch="False" />
            <line number="16" hits="7" branch="True" condition-coverage="100% (2/2)">
              <conditions>
                <condition number="27" type="jump" coverage="100%" />
              </conditions>
            </line>
            <line number="17" hits="4" branch="False" />
            <line number="18" hits="4" branch="False" />
            <line number="20" hits="3" branch="False" />
            <line number="21" hits="4" branch="False" />
            <line number="23" hits="11" branch="False" />
          </lines>
        </class>
      </classes>
    </package>
  </packages>
</coverage>

Tip

Jako alternativu můžete použít balíček MSBuild, pokud váš systém sestavení již využívá nástroj MSBuild. Na příkazovém řádku změňte adresáře na projekt XUnit.Coverlet.MSBuild a spusťte dotnet test příkaz:

dotnet test /p:CollectCoverage=true /p:CoverletOutputFormat=cobertura

Výsledný soubor coverage.cobertura.xml je výstup. Tady můžete postupovat podle průvodce integrací nástroje MSBuild.

Generování sestav

Teď, když máte možnost shromažďovat data z běhů testů jednotek, můžete pomocí ReportGeneratoru generovat sestavy. Pokud chcete balíček NuGet ReportGenerator nainstalovat jako globální nástroj .NET, použijte tento dotnet tool install příkaz:

dotnet tool install -g dotnet-reportgenerator-globaltool

Spusťte nástroj a zadejte požadované možnosti s ohledem na výstupní coverage.cobertura.xml soubor z předchozího testovacího spuštění.

reportgenerator
-reports:"Path\To\TestProject\TestResults\{guid}\coverage.cobertura.xml"
-targetdir:"coveragereport"
-reporttypes:Html

Po spuštění tohoto příkazu představuje soubor HTML vygenerovanou sestavu.

Sestava vygenerovaná testem jednotek

Viz také

Další kroky