From 3ae87de72e4b5a2a2c7b43bed7d570cd075671c7 Mon Sep 17 00:00:00 2001 From: David Pine Date: Mon, 15 Jun 2020 08:50:51 -0500 Subject: [PATCH 01/17] Initial bits of new article --- .../testing/unit-testing-best-practices.md | 6 ++++ .../testing/unit-testing-code-coverage.md | 29 +++++++++++++++++++ docs/core/toc.yml | 2 ++ 3 files changed, 37 insertions(+) create mode 100644 docs/core/testing/unit-testing-code-coverage.md diff --git a/docs/core/testing/unit-testing-best-practices.md b/docs/core/testing/unit-testing-best-practices.md index 0aecbfc774646..d0bd7660a4bd3 100644 --- a/docs/core/testing/unit-testing-best-practices.md +++ b/docs/core/testing/unit-testing-best-practices.md @@ -44,6 +44,12 @@ Writing tests for your code will naturally decouple your code, because it would - **Self-Checking**. The test should be able to automatically detect if it passed or failed without any human interaction. - **Timely**. A unit test should not take a disproportionately long time to write compared to the code being tested. If you find testing the code taking a large amount of time compared to writing the code, consider a design that is more testable. +## Code coverage + +A high code coverage percentage is often associated with a higher quality of code, however; the measurement itself *cannot* determine the quality of code. Setting an ambiguous code coverage percentage goal is counterintuitive. Imagine a complex project with thousands of conditional branches, and imagine that it requires 95% code coverage. Currently the project maintains 90% code coverage. The amount of time it takes to account for all of the edge cases in the remaining 5% could be a massive undertaking and the value proposition quickly diminishes. + +Using code coverage for what it truly represents is always best. It is not an indicator of success, nor does it imply a high code quality - instead it is simply the amount of code that is covered by unit tests. For more information, see [unit testing code coverage](unsit-testing-code-coverage.md). + ## Let's speak the same language The term *mock* is unfortunately very misused when talking about testing. The following defines the most common types of *fakes* when writing unit tests: diff --git a/docs/core/testing/unit-testing-code-coverage.md b/docs/core/testing/unit-testing-code-coverage.md new file mode 100644 index 0000000000000..f98f8118cd60f --- /dev/null +++ b/docs/core/testing/unit-testing-code-coverage.md @@ -0,0 +1,29 @@ +--- +title: Use code coverage for unit testing +description: Learn how to use the code coverage capabilities for .NET unit tests. +author: IEvangelist +ms.author: dapine +ms.date: 06/15/2020 +--- + +# Use code coverage for unit testing + +Unit tests help to ensure functionality, and provide a means of verification for refactoring efforts. Code coverage is a measurement of the amount of code that is ran as part of a unit test run - either lines, branches, or methods. As an example, if you have a simple application with only two conditional branches of code (_branch a_, and _branch b_), a unit test that verifies conditional _branch a_ will report branch code coverage of 50%. + +This article discusses using code coverage for unit testing with coverlet. + +> Coverlet is a cross platform code coverage framework for .NET, with support for line, branch, and method coverage. - [coverlet repo](https://github.com/coverlet-coverage/coverlet) + +Additionally, [coverlet](https://dotnetfoundation.org/projects/coverlet) is part of the [.NET foundation](https://dotnetfoundation.org). + +## Tooling + +To use coverlet for code coverage, an existing unit test project must have the appropriate package dependencies. From the .NET Core CLI at the directory level of the *.csproj* file, run the following command: + +```dotnetcli +dotnet add package coverlet.collector +``` + +The [coverlet.collector](https://www.nuget.org/packages/coverlet.collector) NuGet package is added to the project. + +## \ No newline at end of file diff --git a/docs/core/toc.yml b/docs/core/toc.yml index 1020fcb55f687..28d8d6722d2c6 100644 --- a/docs/core/toc.yml +++ b/docs/core/toc.yml @@ -431,6 +431,8 @@ items: href: testing/selective-unit-tests.md - name: Order unit tests href: testing/order-unit-tests.md + - name: Code coverage + href: testing/unit-testing-code-coverage.md - name: Unit test published output href: testing/unit-testing-published-output.md - name: Live unit test .NET Core projects with Visual Studio From 44ec2b6dc2c3600b1147d2ef8266aa80e6074dac Mon Sep 17 00:00:00 2001 From: David Pine Date: Mon, 15 Jun 2020 08:57:48 -0500 Subject: [PATCH 02/17] Fix linting issue --- docs/core/testing/unit-testing-code-coverage.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/docs/core/testing/unit-testing-code-coverage.md b/docs/core/testing/unit-testing-code-coverage.md index f98f8118cd60f..870d7a029bea5 100644 --- a/docs/core/testing/unit-testing-code-coverage.md +++ b/docs/core/testing/unit-testing-code-coverage.md @@ -25,5 +25,3 @@ dotnet add package coverlet.collector ``` The [coverlet.collector](https://www.nuget.org/packages/coverlet.collector) NuGet package is added to the project. - -## \ No newline at end of file From f630e323cb0a4abf374b8c23b7f493ddf8cd316f Mon Sep 17 00:00:00 2001 From: David Pine Date: Mon, 15 Jun 2020 09:14:05 -0500 Subject: [PATCH 03/17] Correct link --- docs/core/testing/unit-testing-best-practices.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/core/testing/unit-testing-best-practices.md b/docs/core/testing/unit-testing-best-practices.md index d0bd7660a4bd3..17cc43ef91e9c 100644 --- a/docs/core/testing/unit-testing-best-practices.md +++ b/docs/core/testing/unit-testing-best-practices.md @@ -48,7 +48,7 @@ Writing tests for your code will naturally decouple your code, because it would A high code coverage percentage is often associated with a higher quality of code, however; the measurement itself *cannot* determine the quality of code. Setting an ambiguous code coverage percentage goal is counterintuitive. Imagine a complex project with thousands of conditional branches, and imagine that it requires 95% code coverage. Currently the project maintains 90% code coverage. The amount of time it takes to account for all of the edge cases in the remaining 5% could be a massive undertaking and the value proposition quickly diminishes. -Using code coverage for what it truly represents is always best. It is not an indicator of success, nor does it imply a high code quality - instead it is simply the amount of code that is covered by unit tests. For more information, see [unit testing code coverage](unsit-testing-code-coverage.md). +Using code coverage for what it truly represents is always best. It is not an indicator of success, nor does it imply a high code quality - instead it is simply the amount of code that is covered by unit tests. For more information, see [unit testing code coverage](unit-testing-code-coverage.md). ## Let's speak the same language The term *mock* is unfortunately very misused when talking about testing. The following defines the most common types of *fakes* when writing unit tests: From 12ffc5907132281f0b06582122867f0e64c85f13 Mon Sep 17 00:00:00 2001 From: David Pine Date: Mon, 15 Jun 2020 10:19:07 -0500 Subject: [PATCH 04/17] Updates --- .../testing/unit-testing-code-coverage.md | 54 ++++++++++++++++++- 1 file changed, 52 insertions(+), 2 deletions(-) diff --git a/docs/core/testing/unit-testing-code-coverage.md b/docs/core/testing/unit-testing-code-coverage.md index 870d7a029bea5..1e840e481fe2a 100644 --- a/docs/core/testing/unit-testing-code-coverage.md +++ b/docs/core/testing/unit-testing-code-coverage.md @@ -18,10 +18,60 @@ Additionally, [coverlet](https://dotnetfoundation.org/projects/coverlet) is part ## Tooling -To use coverlet for code coverage, an existing unit test project must have the appropriate package dependencies. From the .NET Core CLI at the directory level of the *.csproj* file, run the following command: +To use coverlet for code coverage, an existing unit test project must have the appropriate package dependencies, or alternatively rely on [.NET global tooling](../tools/global-tools.md). + +### Integrate with .NET test + +To integrate with [`dotnet test`](../tools/dotnet-test.md) (formally known as VSTest), add the appropriate package dependency. From the directory of the *.csproj* file, run the following [`dotnet add package`](../tools/dotnet-add-package.md) command: ```dotnetcli dotnet add package coverlet.collector ``` -The [coverlet.collector](https://www.nuget.org/packages/coverlet.collector) NuGet package is added to the project. +The [coverlet.collector](https://www.nuget.org/packages/coverlet.collector) NuGet package is added to the project. Next, run the following command: + +```dotnetcli +dotnet test --collect:"XPlat Code Coverage" +``` + +> [!IMPORTANT] +> The `"XPlat Code Coverage"` argument is a friendly name that corresponds to the data collectors from coverlet. This name is required, but is case insensitive. + +As part of the `dotnet test` run, a resulting *TestResults/{test-run-guid}/coverage.cobertura.xml* file is output. The XML file contains the results. + +#### MSBuild + +As an alternative, you could use the MSBuild package. From the .NET Core CLI at the directory level of the *.csproj* file, run the following [`dotnet add package`](../tools/dotnet-add-package.md) command: + +```dotnetcli +dotnet add package coverlet.msbuild +``` + +The [coverlet.msbuild](https://www.nuget.org/packages/coverlet.msbuild) NuGet package is added to the project. Next, run the following command: + +```dotnetcli +dotnet test /p:CollectCoverage=true +``` + +> [!NOTE] +> There is a subtle differences in the output between the two `dotnet test` commands. The first output was an XML file, whereas the last is a JSON file. + +### Use with .NET global tooling + +To use coverlet globally, it can be installed as a [.NET global tool](../tools/global-tools.md). Run the following [`dotnet tool install`](../tools/dotnet-tool-install.md) command: + +```dotnetcli +dotnet tool install --global coverlet.console +``` + +The [coverlet.console](https://www.nuget.org/packages/coverlet.console) NuGet package is added to the environment globally. Now, `coverlet` can be used. + +```console +coverlet C:\Source\Directory\bin\Debug\netcoreapp3.1\Test.dll --target "dotnet" --targetargs "test . --no-build" +``` + +## See also + +- [Visual Studio unit test cover coverage](/visualstudio/test/using-code-coverage-to-determine-how-much-code-is-being-tested) +- [GitHub - Coverlet repository](https://github.com/coverlet-coverage/coverlet) +- [.NET Core CLI test command](../tools/dotnet-test.md) From af1999d69a330b3790682bbadf1885595f346056 Mon Sep 17 00:00:00 2001 From: David Pine Date: Mon, 15 Jun 2020 10:34:32 -0500 Subject: [PATCH 05/17] Final updates --- docs/core/testing/order-unit-tests.md | 2 +- docs/core/testing/unit-testing-code-coverage.md | 13 +++++++------ docs/core/toc.yml | 2 +- 3 files changed, 9 insertions(+), 8 deletions(-) diff --git a/docs/core/testing/order-unit-tests.md b/docs/core/testing/order-unit-tests.md index 8db2acf967e07..130bfb014a2b0 100644 --- a/docs/core/testing/order-unit-tests.md +++ b/docs/core/testing/order-unit-tests.md @@ -79,4 +79,4 @@ To order tests explicitly, NUnit provides an [`OrderAttribute`](https://github.c ## Next Steps > [!div class="nextstepaction"] -> [Unit testing best practices](unit-testing-best-practices.md) +> [Unit test code coverage](unit-testing-code-coverage.md) diff --git a/docs/core/testing/unit-testing-code-coverage.md b/docs/core/testing/unit-testing-code-coverage.md index 1e840e481fe2a..6e2b7d41325be 100644 --- a/docs/core/testing/unit-testing-code-coverage.md +++ b/docs/core/testing/unit-testing-code-coverage.md @@ -10,11 +10,7 @@ ms.date: 06/15/2020 Unit tests help to ensure functionality, and provide a means of verification for refactoring efforts. Code coverage is a measurement of the amount of code that is ran as part of a unit test run - either lines, branches, or methods. As an example, if you have a simple application with only two conditional branches of code (_branch a_, and _branch b_), a unit test that verifies conditional _branch a_ will report branch code coverage of 50%. -This article discusses using code coverage for unit testing with coverlet. - -> Coverlet is a cross platform code coverage framework for .NET, with support for line, branch, and method coverage. - [coverlet repo](https://github.com/coverlet-coverage/coverlet) - -Additionally, [coverlet](https://dotnetfoundation.org/projects/coverlet) is part of the [.NET foundation](https://dotnetfoundation.org). +This article discusses the usage of code coverage for unit testing with coverlet, and it is [open source project on GitHub](https://github.com/coverlet-coverage/coverlet). Coverlet is a cross platform code coverage framework for .NET. Additionally, [coverlet](https://dotnetfoundation.org/projects/coverlet) is part of the .NET foundation. ## Tooling @@ -22,7 +18,7 @@ To use coverlet for code coverage, an existing unit test project must have the a ### Integrate with .NET test -To integrate with [`dotnet test`](../tools/dotnet-test.md) (formally known as VSTest), add the appropriate package dependency. From the directory of the *.csproj* file, run the following [`dotnet add package`](../tools/dotnet-add-package.md) command: +To integrate with [`dotnet test`](../tools/dotnet-test.md), add the appropriate package dependency. From the directory of the *.csproj* file, run the following [`dotnet add package`](../tools/dotnet-add-package.md) command: ```dotnetcli dotnet add package coverlet.collector @@ -75,3 +71,8 @@ coverlet C:\Source\Directory\bin\Debug\netcoreapp3.1\Test.dll --target "dotnet" - [Visual Studio unit test cover coverage](/visualstudio/test/using-code-coverage-to-determine-how-much-code-is-being-tested) - [GitHub - Coverlet repository](https://github.com/coverlet-coverage/coverlet) - [.NET Core CLI test command](../tools/dotnet-test.md) + +## Next Steps + +> [!div class="nextstepaction"] +> [Unit testing best practices](unit-testing-best-practices.md) \ No newline at end of file diff --git a/docs/core/toc.yml b/docs/core/toc.yml index 28d8d6722d2c6..d6e4842bb6df1 100644 --- a/docs/core/toc.yml +++ b/docs/core/toc.yml @@ -431,7 +431,7 @@ items: href: testing/selective-unit-tests.md - name: Order unit tests href: testing/order-unit-tests.md - - name: Code coverage + - name: Unit test code coverage href: testing/unit-testing-code-coverage.md - name: Unit test published output href: testing/unit-testing-published-output.md From a4325990967781e6d144289af14f286dd812695d Mon Sep 17 00:00:00 2001 From: David Pine Date: Mon, 15 Jun 2020 11:01:19 -0500 Subject: [PATCH 06/17] Fix md error --- docs/core/testing/unit-testing-code-coverage.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/core/testing/unit-testing-code-coverage.md b/docs/core/testing/unit-testing-code-coverage.md index 6e2b7d41325be..bc1fac31db2b9 100644 --- a/docs/core/testing/unit-testing-code-coverage.md +++ b/docs/core/testing/unit-testing-code-coverage.md @@ -75,4 +75,4 @@ coverlet C:\Source\Directory\bin\Debug\netcoreapp3.1\Test.dll --target "dotnet" ## Next Steps > [!div class="nextstepaction"] -> [Unit testing best practices](unit-testing-best-practices.md) \ No newline at end of file +> [Unit testing best practices](unit-testing-best-practices.md) From e7e9a796a363ec3c77cafe32d0678f2d92ce8fa2 Mon Sep 17 00:00:00 2001 From: David Pine Date: Mon, 15 Jun 2020 11:48:03 -0500 Subject: [PATCH 07/17] Apply suggestions from code review Co-authored-by: Tom Dykstra --- docs/core/testing/unit-testing-best-practices.md | 4 ++-- docs/core/testing/unit-testing-code-coverage.md | 10 +++++----- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/docs/core/testing/unit-testing-best-practices.md b/docs/core/testing/unit-testing-best-practices.md index 17cc43ef91e9c..69060a6166d75 100644 --- a/docs/core/testing/unit-testing-best-practices.md +++ b/docs/core/testing/unit-testing-best-practices.md @@ -46,9 +46,9 @@ Writing tests for your code will naturally decouple your code, because it would ## Code coverage -A high code coverage percentage is often associated with a higher quality of code, however; the measurement itself *cannot* determine the quality of code. Setting an ambiguous code coverage percentage goal is counterintuitive. Imagine a complex project with thousands of conditional branches, and imagine that it requires 95% code coverage. Currently the project maintains 90% code coverage. The amount of time it takes to account for all of the edge cases in the remaining 5% could be a massive undertaking and the value proposition quickly diminishes. +A high code coverage percentage is often associated with a higher quality of code. However, the measurement itself *cannot* determine the quality of code. Setting an overly ambitious code coverage percentage goal can be counterproductive. Imagine a complex project with thousands of conditional branches, and imagine that you set a goal of 95% code coverage. Currently the project maintains 90% code coverage. The amount of time it takes to account for all of the edge cases in the remaining 5% could be a massive undertaking, and the value proposition quickly diminishes. -Using code coverage for what it truly represents is always best. It is not an indicator of success, nor does it imply a high code quality - instead it is simply the amount of code that is covered by unit tests. For more information, see [unit testing code coverage](unit-testing-code-coverage.md). +A high code coverage percentage is not an indicator of success, nor does it imply high code quality. It jusst represents the amount of code that is covered by unit tests. For more information, see [unit testing code coverage](unit-testing-code-coverage.md). ## Let's speak the same language The term *mock* is unfortunately very misused when talking about testing. The following defines the most common types of *fakes* when writing unit tests: diff --git a/docs/core/testing/unit-testing-code-coverage.md b/docs/core/testing/unit-testing-code-coverage.md index bc1fac31db2b9..872094f86f553 100644 --- a/docs/core/testing/unit-testing-code-coverage.md +++ b/docs/core/testing/unit-testing-code-coverage.md @@ -8,9 +8,9 @@ ms.date: 06/15/2020 # Use code coverage for unit testing -Unit tests help to ensure functionality, and provide a means of verification for refactoring efforts. Code coverage is a measurement of the amount of code that is ran as part of a unit test run - either lines, branches, or methods. As an example, if you have a simple application with only two conditional branches of code (_branch a_, and _branch b_), a unit test that verifies conditional _branch a_ will report branch code coverage of 50%. +Unit tests help to ensure functionality, and provide a means of verification for refactoring efforts. Code coverage is a measurement of the amount of code that is run by unit tests - either lines, branches, or methods. As an example, if you have a simple application with only two conditional branches of code (_branch a_, and _branch b_), a unit test that verifies conditional _branch a_ will report branch code coverage of 50%. -This article discusses the usage of code coverage for unit testing with coverlet, and it is [open source project on GitHub](https://github.com/coverlet-coverage/coverlet). Coverlet is a cross platform code coverage framework for .NET. Additionally, [coverlet](https://dotnetfoundation.org/projects/coverlet) is part of the .NET foundation. +This article discusses the usage of code coverage for unit testing with coverlet. Coverlet is an [open source project on GitHub](https://github.com/coverlet-coverage/coverlet) that provides a cross platform code coverage framework for .NET. [Coverlet](https://dotnetfoundation.org/projects/coverlet) is part of the .NET foundation. ## Tooling @@ -31,13 +31,13 @@ dotnet test --collect:"XPlat Code Coverage" ``` > [!IMPORTANT] -> The `"XPlat Code Coverage"` argument is a friendly name that corresponds to the data collectors from coverlet. This name is required, but is case insensitive. +> The `"XPlat Code Coverage"` argument is a friendly name that corresponds to the data collectors from coverlet. This name is required but is case insensitive. As part of the `dotnet test` run, a resulting *TestResults/{test-run-guid}/coverage.cobertura.xml* file is output. The XML file contains the results. #### MSBuild -As an alternative, you could use the MSBuild package. From the .NET Core CLI at the directory level of the *.csproj* file, run the following [`dotnet add package`](../tools/dotnet-add-package.md) command: +As an alternative, you could use the MSBuild package. From a command prompt in the project directory, run the following [`dotnet add package`](../tools/dotnet-add-package.md) command: ```dotnetcli dotnet add package coverlet.msbuild @@ -60,7 +60,7 @@ To use coverlet globally, it can be installed as a [.NET global tool](../tools/g dotnet tool install --global coverlet.console ``` -The [coverlet.console](https://www.nuget.org/packages/coverlet.console) NuGet package is added to the environment globally. Now, `coverlet` can be used. +The [coverlet.console](https://www.nuget.org/packages/coverlet.console) NuGet package is added to the environment globally. Now, `coverlet` can be used as a CLI command: ```console coverlet C:\Source\Directory\bin\Debug\netcoreapp3.1\Test.dll --target "dotnet" --targetargs "test . --no-build" From d41c237d85c0d7d8395e221d337b683d2ed998da Mon Sep 17 00:00:00 2001 From: David Pine Date: Mon, 15 Jun 2020 15:28:13 -0500 Subject: [PATCH 08/17] Many more updates --- .../testing/unit-testing-code-coverage.md | 191 +++++++++++++++++- 1 file changed, 183 insertions(+), 8 deletions(-) diff --git a/docs/core/testing/unit-testing-code-coverage.md b/docs/core/testing/unit-testing-code-coverage.md index 872094f86f553..e635d42cd8966 100644 --- a/docs/core/testing/unit-testing-code-coverage.md +++ b/docs/core/testing/unit-testing-code-coverage.md @@ -10,13 +10,18 @@ ms.date: 06/15/2020 Unit tests help to ensure functionality, and provide a means of verification for refactoring efforts. Code coverage is a measurement of the amount of code that is run by unit tests - either lines, branches, or methods. As an example, if you have a simple application with only two conditional branches of code (_branch a_, and _branch b_), a unit test that verifies conditional _branch a_ will report branch code coverage of 50%. -This article discusses the usage of code coverage for unit testing with coverlet. Coverlet is an [open source project on GitHub](https://github.com/coverlet-coverage/coverlet) that provides a cross platform code coverage framework for .NET. [Coverlet](https://dotnetfoundation.org/projects/coverlet) is part of the .NET foundation. +This article discusses the usage of code coverage for unit testing with coverlet. Coverlet is an [open source project on GitHub](https://github.com/coverlet-coverage/coverlet) that provides a cross platform code coverage framework for .NET. [Coverlet](https://dotnetfoundation.org/projects/coverlet) is part of the .NET foundation. Coverlet does not support F# or Visual Basic, as such this article is scoped C# and xUnit. Additionally, this article details how to use the code coverage information collected from test runs to generate reports using [ReportGenerator](https://github.com/danielpalme/ReportGenerator). ReportGenerator converts coverage reports generated by OpenCover, dotCover, Visual Studio, NCover, Cobertura, JaCoCo, Clover, gcov, or lcov into human readable reports in various formats. ## Tooling -To use coverlet for code coverage, an existing unit test project must have the appropriate package dependencies, or alternatively rely on [.NET global tooling](../tools/global-tools.md). +There are several tooling aspects of unit testing code coverage for consideration: -### Integrate with .NET test +- **DataCollectors:** DataCollectors are used to monitor test execution. They collect generated information about test runs in various output formats, XML, JSON, etc. For more information, see [your first DataCollector](https://github.com/Microsoft/vstest-docs/blob/master/docs/extensions/datacollector.md). +- **Report generators:** Use data collected from test runs to generate reports, often as styled HTML. + +In this section, the focus is on data collector tools. To use coverlet for code coverage, an existing unit test project must have the appropriate package dependencies, or alternatively rely on [.NET global tooling](../tools/global-tools.md). + +## Integrate with .NET test To integrate with [`dotnet test`](../tools/dotnet-test.md), add the appropriate package dependency. From the directory of the *.csproj* file, run the following [`dotnet add package`](../tools/dotnet-add-package.md) command: @@ -33,11 +38,86 @@ dotnet test --collect:"XPlat Code Coverage" > [!IMPORTANT] > The `"XPlat Code Coverage"` argument is a friendly name that corresponds to the data collectors from coverlet. This name is required but is case insensitive. -As part of the `dotnet test` run, a resulting *TestResults/{test-run-guid}/coverage.cobertura.xml* file is output. The XML file contains the results. +As part of the `dotnet test` run, a resulting *coverage.cobertura.xml* file is output to the *TestResults* directory. The XML file contains the results. This is a cross platform option that relies on the .NET Core CLI, and it great for build systems where MSBuild is not available. + +Below is the example *coverage.json* file from the corresponding sample repo. + +```xml + + + + C:\ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +``` -#### MSBuild +### MSBuild -As an alternative, you could use the MSBuild package. From a command prompt in the project directory, run the following [`dotnet add package`](../tools/dotnet-add-package.md) command: +As an alternative, you could use the MSBuild package if your build system already makes use of MSBuild. From a command prompt in the project directory, run the following [`dotnet add package`](../tools/dotnet-add-package.md) command: ```dotnetcli dotnet add package coverlet.msbuild @@ -49,10 +129,89 @@ The [coverlet.msbuild](https://www.nuget.org/packages/coverlet.msbuild) NuGet pa dotnet test /p:CollectCoverage=true ``` +Below is the example *coverage.json* file from the corresponding sample repo. + +```json +{ + "Numbers.dll": { + "..\\samples\\csharp\\unit-testing\\Numbers\\PrimeService.cs": { + "Numbers.PrimeService": { + "System.Boolean Numbers.PrimeService::IsPrime(System.Int32)": { + "Lines": { + "8": 11, + "9": 11, + "10": 3, + "11": 3, + "14": 22, + "15": 7, + "16": 7, + "17": 4, + "18": 4, + "20": 3, + "21": 4, + "23": 11 + }, + "Branches": [ + { + "Line": 9, + "Offset": 7, + "EndOffset": 9, + "Path": 0, + "Ordinal": 0, + "Hits": 3 + }, + { + "Line": 9, + "Offset": 7, + "EndOffset": 14, + "Path": 1, + "Ordinal": 1, + "Hits": 8 + }, + { + "Line": 14, + "Offset": 57, + "EndOffset": 18, + "Path": 1, + "Ordinal": 5, + "Hits": 7 + }, + { + "Line": 16, + "Offset": 27, + "EndOffset": 29, + "Path": 0, + "Ordinal": 2, + "Hits": 4 + }, + { + "Line": 16, + "Offset": 27, + "EndOffset": 34, + "Path": 1, + "Ordinal": 3, + "Hits": 3 + }, + { + "Line": 14, + "Offset": 57, + "EndOffset": 59, + "Path": 0, + "Ordinal": 4, + "Hits": 4 + } + ] + } + } + } + } +} +``` + > [!NOTE] -> There is a subtle differences in the output between the two `dotnet test` commands. The first output was an XML file, whereas the last is a JSON file. +> There is a subtle difference in the output between the two `dotnet test` commands. The first output was an XML file, whereas the last is a JSON file. -### Use with .NET global tooling +## Use with .NET global tooling To use coverlet globally, it can be installed as a [.NET global tool](../tools/global-tools.md). Run the following [`dotnet tool install`](../tools/dotnet-tool-install.md) command: @@ -66,10 +225,26 @@ The [coverlet.console](https://www.nuget.org/packages/coverlet.console) NuGet pa coverlet C:\Source\Directory\bin\Debug\netcoreapp3.1\Test.dll --target "dotnet" --targetargs "test . --no-build" ``` +## Generate reports + +Now that you're able to collect data from unit test runs, you can generate reports using [ReportGenerator](https://github.com/danielpalme/ReportGenerator). First, install the [ReportGenerator](https://www.nuget.org/packages/dotnet-reportgenerator-globaltool) NuGet package as a [.NET global tool](../tools/global-tools.md) using the [`dotnet tool install`](../tools/dotnet-tool-install.md) command: + +```dotnetcli +dotnet tool install -g dotnet-reportgenerator-globaltool +``` + +Run the tool and provide the desired options, given the output from a test run. + +```console + +``` + ## See also - [Visual Studio unit test cover coverage](/visualstudio/test/using-code-coverage-to-determine-how-much-code-is-being-tested) - [GitHub - Coverlet repository](https://github.com/coverlet-coverage/coverlet) +- [GitHub - ReportGenerator repository](https://github.com/danielpalme/ReportGenerator) +- [ReportGenerator project site](https://danielpalme.github.io/ReportGenerator) - [.NET Core CLI test command](../tools/dotnet-test.md) ## Next Steps From ae506d0925b004442d3b6a8a08e9cacb840db76d Mon Sep 17 00:00:00 2001 From: David Pine Date: Tue, 16 Jun 2020 08:56:40 -0500 Subject: [PATCH 09/17] Massive updates, more like a tutorial now --- .../testing/unit-testing-code-coverage.md | 147 +++++++++++++++++- 1 file changed, 140 insertions(+), 7 deletions(-) diff --git a/docs/core/testing/unit-testing-code-coverage.md b/docs/core/testing/unit-testing-code-coverage.md index e635d42cd8966..e1cee39fc0884 100644 --- a/docs/core/testing/unit-testing-code-coverage.md +++ b/docs/core/testing/unit-testing-code-coverage.md @@ -3,7 +3,7 @@ title: Use code coverage for unit testing description: Learn how to use the code coverage capabilities for .NET unit tests. author: IEvangelist ms.author: dapine -ms.date: 06/15/2020 +ms.date: 06/16/2020 --- # Use code coverage for unit testing @@ -12,6 +12,136 @@ Unit tests help to ensure functionality, and provide a means of verification for This article discusses the usage of code coverage for unit testing with coverlet. Coverlet is an [open source project on GitHub](https://github.com/coverlet-coverage/coverlet) that provides a cross platform code coverage framework for .NET. [Coverlet](https://dotnetfoundation.org/projects/coverlet) is part of the .NET foundation. Coverlet does not support F# or Visual Basic, as such this article is scoped C# and xUnit. Additionally, this article details how to use the code coverage information collected from test runs to generate reports using [ReportGenerator](https://github.com/danielpalme/ReportGenerator). ReportGenerator converts coverage reports generated by OpenCover, dotCover, Visual Studio, NCover, Cobertura, JaCoCo, Clover, gcov, or lcov into human readable reports in various formats. +## System under test + +The "system under test" refers to the code that you're writing unit tests against, this could be an object, service, or anything else that exposes testable functionality. + +### Create a new class library + +From a command prompt in a new directory named `UnitTestingCodeCoverage`, create a new .NET standard class library using the [`dotnet new classlib`](../tools/dotnet-new.md#classlib) command: + +```dotnetcli +dotnet new classlib -n Numbers +``` + +The snippet below defines a simple `PrimeService` class that provides functionality to check if a number is prime. Copy the snippet below and replace the contents of the *Class1.cs* file that was automatically created in the *Numbers* directory. Rename the *Class1.cs* file to *PrimeService.cs*. + +```csharp +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; + } + } +} +``` + +### Create test projects + +Next, create two new **xUnit Test Project (.NET Core)** templates from the same command prompt using the [`dotnet new xunit`](../tools/dotnet-new.md#test) command: + +```dotnetcli +dotnet new xunit -n XUnit.Coverlet.Collector +``` + +```dotnetcli +dotnet new xunit -n XUnit.Coverlet.MSBuild +``` + +Both of the newly created xUnit test projects need to add a project reference of the *Numbers* class library. This is so that the test projects have access to the *PrimeService* for testing. From the command prompt use the [`dotnet add`](../tools/dotnet-add-reference.md) command: + +```dotnetcli +dotnet add XUnit.Coverlet.Collector\XUnit.Coverlet.Collector.csproj reference Numbers\Numbers.csproj +``` + +```dotnetcli +dotnet add XUnit.Coverlet.MSBuild\XUnit.Coverlet.MSBuild.csproj reference Numbers\Numbers.csproj +``` + +The *MSBuild* project is named appropriately, as it will depend on the [coverlet.msbuild](https://www.nuget.org/packages/coverlet.msbuild) NuGet package. Add this package dependency by running the [`dotnet add package`](../tools/dotnet-add-package.md) command: + +```dotnetcli +cd XUnit.Coverlet.MSBuild\ && dotnet add package coverlet.msbuild && cd .. +``` + +The previous command, first changed directories effectively scoping to the *MSBuild* test project, then added the NuGet package. When that was done, it then changed directories, stepping up one level. + +Open both of the *UnitTest1.cs* files, and replace their contents with the following snippet. + +```csharp +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"); + } +} +``` + +> [!TIP] +> It is worth mentioning the that `Numbers` class library was intentionally added to the `System` namespace. This allows for to be accessible without a `using System;` namespace declaration. For more information, see [namespace (C# Reference)](../../csharp/language-reference/keywords/namespace.md). + +### Create solution + +From the command prompt, create a new solution to encapsulate the class library and the two test projects. Using the [`dotnet sln`](../tools/dotnet-sln.md) command: + +```dotnetcli +dotnet new sln -n XUnit.Coverage +``` + +This will create a new solution file name `XUnit.Coverage` at the root of the *UnitTestingCodeCoverage* directory. Next, add the projects to the root of the solution. + +```dotnetcli +dotnet sln XUnit.Coverage.sln add Numbers\Numbers.csproj XUnit.Coverlet.Collector\XUnit.Coverlet.Collector.csproj XUnit.Coverlet.MSBuild\XUnit.Coverlet.MSBuild.csproj --in-root +``` + +Finally, build the solution to ensure that all the projects were correctly constructed using the [`dotnet build`](../tools/dotnet-build.md) command: + +```dotnetcli +dotnet build +``` + ## Tooling There are several tooling aspects of unit testing code coverage for consideration: @@ -44,16 +174,19 @@ Below is the example *coverage.json* file from the corresponding sample repo. ```xml - + C:\ - + - + @@ -134,7 +267,7 @@ Below is the example *coverage.json* file from the corresponding sample repo. ```json { "Numbers.dll": { - "..\\samples\\csharp\\unit-testing\\Numbers\\PrimeService.cs": { + "Numbers\\PrimeService.cs": { "Numbers.PrimeService": { "System.Boolean Numbers.PrimeService::IsPrime(System.Int32)": { "Lines": { @@ -209,7 +342,7 @@ Below is the example *coverage.json* file from the corresponding sample repo. ``` > [!NOTE] -> There is a subtle difference in the output between the two `dotnet test` commands. The first output was an XML file, whereas the last is a JSON file. +> There is a subtle difference between the outputs of the two `dotnet test` commands. The first output was an XML file, whereas the last is a JSON file. ## Use with .NET global tooling @@ -222,7 +355,7 @@ dotnet tool install --global coverlet.console The [coverlet.console](https://www.nuget.org/packages/coverlet.console) NuGet package is added to the environment globally. Now, `coverlet` can be used as a CLI command: ```console -coverlet C:\Source\Directory\bin\Debug\netcoreapp3.1\Test.dll --target "dotnet" --targetargs "test . --no-build" +coverlet C:\TestProj\bin\Debug\netcoreapp3.1\TestProj.dll --target "dotnet" --targetargs "test . --no-build" ``` ## Generate reports From 73dd099d0d6b901ee062a244a120466949244029 Mon Sep 17 00:00:00 2001 From: David Pine Date: Tue, 16 Jun 2020 10:25:36 -0500 Subject: [PATCH 10/17] Added a lot and managed updates --- docs/core/testing/media/test-report.png | Bin 0 -> 94850 bytes .../testing/unit-testing-code-coverage.md | 80 +++++++++++------- 2 files changed, 50 insertions(+), 30 deletions(-) create mode 100644 docs/core/testing/media/test-report.png diff --git a/docs/core/testing/media/test-report.png b/docs/core/testing/media/test-report.png new file mode 100644 index 0000000000000000000000000000000000000000..1d1410ab61c1feb111b7fc37c0345d90a2252c09 GIT binary patch literal 94850 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

