Utiliser la couverture du code pour les tests unitaires

Important

Cet article explique la création de l’exemple de projet. Si vous avez déjà un projet, vous pouvez passer à la section Outils de couverture du code .

Les tests unitaires permettent de garantir la fonctionnalité et fournissent un moyen de vérification pour les efforts de refactorisation. La couverture du code est une mesure de la quantité de code exécutée par des tests unitaires ( lignes, branches ou méthodes). Par exemple, si vous avez une application simple avec seulement deux branches conditionnelles de code (branche a et branche b), un test unitaire qui vérifie la branche conditionnelle a signale une couverture du code de branche de 50 %.

Cet article décrit l’utilisation de la couverture du code pour les tests unitaires avec Coverlet et la génération de rapports à l’aide de ReportGenerator. Bien que cet article se concentre sur C# et xUnit comme infrastructure de test, MSTest et NUnit fonctionnent également. Coverlet est un projet open source sur GitHub qui fournit une infrastructure de couverture de code multiplateforme pour C#. Coverlet fait partie de la base .NET. Coverlet collecte les données de la série de test de couverture Cobertura, qui sont utilisées pour la génération de rapports.

En outre, cet article explique comment utiliser les informations de couverture du code collectées à partir d’une série de tests Coverlet pour générer un rapport. La génération de rapport est possible à l’aide d’un autre projet open source sur GitHub : ReportGenerator. ReportGenerator convertit les rapports de couverture générés par Cobertura, entre autres, en rapports lisibles par l’homme dans différents formats.

Cet article est basé sur l’exemple de projet de code source, disponible dans le navigateur d’exemples.

Système en cours de test

Le « système en cours de test » fait référence au code sur lequel vous écrivez des tests unitaires, il peut s’agir d’un objet, d’un service ou de tout autre élément qui expose des fonctionnalités testables. Pour cet article, vous allez créer une bibliothèque de classes qui sera le système en cours de test et deux projets de test unitaire correspondants.

Créer une bibliothèque de classes

À partir d’une invite de commandes dans un nouveau répertoire nommé UnitTestingCodeCoverage, créez une bibliothèque de classes .NET standard à l’aide de la dotnet new classlib commande :

dotnet new classlib -n Numbers

L’extrait de code ci-dessous définit une classe simple PrimeService qui fournit des fonctionnalités permettant de vérifier si un nombre est premier. Copiez l’extrait de code ci-dessous et remplacez le contenu du fichier Class1.cs qui a été créé automatiquement dans le répertoire Numbers . Renommez le fichier Class1.csen 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;
        }
    }
}

Conseil

Il convient de mentionner que la Numbers bibliothèque de classes a été ajoutée intentionnellement à l’espace de System noms. Cela permet System.Math d’être accessible sans déclaration d’espace using System; de noms. Pour plus d’informations, consultez espace de noms (référence C#).

Créer des projets de test

Créez deux nouveaux modèles de projet de test xUnit (.NET Core) à partir de la même invite de commandes à l’aide de la dotnet new xunit commande :

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

Les deux projets de test xUnit nouvellement créés doivent ajouter une référence de projet de la bibliothèque de classes Numbers . Cela permet aux projets de test d’avoir accès à PrimeService à des fins de test. À partir de l’invite de commandes, utilisez la dotnet add commande :

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

Le projet MSBuild est nommé de manière appropriée, car il dépend du package NuGet coverlet.msbuild . Ajoutez cette dépendance de package en exécutant la dotnet add package commande :

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

La commande précédente a modifié les répertoires en s’appuyant efficacement sur le projet de test MSBuild , puis a ajouté le package NuGet. Lorsque cela a été fait, il a ensuite changé les répertoires, en faisant monter d’un niveau.

Ouvrez les deux fichiers UnitTest1.cs et remplacez leur contenu par l’extrait de code suivant. Renommez les fichiers UnitTest1.csen 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");
    }
}

Créer une solution

À partir de l’invite de commandes, créez une solution pour encapsuler la bibliothèque de classes et les deux projets de test. À l’aide de la dotnet sln commande :

dotnet new sln -n XUnit.Coverage

Cela crée un nouveau nom XUnit.Coverage de fichier de solution dans le répertoire UnitTestingCodeCoverage . Ajoutez les projets à la racine de la solution.

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

Générez la solution à l’aide de la dotnet build commande :

dotnet build

Si la génération réussit, vous avez créé les trois projets, correctement référencé des projets et des packages, et mis à jour le code source correctement. Bravo !

Outils de couverture du code

Il existe deux types d’outils de couverture du code :

  • DataCollectors : Les DataCollectors surveillent l’exécution des tests et collectent des informations sur les séries de tests. Ils signalent les informations collectées dans différents formats de sortie, tels que XML et JSON. Pour plus d’informations, consultez votre premier DataCollector.
  • Générateurs de rapports : Utilisez les données collectées à partir des séries de tests pour générer des rapports, souvent sous forme de code HTML.

Dans cette section, l’accent est mis sur les outils de collecte de données. Pour utiliser Coverlet pour la couverture du code, un projet de test unitaire existant doit avoir les dépendances de package appropriées ou s’appuyer sur les outils globaux .NET et le package NuGet coverlet.console correspondant.

Intégrer au test .NET

Le modèle de projet de test xUnit s’intègre déjà à coverlet.collector par défaut. À partir de l’invite de commandes, remplacez les répertoires par le projet XUnit.Coverlet.Collector , puis exécutez la dotnet test commande :

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

Notes

L’argument "XPlat Code Coverage" est un nom convivial qui correspond aux collecteurs de données de Coverlet. Ce nom est obligatoire, mais ne respecte pas la casse.

Dans le cadre de l’exécution dotnet test , un fichier coverage.cobertura.xml résultant est généré dans le répertoire TestResults . Le fichier XML contient les résultats. Il s’agit d’une option multiplateforme qui s’appuie sur l’interface CLI .NET, et elle est idéale pour les systèmes de génération où MSBuild n’est pas disponible.

Voici l’exemple coverage.cobertura.xml fichier.

<?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>

Conseil

Vous pouvez également utiliser le package MSBuild si votre système de build utilise déjà MSBuild. À partir de l’invite de commandes, remplacez les répertoires par le projet XUnit.Coverlet.MSBuild et exécutez la dotnet test commande :

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

Le fichier coverage.cobertura.xml résultant est la sortie. Vous pouvez suivre le guide d’intégration MSBuild ici

Génération de rapports

Maintenant que vous pouvez collecter des données à partir d’exécutions de tests unitaires, vous pouvez générer des rapports à l’aide de ReportGenerator. Pour installer le package NuGet ReportGenerator en tant qu’outil global .NET, utilisez la dotnet tool install commande :

dotnet tool install -g dotnet-reportgenerator-globaltool

Exécutez l’outil et fournissez les options souhaitées, compte tenu de la sortie coverage.cobertura.xml fichier de la série de tests précédente.

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

Après avoir exécuté cette commande, un fichier HTML représente le rapport généré.

Rapport généré par les tests unitaires

Voir aussi

Étapes suivantes