Übung: Durchführen von Code Coverage Tests
Ebenso wie das Tool für Komponententests hängt das Tool, das Sie für Code Coverage-Tests verwenden, von der Programmiersprache und dem Anwendungsframework ab.
Wenn .NET-Anwendungen unter Linux ausgeführt werden sollen, ist coverlet eine beliebte Wahl. Coverlet ist eine plattformübergreifende Code Coverage-Bibliothek für .NET.
Wie erfolgen Code Coverage-Tests in .NET?
Die Art und Weise Ihrer Code Coverage hängt von der verwendeten Programmiersprache, den verwendeten Frameworks sowie den verfügbaren Code Coverage-Tools ab.
In unserem Tailspin-Szenario finden wir Folgendes:
Visual Studio unter Windows bietet eine Möglichkeit, Code Coverage-Tests auszuführen.
Da wir Builds jedoch unter Linux erstellen, kann coverlet verwendet werden, eine plattformübergreifende Code Coverage-Bibliothek für .NET.
Für das Komponententestprojekt ist das NuGet-Paket coverlet.msbuild erforderlich.
Code Coverage-Ergebnisse werden in eine XML-Datei geschrieben, damit sie von einem anderen Tool verarbeitet werden können. Azure Pipelines unterstützt die Formate Cobertura und JaCoCo für Abdeckungsergebnisse.
Für dieses Modul verwenden wir Cobertura.
Um Cobertura-Abdeckungsergebnisse in ein lesbares Format zu konvertieren, können wir ein Tool namens ReportGenerator verwenden.
ReportGenerator unterstützt eine Reihe von Formaten, einschließlich HTML. Mit den HTML-Formaten können ausführliche Berichte für die einzelnen Klassen in einem .NET-Projekt erstellt werden.
Insbesondere gibt es ein HTML-Format namens HtmlInline_AzurePipelines, das eine visuelle Darstellung ermöglicht, die Azure Pipelines entspricht.
Wie kann ich .NET-Tools verwalten?
Ein .NET-Tool, z. B. ReportGenerator
, ist ein spezielles NuGet-Paket, das eine Konsolenanwendung enthält. Sie können ein .NET-Tool als globales oder lokales Tool verwalten.
Ein globales Tool wird an einem zentralen Speicherort installiert und kann von jedem beliebigen Verzeichnis aus aufgerufen werden. Für alle Verzeichnisse des Computers wird eine Version eines globalen Tools verwendet.
Ein lokales Tool ist ein isoliertes Exemplar eines .NET-Tools, das für ein bestimmtes Verzeichnis gilt. Dadurch können unterschiedliche Verzeichnisse verschiedene Versionen desselben Tools enthalten.
Für die Verwaltung von lokalen Tools für ein bestimmtes Verzeichnis wird eine Manifestdatei verwendet. Diese Datei weist das JSON-Format auf und heißt in der Regel dotnet-tools.json. Mit einer Manifestdatei können Sie die jeweiligen Toolversionen beschreiben, die Sie zum Erstellen oder Ausführen der Anwendung benötigen.
Wenn Sie die Manifestdatei zusammen mit dem Anwendungsquellcode in die Quellcodeverwaltung einfügen, können Entwickler und Buildsysteme den Befehl dotnet tool restore
ausführen, um alle in der Manifestdatei aufgeführten Tools zu installieren. Wenn Sie eine neuere Version eines lokalen Tools benötigen, aktualisieren Sie einfach die Version in der Manifestdatei.
In diesem Modul arbeiten Sie aus Gründen der Isolation mit lokalen Tools. Sie erstellen ein Toolmanifest, das das Tool ReportGenerator
enthält. Außerdem ändern Sie die Buildpipeline, um das Tool ReportGenerator
zu installieren, das Code Coverage-Ergebnisse in ein lesbares Format konvertiert.
Lokale Ausführung von Code Coverage
Bevor Sie einen Pipelinecode schreiben, können Sie versuchen, die einzelnen Schritte manuell durchführen, um den Prozess zu überprüfen.
Öffnen Sie in Visual Studio Code das integrierte Terminal.
Führen Sie den folgenden
dotnet new
-Befehl aus, um eine lokale Toolmanifestdatei zu erstellen.dotnet new tool-manifest
Der Befehl erstellt eine Datei namens .config/dotnet-tools.json.
Führen Sie den folgenden
dotnet tool install
-Befehl aus, um ReportGenerator zu installieren:dotnet tool install dotnet-reportgenerator-globaltool
Dieser Befehl installiert die neueste Version von
ReportGenerator
und fügt einen Eintrag zur Toolmanifestdatei hinzu.Führen Sie den folgenden
dotnet add package
-Befehl aus, um das Paketcoverlet.msbuild
zum Projekt Tailspin.SpaceGame.Web.Tests hinzuzufügen:dotnet add Tailspin.SpaceGame.Web.Tests package coverlet.msbuild
Führen Sie den folgenden
dotnet test
-Befehl aus, um die Komponententests auszuführen und die Code Coverage zu erfassen:Hinweis
Wenn Sie das PowerShell-Terminal in Visual Studio verwenden, ist das Zeilenfortsetzungszeichen ein Backtick (`), daher verwenden Sie dieses Zeichen anstelle des umgekehrten Schrägstrichs (\) für mehrzeilige Befehle.
dotnet test --no-build \ --configuration Release \ /p:CollectCoverage=true \ /p:CoverletOutputFormat=cobertura \ /p:CoverletOutput=./TestResults/Coverage/
Führen Sie den Befehl wie folgt aus, wenn er fehlschlägt:
MSYS2_ARG_CONV_EXCL="*" dotnet test --no-build \ --configuration Release \ /p:CollectCoverage=true \ /p:CoverletOutputFormat=cobertura \ /p:CoverletOutput=./TestResults/Coverage/
Dieser Befehl ähnelt dem Befehl, den Sie zuvor ausgeführt haben. Die
/p:
-Flags teilen Coverlet mit, welches Code Coverage Format verwendet werden soll und wo die Ergebnisse gespeichert werden sollen.Führen Sie den folgenden
dotnet tool run
-Befehl aus, um die Cobertura-DateiReportGenerator
in das HTML-Format zu konvertieren:dotnet tool run reportgenerator \ -- -reports:./Tailspin.SpaceGame.Web.Tests/TestResults/Coverage/coverage.cobertura.xml \ -targetdir:./CodeCoverage \ -reporttypes:HtmlInline_AzurePipelines
Im Ordner CodeCoverage im Stammverzeichnis des Projekts werden viele HTML-Dateien angezeigt.
Erweitern Sie in Visual Studio Code den Ordner CodeCoverage, klicken Sie mit der rechten Maustaste auf index.htm, und wählen Sie dann Im File Explorer anzeigen (In Finder anzeigen unter macOS oder Enthaltenden Ordner öffnen unter Linux) aus.
Doppelklicken Sie in Windows-Explorer (Finder unter macOS) auf index.htm, um die Datei in einem Webbrowser zu öffnen.
Die Zusammenfassung des Coverage-Berichts wird angezeigt.
Scrollen Sie zum unteren Rand der Seite, um eine Abdeckungsaufschlüsselung nach Klassentyp anzuzeigen.
Wählen Sie den Link zu
TailSpin.SpaceGame.Web.LocalDocumentDBRepository<T>
aus, um weitere Details anzuzeigen.Beachten Sie, dass die
GetItemsAsync
-Methode von Komponententests abgedeckt wird, dieCountItemsAsync
-Methode jedoch nicht abgedeckt wird.Dies ergibt einen Sinn, weil die
FetchOnlyRequestedGameRegion
-Testmethode dieGetItemsAsync
-Methode, aber nicht dieCountItemsAsync
-Methode aufruft. (Informationen zum Überprüfen des Testcodes finden Sie in der Datei DocumentDBRepository_GetItemsAsyncShould.cs.)
Erstellen einer Verzweigung
Nachdem Sie nun einen Code Coverage-Bericht lokal erstellen können, können Sie die entsprechenden Aufgaben zu Ihrer Buildpipeline hinzufügen.
In diesem Abschnitt erstellen Sie einen Branch namens code-coverage
, der auf dem unit-tests
-Branch basiert, der Ihre Arbeit aufnehmen soll. In der Praxis wird dieser Branch üblicherweise im main
-Branch erstellt.
Öffnen Sie in Visual Studio Code das integrierte Terminal.
Führen Sie im Terminal den folgenden
git checkout
-Befehl aus, um einen Branch namenscode-coverage
zu erstellen:git checkout -B code-coverage
Hinzufügen von Buildaufgaben
In diesem Abschnitt fügen Sie Aufgaben zu Ihrer Buildpipeline hinzu, um die Code Coverage zu messen.
Ändern Sie in Visual Studio Code azure-pipelines.yml wie folgt:
trigger: - '*' pool: vmImage: 'ubuntu-20.04' demands: - npm variables: buildConfiguration: 'Release' wwwrootDir: 'Tailspin.SpaceGame.Web/wwwroot' dotnetSdkVersion: '6.x' steps: - task: UseDotNet@2 displayName: 'Use .NET SDK $(dotnetSdkVersion)' inputs: version: '$(dotnetSdkVersion)' - task: Npm@1 displayName: 'Run npm install' inputs: verbose: false - script: './node_modules/.bin/node-sass $(wwwrootDir) --output $(wwwrootDir)' displayName: 'Compile Sass assets' - task: gulp@1 displayName: 'Run gulp tasks' - script: 'echo "$(Build.DefinitionName), $(Build.BuildId), $(Build.BuildNumber)" > buildinfo.txt' displayName: 'Write build info' workingDirectory: $(wwwrootDir) - task: DotNetCoreCLI@2 displayName: 'Restore project dependencies' inputs: command: 'restore' projects: '**/*.csproj' - task: DotNetCoreCLI@2 displayName: 'Build the project - $(buildConfiguration)' inputs: command: 'build' arguments: '--no-restore --configuration $(buildConfiguration)' projects: '**/*.csproj' - task: DotNetCoreCLI@2 displayName: 'Install .NET tools from local manifest' inputs: command: custom custom: tool arguments: 'restore' - task: DotNetCoreCLI@2 displayName: 'Run unit tests - $(buildConfiguration)' inputs: command: 'test' arguments: '--no-build --configuration $(buildConfiguration) /p:CollectCoverage=true /p:CoverletOutputFormat=cobertura /p:CoverletOutput=$(Build.SourcesDirectory)/TestResults/Coverage/' publishTestResults: true projects: '**/*.Tests.csproj' - task: DotNetCoreCLI@2 displayName: 'Create code coverage report' inputs: command: custom custom: tool arguments: 'run reportgenerator -reports:$(Build.SourcesDirectory)/**/coverage.cobertura.xml -targetdir:$(Build.SourcesDirectory)/CodeCoverage -reporttypes:HtmlInline_AzurePipelines' - task: PublishCodeCoverageResults@1 displayName: 'Publish code coverage report' inputs: codeCoverageTool: 'cobertura' summaryFileLocation: '$(Build.SourcesDirectory)/**/coverage.cobertura.xml' - task: DotNetCoreCLI@2 displayName: 'Publish the project - $(buildConfiguration)' inputs: command: 'publish' projects: '**/*.csproj' publishWebProjects: false arguments: '--no-build --configuration $(buildConfiguration) --output $(Build.ArtifactStagingDirectory)/$(buildConfiguration)' zipAfterPublish: true - task: PublishBuildArtifacts@1 displayName: 'Publish Artifact: drop' condition: succeeded()
Diese Version baut auf Ihrer vorhandenen Konfiguration auf. Hier sehen Sie eine Zusammenfassung der neuen Aufgaben:
Azure Pipelines-Aufgabe `Display name` BESCHREIBUNG DotNetCoreCLI@2
Installieren von .Net-Tools aus dem lokalen Manifest Installiert die in der Manifestdatei dotnet-tools.js aufgeführten Tools. DotNetCoreCLI@2
Run unit tests - $(buildConfiguration) Führt die Komponententests aus und erfasst die Code Coverage im Cobertura-Format. DotNetCoreCLI@2
Create code coverage report Konvertiert die Cobertura-Ausgabe in HTML. PublishCodeCoverageResults@1
Publish code coverage report Veröffentlicht den Bericht in der Pipeline.
Committen der Änderungen und Pushen des Branchs an GitHub
In diesem Abschnitt pushen Sie Ihre Änderungen an GitHub. Außerdem wird die Pipeline ausgeführt. Denken Sie daran, dass Sie sich derzeit im code-coverage
-Branch befinden.
Obwohl es nicht erforderlich ist, fügen Sie hier die einzelnen Dateien getrennt hinzu und committen diese, um jeder Änderung eine beschreibende Commit-Nachricht zuzuordnen.
Rufen Sie in Visual Studio Code das Terminal auf.
Fügen Sie die Datei Tailspin.SpaceGame.Web.Tests.csproj, die nun einen Verweis auf das
coverlet.msbuild
-Paket enthält, hinzu und committen Sie die Datei:git add Tailspin.SpaceGame.Web.Tests/Tailspin.SpaceGame.Web.Tests.csproj git commit -m "Add coverlet.msbuild package"
Fügen Sie die Toolmanifestdatei dotnet-tools.js hinzu und committen Sie die Datei:
git add .config/dotnet-tools.json git commit -m "Add code coverage"
Fügen Sie die Datei azure-pipelines.yml mit der aktualisierten Buildkonfiguration hinzu und committen Sie die Datei:
git add azure-pipelines.yml git commit -m "Add code coverage"
Pushen Sie den Branch
code-coverage
an GitHub.git push origin code-coverage
Beobachten der Testausführung in Azure Pipelines
Hier wird gezeigt, wie die Tests in der Pipeline ausgeführt und die Ergebnisse dann in Azure Test Plans visualisiert werden.
Verfolgen Sie die einzelnen Schritte des Buildvorgangs in Azure Pipelines.
Kehren Sie zurück zur Zusammenfassungsseite, nachdem der Build erstellt wurde, und wählen Sie die Registerkarte Code Coverage aus.
Es werden die gleichen Ergebnisse angezeigt wie bei der lokalen Testausführung.
Optional können Sie die Ergebnisse in Azure Pipelines untersuchen.
Hinzufügen des Dashboardwidgets
Im vorherigen Abschnitt haben Sie das Widget Test Results Trend zu Ihrem Dashboard hinzugefügt, mit dem andere Benutzer Testergebnistrends schnell überblicken können.
Hier fügen Sie ein zweites Widget hinzu, das die Code Coverage zusammenfasst.
Navigieren Sie im Browser auf einer neuen Registerkarte zu marketplace.visualstudio.com.
Suchen Sie auf der Registerkarte Azure DevOps nach Code Coverage.
Wählen Sie Code Coverage Widgets (veröffentlicht von Shane Davis) aus.
Wählen Sie Kostenlos erhalten aus.
Wählen Sie Ihre Azure DevOps-Organisation in der Dropdownliste aus.
Wählen Sie Installieren aus.
Wechseln Sie zurück zu Azure DevOps.
Navigieren Sie zu Overview>Dashboards.
Wählen Sie Bearbeiten aus.
Suchen Sie nach Code Coverage, und wählen Sie dann Code Coverage aus.
Ziehen Sie Code Coverage in den Canvas.
Wählen Sie das Zahnradsymbol aus, um das Widget zu konfigurieren.
Übernehmen Sie alle Standardeinstellungen mit Ausnahme von:
- Breite: Geben Sie 2 ein.
- Builddefinition: Wählen Sie Ihre Pipeline aus
- Coverage measurement: Wählen Sie Lines aus
Wählen Sie Speichern aus.
Wählen Sie Bearbeitung abgeschlossen aus.
Das Widget zeigt den Prozentsatz des Codes an, der von den Komponententests abgedeckt wird.
Sie haben Code Coverage jetzt in ihrer Pipeline eingerichtet. Obwohl die bestehende Code Coverage gering ist, haben Sie eine Baseline, die Sie im Laufe der Zeit verbessern können.
Später können Sie coverlet so konfigurieren, dass geprüft wird, ob Ihre Tests einen minimalen Schwellenwert für die Abdeckung ergeben. Der Schwellenwert kann abhängig von den jeweiligen Anforderungen eine Abdeckung von 30 Prozent, 50 Prozent oder 80 Prozent sein. Der Build schlägt fehl, wenn Ihre Tests weniger als diesen Wert abdecken.
Entfernen von Code Coverage-Dateien
Bei der früheren Ausführung von Reportgenerator
wurden im Ordner CodeCoverage im Stammverzeichnis des Projekts zahlreiche HTML-Dateien angezeigt.
Diese HTML-Dateien sollen nicht in die Quellcodeverwaltung einbezogen werden, weil Sie sie nicht mehr benötigen. Obwohl die .gitignore-Datei des Projekts bereits so eingerichtet ist, dass Elemente im CodeCoverage-Verzeichnis ignoriert werden, sollten Sie diese Dateien löschen, damit Sie in zukünftigen Modulen nicht zu Ihrem Git-Repository hinzugefügt werden.
Wechseln Sie in Visual Studio Code zum Terminalfenster, und führen Sie dann im Stammverzeichnis des Projekts den folgenden Befehl aus:
rm -rf CodeCoverage/