MM+8;IN<%Fy)UM4p6CfUV713Vv zGhmhGH#!4buA2oU+Oa%SLDIE%5;6s$GpMO-UwZh^_02CVUcU(qvTx2nl%~xhZ|~7L zT`oSPj!!nKKe|wKg?41uhkVj5+8-Mibb`L-L))L!T^6Lm=0V-%8{q&ki}nj|jY_Mj;QltDq4`yag9!b;VGS>m_m@lK3yO@X zhf;10Uq*NN>OtHc21oC5%P0u{PjD1G*dD5xB5;vWbJvbp+}K1GBLyPwKx!JWA1Zl} zf>i0?^WJ;pPxN*kbEMS5EsGt>`{=Eolo0}|FAQLSc}wgm6o{MXv~ekzW!SfBGixK+1a!;J|7nD&P=(pi{1TOj^$oO= zX`j&fdy!$>iP1$z5y`Kflnk-(Lu8yiGbZ-cWW%I>(&B~=%!4;F8l@;bDI9X*?F?#A zgh&a?FZ|QBjkR*`FtjfALt39@#=4{$i*ngxDiUp>S+r2Ar(`THw9()xZ82Z9=a`1N z*Tyh-T4~s`X@3>zeHptVBb=W&UUzi!75YXvIFVsgsc!0mlip}gXah=C7WE8V*62C; z*!0@U2}-?%wkR~C<+-#8@o$oqDHymsulb~R+Cs1xYy*OjGHBk`b<9X`Tvb8bPI;$K zTCwDyTm~&=YwBtZmTH~z-uA2b`;W);IvV*(Q(skR;9o8Wn(Xv!?nYkl)>Ceeeto1C zvPgaW1&TL+N4{TgvBG=76SaO&)uK*de--!GBKOjPhYUDF7%t4_rHorhm5!%fg_Lmc zGXbjVfa0pMbA3hgU=`}0R$wlwFH`RI6*ain3sGcng{T!T4Wwy!bxP7ELaoUaqtyc} z;|9c#|QP^0S zT~-s0JB+=yIVN^%BY;$Qb_E?z9+`mN@RdT-mM-sP>+?|6@s@4UeJNBIbt3zfX!mZH z9p{`U8{eapX3pvoQt|Iovgc+#|6Z(0Y1LtF%T9bO0q1)2S&lvVG2#FZu-IMpo z^-`(6<5VK-7UhpJHrM??*QgB*sP;SDTw(;%4drUDPpp ziyjFQJ)%VKb@VcNNd!UEFqlyyq8ox3(Z40~Jp0-Ed-rd@zkM9vAKyA0Gp4LH*SgD9 z&g;DH`+Y6|K=UKLV@>y{g58)*eaF><(ViOH`WF_e=2ZiU&CJch*Iy@|Ir`~VFl&Sf z>4qM>bF#K*J+8m=NbXv`N;;%iuk{Q4MPAiy-)@KP9)*QyaCUqD=g5k0j5=nAYk>wt zT}zEqoS_M>9gAXKxVyDVuEGGjcMTeZ{kr19Oz;I~4D3onLW{S^uk?jCHhH6K5t36N zkX=CH)y>vy5|hPNRuj{$C%i8E9-1Nd>@(pe?a`;lDjyT1*cTw`6rVoP+JE3RtDxa^ zQL~Ce6P1UI)%q-0tCkdYU+oPb%8wIRb#eMtfH$WSR@En@Id8gM)9KHDo0?3FcPSkQ zTYtW-eEPA(&KZIE!{%)X*(xt<=lTBQM?&>!zxq4#`{6?GvCx=J4zn~|7^12P( z8VRfN+OIreKaKdXuTj;Q>mvE%=v7B5my?j;QT}xvqeL&OMvc;_wC0ERN_L5J02r9{ z(8sO5IQ)1F02d}u;iK1zj-t4nqysX{kQYsJ>?nV-hSPxt8{Eew%5a{kz

4I2gkr(7YS$~KDHW{Gr545Km=)-a&rdA{+ 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 N002ovPDHLkV1hsoclQ7Q literal 0 HcmV?d00001 diff --git a/docs/core/testing/unit-testing-code-coverage.md b/docs/core/testing/unit-testing-code-coverage.md index e1cee39fc0884..45184941b5f00 100644 --- a/docs/core/testing/unit-testing-code-coverage.md +++ b/docs/core/testing/unit-testing-code-coverage.md @@ -10,13 +10,15 @@ ms.date: 06/16/2020 Unit tests help to ensure functionality, and provide a means of verification for refactoring efforts. Code coverage is a measurement of the amount of code that is run by unit tests - either lines, branches, or methods. As an example, if you have a simple application with only two conditional branches of code (_branch a_, and _branch b_), a unit test that verifies conditional _branch a_ will report branch code coverage of 50%. -This article discusses the usage of code coverage for unit testing with coverlet. Coverlet is an [open source project on GitHub](https://github.com/coverlet-coverage/coverlet) that provides a cross platform code coverage framework for .NET. [Coverlet](https://dotnetfoundation.org/projects/coverlet) is part of the .NET foundation. Coverlet does not support F# or Visual Basic, as such this article is scoped C# and xUnit. Additionally, this article details how to use the code coverage information collected from test runs to generate reports using [ReportGenerator](https://github.com/danielpalme/ReportGenerator). ReportGenerator converts coverage reports generated by OpenCover, dotCover, Visual Studio, NCover, Cobertura, JaCoCo, Clover, gcov, or lcov into human readable reports in various formats. +This article discusses the usage of code coverage for unit testing with coverlet and report generation with ReportGenerator. Coverlet is an [open source project on GitHub](https://github.com/coverlet-coverage/coverlet) that provides a cross platform code coverage framework for .NET. [Coverlet](https://dotnetfoundation.org/projects/coverlet) is part of the .NET foundation. Coverlet does not support F# or Visual Basic, as such this article is scoped C# and xUnit. + +Additionally, this article details how to use the code coverage information collected from test runs to generate reports using another [open source project on GitHub - ReportGenerator](https://github.com/danielpalme/ReportGenerator). ReportGenerator converts coverage reports generated by OpenCover, dotCover, Visual Studio, NCover, Cobertura, JaCoCo, Clover, gcov, or lcov into human readable reports in various formats. ## System under test -The "system under test" refers to the code that you're writing unit tests against, this could be an object, service, or anything else that exposes testable functionality. +The "system under test" refers to the code that you're writing unit tests against, this could be an object, service, or anything else that exposes testable functionality. For the purpose of this article, you'll create a class library that will be the system under test, and two corresponding unit test projects. -### Create a new class library +### Create a class library From a command prompt in a new directory named `UnitTestingCodeCoverage`, create a new .NET standard class library using the [`dotnet new classlib`](../tools/dotnet-new.md#classlib) command: @@ -51,9 +53,12 @@ namespace System.Numbers } ``` +> [!TIP] +> It is worth mentioning the that `Numbers` class library was intentionally added to the `System` namespace. This allows for to be accessible without a `using System;` namespace declaration. For more information, see [namespace (C# Reference)](../../csharp/language-reference/keywords/namespace.md). + ### Create test projects -Next, create two new **xUnit Test Project (.NET Core)** templates from the same command prompt using the [`dotnet new xunit`](../tools/dotnet-new.md#test) command: +Create two new **xUnit Test Project (.NET Core)** templates from the same command prompt using the [`dotnet new xunit`](../tools/dotnet-new.md#test) command: ```dotnetcli dotnet new xunit -n XUnit.Coverlet.Collector @@ -79,9 +84,9 @@ The *MSBuild* project is named appropriately, as it will depend on the [coverlet cd XUnit.Coverlet.MSBuild\ && dotnet add package coverlet.msbuild && cd .. ``` -The previous command, first changed directories effectively scoping to the *MSBuild* test project, then added the NuGet package. When that was done, it then changed directories, stepping up one level. +The previous command changed directories effectively scoping to the *MSBuild* test project, then added the NuGet package. When that was done, it then changed directories, stepping up one level. -Open both of the *UnitTest1.cs* files, and replace their contents with the following snippet. +Open both of the *UnitTest1.cs* files, and replace their contents with the following snippet. Rename the *UnitTest1.cs* files to *PrimeServiceTests.cs*. ```csharp using System.Numbers; @@ -119,10 +124,7 @@ namespace XUnit.Coverlet } ``` -> [!TIP] -> It is worth mentioning the that `Numbers` class library was intentionally added to the `System` namespace. This allows for to be accessible without a `using System;` namespace declaration. For more information, see [namespace (C# Reference)](../../csharp/language-reference/keywords/namespace.md). - -### Create solution +### Create a solution From the command prompt, create a new solution to encapsulate the class library and the two test projects. Using the [`dotnet sln`](../tools/dotnet-sln.md) command: @@ -130,18 +132,30 @@ From the command prompt, create a new solution to encapsulate the class library dotnet new sln -n XUnit.Coverage ``` -This will create a new solution file name `XUnit.Coverage` at the root of the *UnitTestingCodeCoverage* directory. Next, add the projects to the root of the solution. +This will create a new solution file name `XUnit.Coverage` in the *UnitTestingCodeCoverage* directory. Add the projects to the root of the solution. + +## [Linux](#tab/linux) ```dotnetcli -dotnet sln XUnit.Coverage.sln add Numbers\Numbers.csproj XUnit.Coverlet.Collector\XUnit.Coverlet.Collector.csproj XUnit.Coverlet.MSBuild\XUnit.Coverlet.MSBuild.csproj --in-root +dotnet sln XUnit.Coverage.sln add **/*.csproj --in-root ``` -Finally, build the solution to ensure that all the projects were correctly constructed using the [`dotnet build`](../tools/dotnet-build.md) command: +## [Windows](#tab/windows) + +```dotnetcli +dotnet sln XUnit.Coverage.sln add (ls **/*.csproj) --in-root +``` + +--- + +Build the solution using the [`dotnet build`](../tools/dotnet-build.md) command: ```dotnetcli dotnet build ``` +If the build is successful, you've created the three projects, appropriately referenced projects and packages, and updated the source code correctly. Well done! + ## Tooling There are several tooling aspects of unit testing code coverage for consideration: @@ -153,24 +167,29 @@ In this section, the focus is on data collector tools. To use coverlet for code ## Integrate with .NET test +> [!IMPORTANT] +> The xUnit test project template already integrates with [coverlet.collector](https://www.nuget.org/packages/coverlet.collector) by default. However, if you're working with a test project that doesn't already include this package reference you could add it. + To integrate with [`dotnet test`](../tools/dotnet-test.md), add the appropriate package dependency. From the directory of the *.csproj* file, run the following [`dotnet add package`](../tools/dotnet-add-package.md) command: ```dotnetcli dotnet add package coverlet.collector ``` -The [coverlet.collector](https://www.nuget.org/packages/coverlet.collector) NuGet package is added to the project. Next, run the following command: +The [coverlet.collector](https://www.nuget.org/packages/coverlet.collector) NuGet package is added to the project. + +From the command prompt, change directories to the *XUnit.Coverlet.Collector* project, and run the [`dotnet test`](../tools/dotnet-test.md) command: ```dotnetcli -dotnet test --collect:"XPlat Code Coverage" +cd XUnit.Coverlet.Collector && dotnet test --collect:"XPlat Code Coverage" ``` -> [!IMPORTANT] +> [!NOTE] > The `"XPlat Code Coverage"` argument is a friendly name that corresponds to the data collectors from coverlet. This name is required but is case insensitive. -As part of the `dotnet test` run, a resulting *coverage.cobertura.xml* file is output to the *TestResults* directory. The XML file contains the results. This is a cross platform option that relies on the .NET Core CLI, and it great for build systems where MSBuild is not available. +As part of the `dotnet test` run, a resulting *coverage.cobertura.xml* file is output to the *TestResults* directory. The XML file contains the results. This is a cross platform option that relies on the .NET Core CLI, and it is great for build systems where MSBuild is not available. -Below is the example *coverage.json* file from the corresponding sample repo. +Below is the example *coverage.cobertura.xml* file from the corresponding sample repo. ```xml @@ -250,13 +269,7 @@ Below is the example *coverage.json* file from the corresponding sample repo. ### MSBuild -As an alternative, you could use the MSBuild package if your build system already makes use of MSBuild. From a command prompt in the project directory, run the following [`dotnet add package`](../tools/dotnet-add-package.md) command: - -```dotnetcli -dotnet add package coverlet.msbuild -``` - -The [coverlet.msbuild](https://www.nuget.org/packages/coverlet.msbuild) NuGet package is added to the project. Next, run the following command: +As an alternative, you could use the MSBuild package if your build system already makes use of MSBuild. From a command prompt change directories to the *XUnit.Coverlet.MSBuild* project, and run the `dotnet test` command: ```dotnetcli dotnet test /p:CollectCoverage=true @@ -346,7 +359,7 @@ Below is the example *coverage.json* file from the corresponding sample repo. ## Use with .NET global tooling -To use coverlet globally, it can be installed as a [.NET global tool](../tools/global-tools.md). Run the following [`dotnet tool install`](../tools/dotnet-tool-install.md) command: +To use coverlet globally, it can be installed as a [.NET global tool](../tools/global-tools.md). Optionally, run the following [`dotnet tool install`](../tools/dotnet-tool-install.md) command: ```dotnetcli dotnet tool install --global coverlet.console @@ -355,23 +368,30 @@ dotnet tool install --global coverlet.console The [coverlet.console](https://www.nuget.org/packages/coverlet.console) NuGet package is added to the environment globally. Now, `coverlet` can be used as a CLI command: ```console -coverlet C:\TestProj\bin\Debug\netcoreapp3.1\TestProj.dll --target "dotnet" --targetargs "test . --no-build" +coverlet Full\Path\To\TestProject.dll --target "dotnet" --targetargs "test . --no-build" ``` ## Generate reports -Now that you're able to collect data from unit test runs, you can generate reports using [ReportGenerator](https://github.com/danielpalme/ReportGenerator). First, install the [ReportGenerator](https://www.nuget.org/packages/dotnet-reportgenerator-globaltool) NuGet package as a [.NET global tool](../tools/global-tools.md) using the [`dotnet tool install`](../tools/dotnet-tool-install.md) command: +Now that you're able to collect data from unit test runs, you can generate reports using [ReportGenerator](https://github.com/danielpalme/ReportGenerator). To install the [ReportGenerator](https://www.nuget.org/packages/dotnet-reportgenerator-globaltool) NuGet package as a [.NET global tool](../tools/global-tools.md), use the [`dotnet tool install`](../tools/dotnet-tool-install.md) command: ```dotnetcli dotnet tool install -g dotnet-reportgenerator-globaltool ``` -Run the tool and provide the desired options, given the output from a test run. +Run the tool and provide the desired options, given the output *coverage.cobertura.xml* file from the previous test run. ```console - +reportgenerator +"-reports:Path\To\TestProject\TestResults\{guid}\coverage.cobertura.xml" +"-targetdir:coveragereport" +-reporttypes:Html ``` +This will generate a report as an HTML file. + +:::image type="content" source="media/test-report.png" alt-text="Unit test generated report"::: + ## See also - [Visual Studio unit test cover coverage](/visualstudio/test/using-code-coverage-to-determine-how-much-code-is-being-tested) From 5e77384990d2c9ff6daf86289765c1b5ecb78794 Mon Sep 17 00:00:00 2001 From: David Pine Date: Tue, 16 Jun 2020 10:56:35 -0500 Subject: [PATCH 11/17] Minor tweaks --- docs/core/testing/unit-testing-code-coverage.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/core/testing/unit-testing-code-coverage.md b/docs/core/testing/unit-testing-code-coverage.md index 45184941b5f00..a6432d7109dbc 100644 --- a/docs/core/testing/unit-testing-code-coverage.md +++ b/docs/core/testing/unit-testing-code-coverage.md @@ -388,9 +388,9 @@ reportgenerator -reporttypes:Html ``` -This will generate a report as an HTML file. +This will generate a report as an HTML file. Here is an example report: -:::image type="content" source="media/test-report.png" alt-text="Unit test generated report"::: +:::image type="content" source="media/test-report.png" lightbox="media/test-report.png" alt-text="Unit test generated report"::: ## See also From 24fed3859a90d1109719f3e549eb0302b70b8d21 Mon Sep 17 00:00:00 2001 From: David Pine Date: Tue, 16 Jun 2020 11:00:23 -0500 Subject: [PATCH 12/17] Updates for acrolinx --- docs/core/testing/unit-testing-code-coverage.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/core/testing/unit-testing-code-coverage.md b/docs/core/testing/unit-testing-code-coverage.md index a6432d7109dbc..7c92dd630927b 100644 --- a/docs/core/testing/unit-testing-code-coverage.md +++ b/docs/core/testing/unit-testing-code-coverage.md @@ -68,7 +68,7 @@ dotnet new xunit -n XUnit.Coverlet.Collector dotnet new xunit -n XUnit.Coverlet.MSBuild ``` -Both of the newly created xUnit test projects need to add a project reference of the *Numbers* class library. This is so that the test projects have access to the *PrimeService* for testing. From the command prompt use the [`dotnet add`](../tools/dotnet-add-reference.md) command: +Both of the newly created xUnit test projects need to add a project reference of the *Numbers* class library. This is so that the test projects have access to the *PrimeService* for testing. From the command prompt, use the [`dotnet add`](../tools/dotnet-add-reference.md) command: ```dotnetcli dotnet add XUnit.Coverlet.Collector\XUnit.Coverlet.Collector.csproj reference Numbers\Numbers.csproj @@ -160,7 +160,7 @@ If the build is successful, you've created the three projects, appropriately ref There are several tooling aspects of unit testing code coverage for consideration: -- **DataCollectors:** DataCollectors are used to monitor test execution. They collect generated information about test runs in various output formats, XML, JSON, etc. For more information, see [your first DataCollector](https://github.com/Microsoft/vstest-docs/blob/master/docs/extensions/datacollector.md). +- **DataCollectors:** DataCollectors are used to monitor test execution, and to collect generated information about test runs in various output formats, XML, JSON, etc. For more information, see [your first DataCollector](https://github.com/Microsoft/vstest-docs/blob/master/docs/extensions/datacollector.md). - **Report generators:** Use data collected from test runs to generate reports, often as styled HTML. In this section, the focus is on data collector tools. To use coverlet for code coverage, an existing unit test project must have the appropriate package dependencies, or alternatively rely on [.NET global tooling](../tools/global-tools.md). @@ -390,7 +390,7 @@ reportgenerator This will generate a report as an HTML file. Here is an example report: -:::image type="content" source="media/test-report.png" lightbox="media/test-report.png" alt-text="Unit test generated report"::: +:::image type="content" source="media/test-report.png" lightbox="media/test-report.png" alt-text="Unit test-generated report"::: ## See also From cfc46b5b872e5e78fdf6f3f5a5d2ac11e491d943 Mon Sep 17 00:00:00 2001 From: David Pine Date: Tue, 16 Jun 2020 11:01:36 -0500 Subject: [PATCH 13/17] Another minor update --- docs/core/testing/unit-testing-code-coverage.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/core/testing/unit-testing-code-coverage.md b/docs/core/testing/unit-testing-code-coverage.md index 7c92dd630927b..282ca3d3f5cc4 100644 --- a/docs/core/testing/unit-testing-code-coverage.md +++ b/docs/core/testing/unit-testing-code-coverage.md @@ -170,7 +170,7 @@ In this section, the focus is on data collector tools. To use coverlet for code > [!IMPORTANT] > The xUnit test project template already integrates with [coverlet.collector](https://www.nuget.org/packages/coverlet.collector) by default. However, if you're working with a test project that doesn't already include this package reference you could add it. -To integrate with [`dotnet test`](../tools/dotnet-test.md), add the appropriate package dependency. From the directory of the *.csproj* file, run the following [`dotnet add package`](../tools/dotnet-add-package.md) command: +To integrate with [`dotnet test`](../tools/dotnet-test.md), add the appropriate package dependency. From the directory of the *\*.csproj* file, run the following [`dotnet add package`](../tools/dotnet-add-package.md) command: ```dotnetcli dotnet add package coverlet.collector @@ -269,7 +269,7 @@ Below is the example *coverage.cobertura.xml* file from the corresponding sample ### MSBuild -As an alternative, you could use the MSBuild package if your build system already makes use of MSBuild. From a command prompt change directories to the *XUnit.Coverlet.MSBuild* project, and run the `dotnet test` command: +As an alternative, you could use the MSBuild package if your build system already makes use of MSBuild. From a command prompt, change directories to the *XUnit.Coverlet.MSBuild* project, and run the `dotnet test` command: ```dotnetcli dotnet test /p:CollectCoverage=true @@ -388,7 +388,7 @@ reportgenerator -reporttypes:Html ``` -This will generate a report as an HTML file. Here is an example report: +After running this command, an HTML file represents the generated report. :::image type="content" source="media/test-report.png" lightbox="media/test-report.png" alt-text="Unit test-generated report"::: From 3cbe09a4e03e12e52e977e48196dd1c710eaeb06 Mon Sep 17 00:00:00 2001 From: David Pine Date: Tue, 16 Jun 2020 16:43:06 -0500 Subject: [PATCH 14/17] Apply suggestions from code review Co-authored-by: Tom Dykstra --- docs/core/testing/unit-testing-code-coverage.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/core/testing/unit-testing-code-coverage.md b/docs/core/testing/unit-testing-code-coverage.md index 282ca3d3f5cc4..217980ae88e23 100644 --- a/docs/core/testing/unit-testing-code-coverage.md +++ b/docs/core/testing/unit-testing-code-coverage.md @@ -158,9 +158,9 @@ If the build is successful, you've created the three projects, appropriately ref ## Tooling -There are several tooling aspects of unit testing code coverage for consideration: +There are two types of code coverage tools: -- **DataCollectors:** DataCollectors are used to monitor test execution, and to collect generated information about test runs in various output formats, XML, JSON, etc. For more information, see [your first DataCollector](https://github.com/Microsoft/vstest-docs/blob/master/docs/extensions/datacollector.md). +- **DataCollectors:** DataCollectors monitor test execution and collect information about test runs. They report the collected information in various output formats, such as XML and JSON. For more information, see [your first DataCollector](https://github.com/Microsoft/vstest-docs/blob/master/docs/extensions/datacollector.md). - **Report generators:** Use data collected from test runs to generate reports, often as styled HTML. In this section, the focus is on data collector tools. To use coverlet for code coverage, an existing unit test project must have the appropriate package dependencies, or alternatively rely on [.NET global tooling](../tools/global-tools.md). From 6735415533c1bcbd74a6fe37f3f8a3ae3d7c45da Mon Sep 17 00:00:00 2001 From: David Pine Date: Wed, 17 Jun 2020 08:30:28 -0500 Subject: [PATCH 15/17] Updates from peer review. --- .../testing/unit-testing-code-coverage.md | 131 ++---------------- 1 file changed, 13 insertions(+), 118 deletions(-) diff --git a/docs/core/testing/unit-testing-code-coverage.md b/docs/core/testing/unit-testing-code-coverage.md index 217980ae88e23..d3ed15ebdc73a 100644 --- a/docs/core/testing/unit-testing-code-coverage.md +++ b/docs/core/testing/unit-testing-code-coverage.md @@ -10,9 +10,9 @@ ms.date: 06/16/2020 Unit tests help to ensure functionality, and provide a means of verification for refactoring efforts. Code coverage is a measurement of the amount of code that is run by unit tests - either lines, branches, or methods. As an example, if you have a simple application with only two conditional branches of code (_branch a_, and _branch b_), a unit test that verifies conditional _branch a_ will report branch code coverage of 50%. -This article discusses the usage of code coverage for unit testing with coverlet and report generation with ReportGenerator. Coverlet is an [open source project on GitHub](https://github.com/coverlet-coverage/coverlet) that provides a cross platform code coverage framework for .NET. [Coverlet](https://dotnetfoundation.org/projects/coverlet) is part of the .NET foundation. Coverlet does not support F# or Visual Basic, as such this article is scoped C# and xUnit. +This article discusses the usage of code coverage for unit testing with coverlet and report generation using ReportGenerator. While this article focuses on C# and xUnit as the test framework, both MSTest and NUnit would also work. Coverlet is an [open source project on GitHub](https://github.com/coverlet-coverage/coverlet) that provides a cross platform code coverage framework for C#. [Coverlet](https://dotnetfoundation.org/projects/coverlet) is part of the .NET foundation. Coverlet collects Cobertura coverage test run data, which is used for report generation. -Additionally, this article details how to use the code coverage information collected from test runs to generate reports using another [open source project on GitHub - ReportGenerator](https://github.com/danielpalme/ReportGenerator). ReportGenerator converts coverage reports generated by OpenCover, dotCover, Visual Studio, NCover, Cobertura, JaCoCo, Clover, gcov, or lcov into human readable reports in various formats. +Additionally, this article details how to use the code coverage information collected from a coverlet test run to generate a report. The report generation is possible using another [open source project on GitHub - ReportGenerator](https://github.com/danielpalme/ReportGenerator). ReportGenerator converts coverage reports generated by Cobertura among many others, into human readable reports in various formats. ## System under test @@ -81,7 +81,7 @@ dotnet add XUnit.Coverlet.MSBuild\XUnit.Coverlet.MSBuild.csproj reference Number The *MSBuild* project is named appropriately, as it will depend on the [coverlet.msbuild](https://www.nuget.org/packages/coverlet.msbuild) NuGet package. Add this package dependency by running the [`dotnet add package`](../tools/dotnet-add-package.md) command: ```dotnetcli -cd XUnit.Coverlet.MSBuild\ && dotnet add package coverlet.msbuild && cd .. +cd XUnit.Coverlet.MSBuild && dotnet add package coverlet.msbuild && cd .. ``` The previous command changed directories effectively scoping to the *MSBuild* test project, then added the NuGet package. When that was done, it then changed directories, stepping up one level. @@ -167,17 +167,7 @@ In this section, the focus is on data collector tools. To use coverlet for code ## Integrate with .NET test -> [!IMPORTANT] -> The xUnit test project template already integrates with [coverlet.collector](https://www.nuget.org/packages/coverlet.collector) by default. However, if you're working with a test project that doesn't already include this package reference you could add it. - -To integrate with [`dotnet test`](../tools/dotnet-test.md), add the appropriate package dependency. From the directory of the *\*.csproj* file, run the following [`dotnet add package`](../tools/dotnet-add-package.md) command: - -```dotnetcli -dotnet add package coverlet.collector -``` - -The [coverlet.collector](https://www.nuget.org/packages/coverlet.collector) NuGet package is added to the project. - +The xUnit test project template already integrates with [coverlet.collector](https://www.nuget.org/packages/coverlet.collector) by default. From the command prompt, change directories to the *XUnit.Coverlet.Collector* project, and run the [`dotnet test`](../tools/dotnet-test.md) command: ```dotnetcli @@ -189,7 +179,7 @@ cd XUnit.Coverlet.Collector && dotnet test --collect:"XPlat Code Coverage" As part of the `dotnet test` run, a resulting *coverage.cobertura.xml* file is output to the *TestResults* directory. The XML file contains the results. This is a cross platform option that relies on the .NET Core CLI, and it is great for build systems where MSBuild is not available. -Below is the example *coverage.cobertura.xml* file from the corresponding sample repo. +Below is the example *coverage.cobertura.xml* file. ```xml @@ -267,109 +257,14 @@ Below is the example *coverage.cobertura.xml* file from the corresponding sample ``` -### MSBuild - -As an alternative, you could use the MSBuild package if your build system already makes use of MSBuild. From a command prompt, change directories to the *XUnit.Coverlet.MSBuild* project, and run the `dotnet test` command: - -```dotnetcli -dotnet test /p:CollectCoverage=true -``` - -Below is the example *coverage.json* file from the corresponding sample repo. - -```json -{ - "Numbers.dll": { - "Numbers\\PrimeService.cs": { - "Numbers.PrimeService": { - "System.Boolean Numbers.PrimeService::IsPrime(System.Int32)": { - "Lines": { - "8": 11, - "9": 11, - "10": 3, - "11": 3, - "14": 22, - "15": 7, - "16": 7, - "17": 4, - "18": 4, - "20": 3, - "21": 4, - "23": 11 - }, - "Branches": [ - { - "Line": 9, - "Offset": 7, - "EndOffset": 9, - "Path": 0, - "Ordinal": 0, - "Hits": 3 - }, - { - "Line": 9, - "Offset": 7, - "EndOffset": 14, - "Path": 1, - "Ordinal": 1, - "Hits": 8 - }, - { - "Line": 14, - "Offset": 57, - "EndOffset": 18, - "Path": 1, - "Ordinal": 5, - "Hits": 7 - }, - { - "Line": 16, - "Offset": 27, - "EndOffset": 29, - "Path": 0, - "Ordinal": 2, - "Hits": 4 - }, - { - "Line": 16, - "Offset": 27, - "EndOffset": 34, - "Path": 1, - "Ordinal": 3, - "Hits": 3 - }, - { - "Line": 14, - "Offset": 57, - "EndOffset": 59, - "Path": 0, - "Ordinal": 4, - "Hits": 4 - } - ] - } - } - } - } -} -``` - -> [!NOTE] -> There is a subtle difference between the outputs of the two `dotnet test` commands. The first output was an XML file, whereas the last is a JSON file. - -## Use with .NET global tooling - -To use coverlet globally, it can be installed as a [.NET global tool](../tools/global-tools.md). Optionally, run the following [`dotnet tool install`](../tools/dotnet-tool-install.md) command: - -```dotnetcli -dotnet tool install --global coverlet.console -``` - -The [coverlet.console](https://www.nuget.org/packages/coverlet.console) NuGet package is added to the environment globally. Now, `coverlet` can be used as a CLI command: - -```console -coverlet Full\Path\To\TestProject.dll --target "dotnet" --targetargs "test . --no-build" -``` +> [!TIP] +> As an alternative, you could use the MSBuild package if your build system already makes use of MSBuild. From the command prompt, change directories to the *XUnit.Coverlet.MSBuild* project, and run the `dotnet test` command: +> +> ```dotnetcli +> dotnet test --collect:"XPlat Code Coverage" +> ``` +> +> The resulting *coverage.cobertura.xml* file is output. ## Generate reports From 486532c36ae4586aedee628efcece3e01fcc9a7e Mon Sep 17 00:00:00 2001 From: David Pine Date: Wed, 17 Jun 2020 08:39:45 -0500 Subject: [PATCH 16/17] Proper casing --- docs/core/testing/unit-testing-code-coverage.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/core/testing/unit-testing-code-coverage.md b/docs/core/testing/unit-testing-code-coverage.md index d3ed15ebdc73a..b0f0cc0900824 100644 --- a/docs/core/testing/unit-testing-code-coverage.md +++ b/docs/core/testing/unit-testing-code-coverage.md @@ -10,9 +10,9 @@ ms.date: 06/16/2020 Unit tests help to ensure functionality, and provide a means of verification for refactoring efforts. Code coverage is a measurement of the amount of code that is run by unit tests - either lines, branches, or methods. As an example, if you have a simple application with only two conditional branches of code (_branch a_, and _branch b_), a unit test that verifies conditional _branch a_ will report branch code coverage of 50%. -This article discusses the usage of code coverage for unit testing with coverlet and report generation using ReportGenerator. While this article focuses on C# and xUnit as the test framework, both MSTest and NUnit would also work. Coverlet is an [open source project on GitHub](https://github.com/coverlet-coverage/coverlet) that provides a cross platform code coverage framework for C#. [Coverlet](https://dotnetfoundation.org/projects/coverlet) is part of the .NET foundation. Coverlet collects Cobertura coverage test run data, which is used for report generation. +This article discusses the usage of code coverage for unit testing with Coverlet and report generation using ReportGenerator. While this article focuses on C# and xUnit as the test framework, both MSTest and NUnit would also work. Coverlet is an [open source project on GitHub](https://github.com/coverlet-coverage/coverlet) that provides a cross platform code coverage framework for C#. [Coverlet](https://dotnetfoundation.org/projects/coverlet) is part of the .NET foundation. Coverlet collects Cobertura coverage test run data, which is used for report generation. -Additionally, this article details how to use the code coverage information collected from a coverlet test run to generate a report. The report generation is possible using another [open source project on GitHub - ReportGenerator](https://github.com/danielpalme/ReportGenerator). ReportGenerator converts coverage reports generated by Cobertura among many others, into human readable reports in various formats. +Additionally, this article details how to use the code coverage information collected from a Coverlet test run to generate a report. The report generation is possible using another [open source project on GitHub - ReportGenerator](https://github.com/danielpalme/ReportGenerator). ReportGenerator converts coverage reports generated by Cobertura among many others, into human readable reports in various formats. ## System under test @@ -163,7 +163,7 @@ There are two types of code coverage tools: - **DataCollectors:** DataCollectors monitor test execution and collect information about test runs. They report the collected information in various output formats, such as XML and JSON. For more information, see [your first DataCollector](https://github.com/Microsoft/vstest-docs/blob/master/docs/extensions/datacollector.md). - **Report generators:** Use data collected from test runs to generate reports, often as styled HTML. -In this section, the focus is on data collector tools. To use coverlet for code coverage, an existing unit test project must have the appropriate package dependencies, or alternatively rely on [.NET global tooling](../tools/global-tools.md). +In this section, the focus is on data collector tools. To use Coverlet for code coverage, an existing unit test project must have the appropriate package dependencies, or alternatively rely on [.NET global tooling](../tools/global-tools.md). ## Integrate with .NET test @@ -175,7 +175,7 @@ cd XUnit.Coverlet.Collector && dotnet test --collect:"XPlat Code Coverage" ``` > [!NOTE] -> The `"XPlat Code Coverage"` argument is a friendly name that corresponds to the data collectors from coverlet. This name is required but is case insensitive. +> The `"XPlat Code Coverage"` argument is a friendly name that corresponds to the data collectors from Coverlet. This name is required but is case insensitive. As part of the `dotnet test` run, a resulting *coverage.cobertura.xml* file is output to the *TestResults* directory. The XML file contains the results. This is a cross platform option that relies on the .NET Core CLI, and it is great for build systems where MSBuild is not available. From 54f53fc2fd5a12f736916fef0e9f291e5413c657 Mon Sep 17 00:00:00 2001 From: David Pine Date: Wed, 17 Jun 2020 09:04:03 -0500 Subject: [PATCH 17/17] Final change --- docs/core/testing/unit-testing-code-coverage.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/core/testing/unit-testing-code-coverage.md b/docs/core/testing/unit-testing-code-coverage.md index b0f0cc0900824..42f6f7adeabd3 100644 --- a/docs/core/testing/unit-testing-code-coverage.md +++ b/docs/core/testing/unit-testing-code-coverage.md @@ -163,7 +163,7 @@ There are two types of code coverage tools: - **DataCollectors:** DataCollectors monitor test execution and collect information about test runs. They report the collected information in various output formats, such as XML and JSON. For more information, see [your first DataCollector](https://github.com/Microsoft/vstest-docs/blob/master/docs/extensions/datacollector.md). - **Report generators:** Use data collected from test runs to generate reports, often as styled HTML. -In this section, the focus is on data collector tools. To use Coverlet for code coverage, an existing unit test project must have the appropriate package dependencies, or alternatively rely on [.NET global tooling](../tools/global-tools.md). +In this section, the focus is on data collector tools. To use Coverlet for code coverage, an existing unit test project must have the appropriate package dependencies, or alternatively rely on [.NET global tooling](../tools/global-tools.md) and the corresponding [coverlet.console](https://www.nuget.org/packages/coverlet.console) NuGet package. ## Integrate with .NET test