65.9K
CodeProject 正在变化。 阅读更多。
Home

Visual Studio 2013 和 2015 中的 OpenCover 和 ReportGenerator 单元测试覆盖率

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.80/5 (2投票s)

2019 年 2 月 11 日

CPOL

3分钟阅读

viewsIcon

12369

Visual Studio 2013 和 2015 中的 OpenCover 和 ReportGenerator 单元测试覆盖率

在 Visual Studio 中获取代码覆盖率指标的常用方法是购买 Visual Studio Enterprise 版本或购买 dotCover 第三方工具,这两者都价格昂贵,特别是如果您自己开发小型应用程序并希望检查单元测试的覆盖率。

有一个免费的 NuGet 包,用于生成代码覆盖率指标,名为 OpenCover,并且与另一个免费的 NuGet 包 ReportGenerator 一起,可以免费为您提供代码覆盖率报告。

然而,我发现的问题是,用于让该工具工作的文档对于我的目的来说不够充分,并且我花费了几个小时来使它为我工作。为了节省您的时间和金钱,我在这里记录了我的经验。

创建本文档时参考了以下内容

我已经测试过它在 Visual Studio 2013 Professional 和 Visual Studio 2015 Community Edition 中都有效,并且同时使用 MSTest 和 NUnit。

MSTest 单元测试可以使用 mstest.exe 或较新的 vstest.console.exe 运行。由于我主要使用 NUnit,因此我没有做任何除了基本测试之外的事情来确保 OpenCover 与这两个测试运行程序一起工作,因此无法说明它们在大型项目中的工作方式。

我假设您已经有一个解决方案,其中包含您正在使用测试项目的应用程序项目,并且您正在使用 NUnit 进行该测试,并且您已经包含了 NUnit NuGet 包。

您将需要在 Visual Studio 中打开您的解决方案,并使用程序包管理器控制台获取以下程序包

REM PM> Install-Package OpenCover
REM PM> Install-Package ReportGenerator

如果您使用的是 NUnit 而不是 MSTest,您还需要此包

REM PM> Install-Package NUnit.ConsoleRunner

然后在解决方案根文件夹中,您将需要创建一个批处理文件,用于生成代码覆盖率报告。我提供了三个批处理文件,一个用于使用 NUnit 的情况,一个用于使用 MSTest 和 mstest.exe 测试运行程序的情况,以及一个用于使用 MSTest 和 vstest.console.exe 测试运行程序的情况。

您将需要修改批处理文件以指定包含单元测试的 DLL,即,根据需要更改此行(请注意,%~dp0 是一个符号,它会自动替换为批处理文件的文件夹路径)

SET DllContainingTests=%~dp0WebApp.Tests\bin\Debug\WebApp.Tests.dll

您可能还需要更改应用于结果的筛选器,以排除您不感兴趣代码覆盖率指标的解决方案部分,就我而言,我已要求它包含所有内容(+[*]*),然后排除我的测试项目(-[*.Tests*]*)和所有以 Config 结尾的类(-[*]*.*Config),即

 -filter:"+[*]* -[*.Tests*]* -[*]*.*Config"

如果您使用 MSTest,您可能需要将 TestRunnerExe 变量更改为指向正确版本的 mstest.exevstest.runner.exe。下面的示例指向 Visual Studio 2013 中的文件,但如果您使用 2015,则需要将其更改为 Microsoft Visual Studio 14.0 而不是 Microsoft Visual Studio 12.0。

剩下的就是执行批处理文件以生成代码覆盖率报告,该报告允许您深入了解实际的颜色编码代码是否被覆盖。

NUnit 版本

@ECHO OFF

REM OpenCover-NUnit.bat

REM Run opencover against NUnit tests in your test project and show report of code coverage

REM Derivative work based on work by: 
REM  Shaun Wilde - https://nuget.net.cn/packages/OpenCover/
REM  Daniel Palme - https://nuget.net.cn/packages/ReportGenerator/
REM  Charlie Poole - https://nuget.net.cn/packages/NUnit.ConsoleRunner/
REM  Allen Conway - 
REM   http://www.allenconway.net/2015/06/using-opencover-and-reportgenerator-to.html
REM  Andrew Newton - 
REM   http://www.nootn.com.au/2014/01/code-coverage-with-opencover-example.html#.VxiNn_krLDc


SET DllContainingTests=%~dp0WebApp.Tests\bin\Debug\WebApp.Tests.dll


REM *** IMPORTANT - Change DllContainingTests variable (above) to point to the DLL 
REM ***             in your solution containing your NUnit tests
REM ***
REM ***             You may also want to change the include/exclude filters (below) 
REM ***             for OpenCover
REM ***
REM ***             This batch file should dbe placed in the root folder of your solution

REM *** Before being able to use this to generate coverage reports you 
REM *** will need the following NuGet packages
REM PM> Install-Package OpenCover
REM PM> Install-Package ReportGenerator
REM PM> Install-Package NUnit.ConsoleRunner
REM

REM NUnit Test Runner (done this way so we dont have to change the code 
REM when the version number changes)
for /R "%~dp0packages" %%a in (*) do if /I "%%~nxa"=="nunit3-console.exe" SET TestRunnerExe=%%~dpnxa

REM Get OpenCover Executable (done this way so we dont have to change the 
REM code when the version number changes)
for /R "%~dp0packages" %%a in (*) do if /I "%%~nxa"=="OpenCover.Console.exe" SET OpenCoverExe=%%~dpnxa

REM Get Report Generator (done this way so we dont have to change the code 
REM when the version number changes)
for /R "%~dp0packages" %%a in (*) do if /I "%%~nxa"=="ReportGenerator.exe" 
    SET ReportGeneratorExe=%%~dpnxa

REM Create a 'GeneratedReports' folder if it does not exist
if not exist "%~dp0GeneratedReports" mkdir "%~dp0GeneratedReports"

REM Run the tests against the targeted output
call :RunOpenCoverUnitTestMetrics

REM Generate the report output based on the test results
if %errorlevel% equ 0 ( 
 call :RunReportGeneratorOutput 
)

REM Launch the report
if %errorlevel% equ 0 ( 
 call :RunLaunchReport 
)
exit /b %errorlevel%

:RunOpenCoverUnitTestMetrics 
REM *** Change the filter to include/exclude parts of the solution you want 
REM *** to check for test coverage
"%OpenCoverExe%" ^
 -target:"%TestRunnerExe%" ^
 -targetargs:"\"%DllContainingTests%\"" ^
 -filter:"+[*]* -[*.Tests*]* -[*]*.*Config" ^
 -mergebyhash ^
 -skipautoprops ^
 -register:user ^
 -output:"%~dp0GeneratedReports\CoverageReport.xml"
exit /b %errorlevel%

:RunReportGeneratorOutput
"%ReportGeneratorExe%" ^
 -reports:"%~dp0\GeneratedReports\CoverageReport.xml" ^
 -targetdir:"%~dp0\GeneratedReports\ReportGenerator Output"
exit /b %errorlevel%

:RunLaunchReport
start "report" "%~dp0\GeneratedReports\ReportGenerator Output\index.htm"
exit /b %errorlevel%

使用 mstest.exe 的 MSTest 版本

@ECHO OFF

REM OpenCover-MSTest.bat

REM Run opencover against MSTest tests in your test project and show report of code coverage

REM Derivative work based on work by: 
REM  Shaun Wilde - https://nuget.net.cn/packages/OpenCover/
REM  Daniel Palme - https://nuget.net.cn/packages/ReportGenerator/
REM  Allen Conway - 
REM   http://www.allenconway.net/2015/06/using-opencover-and-reportgenerator-to.html
REM  Andrew Newton - 
REM   http://www.nootn.com.au/2014/01/code-coverage-with-opencover-example.html#.VxiNn_krLDc


SET DllContainingTests=%~dp0WebApp.Tests\bin\Debug\WebApp.Tests.dll


REM *** IMPORTANT - Change DllContainingTests variable (above) to point to the DLL 
REM ***             in your solution containing your NUnit tests
REM ***
REM ***             You may also want to change the include/exclude filters 
REM ***             (below) for OpenCover
REM ***
REM ***             This batch file should dbe placed in the root folder of your solution

REM *** Before being able to use this to generate coverage reports you will 
REM *** need the following NuGet packages
REM PM> Install-Package OpenCover
REM PM> Install-Package ReportGenerator
REM

REM *** MSTest Test Runner (VS2013, will need to change 12.0 to 14.0 for VS2015)
SET TestRunnerExe=%PROGRAMFILES(X86)%\Microsoft Visual Studio 12.0\Common7\IDE\MSTest.exe

REM Get OpenCover Executable (done this way so we dont have to change 
REM the code when the version number changes)
for /R "%~dp0packages" %%a in (*) do if /I "%%~nxa"=="OpenCover.Console.exe" SET OpenCoverExe=%%~dpnxa

REM Get Report Generator (done this way so we dont have to change the code 
REM when the version number changes)
for /R "%~dp0packages" %%a in (*) do if /I "%%~nxa"=="ReportGenerator.exe" 
     SET ReportGeneratorExe=%%~dpnxa

REM Create a 'GeneratedReports' folder if it does not exist
if not exist "%~dp0GeneratedReports" mkdir "%~dp0GeneratedReports"

REM Run the tests against the targeted output
call :RunOpenCoverUnitTestMetrics

REM Generate the report output based on the test results
if %errorlevel% equ 0 ( 
 call :RunReportGeneratorOutput 
)

REM Launch the report
if %errorlevel% equ 0 ( 
 call :RunLaunchReport 
)
exit /b %errorlevel%

:RunOpenCoverUnitTestMetrics 
REM *** Change the filter to include/exclude parts of the solution you want to 
REM *** check for test coverage
"%OpenCoverExe%" ^
 -target:"%TestRunnerExe%" ^
 -targetargs:"/noisolation /testcontainer:\"%DllContainingTests%\"" ^
 -filter:"+[*]* -[*.Tests*]* -[*]*.Global -[*]*.RouteConfig -[*]*.WebApiConfig" ^
 -mergebyhash ^
 -skipautoprops ^
 -register:user ^
 -output:"%~dp0GeneratedReports\CoverageReport.xml"
exit /b %errorlevel%

:RunReportGeneratorOutput
"%ReportGeneratorExe%" ^
 -reports:"%~dp0\GeneratedReports\CoverageReport.xml" ^
 -targetdir:"%~dp0\GeneratedReports\ReportGenerator Output"
exit /b %errorlevel%

:RunLaunchReport
start "report" "%~dp0\GeneratedReports\ReportGenerator Output\index.htm"
exit /b %errorlevel%

使用 vstest.console.exe 的 MSTest 版本

@ECHO OFF

REM OpenCover-VSTest.bat

REM Run opencover against MSTest tests in your test project and show report of code coverage

REM Derivative work based on work by: 
REM  Shaun Wilde - https://nuget.net.cn/packages/OpenCover/
REM  Daniel Palme - https://nuget.net.cn/packages/ReportGenerator/
REM  Allen Conway - 
REM   http://www.allenconway.net/2015/06/using-opencover-and-reportgenerator-to.html
REM  Andrew Newton - 
REM   http://www.nootn.com.au/2014/01/code-coverage-with-opencover-example.html#.VxiNn_krLDc


SET DllContainingTests=%~dp0WebApp.Tests\bin\Debug\WebApp.Tests.dll


REM *** IMPORTANT - Change DllContainingTests variable (above) to point to the DLL 
REM ***             in your solution containing your NUnit tests
REM ***
REM ***             You may also want to change the include/exclude filters 
REM ***             (below) for OpenCover
REM ***
REM ***             This batch file should dbe placed in the root folder of your solution

REM *** Before being able to use this to generate coverage reports you will 
REM *** need the following NuGet packages
REM PM> Install-Package OpenCover
REM PM> Install-Package ReportGenerator
REM

REM *** MSTest Test Runner (VS2013, will need to change 12.0 to 14.0 for VS2015)
SET TestRunnerExe=%PROGRAMFILES(X86)%\Microsoft Visual Studio 12.0\Common7\IDE\
CommonExtensions\Microsoft\TestWindow\vstest.console.exe

REM Get OpenCover Executable (done this way so we dont have to change 
REM the code when the version number changes)
for /R "%~dp0packages" %%a in (*) do if /I "%%~nxa"=="OpenCover.Console.exe" SET OpenCoverExe=%%~dpnxa

REM Get Report Generator (done this way so we dont have to change the code 
REM when the version number changes)
for /R "%~dp0packages" %%a in (*) do if /I "%%~nxa"=="ReportGenerator.exe" 
   SET ReportGeneratorExe=%%~dpnxa

REM Create a 'GeneratedReports' folder if it does not exist
if not exist "%~dp0GeneratedReports" mkdir "%~dp0GeneratedReports"

REM Run the tests against the targeted output
call :RunOpenCoverUnitTestMetrics

REM Generate the report output based on the test results
if %errorlevel% equ 0 ( 
 call :RunReportGeneratorOutput 
)

REM Launch the report
if %errorlevel% equ 0 ( 
 call :RunLaunchReport 
)
exit /b %errorlevel%

:RunOpenCoverUnitTestMetrics 
REM *** Change the filter to include/exclude parts of the solution you want to 
REM *** check for test coverage
"%OpenCoverExe%" ^
 -target:"%TestRunnerExe%" ^
 -targetargs:"\"%DllContainingTests%\"" ^
 -filter:"+[*]* -[*.Tests*]* -[*]*.Global -[*]*.RouteConfig -[*]*.WebApiConfig" ^
 -mergebyhash ^
 -skipautoprops ^
 -register:user ^
 -output:"%~dp0GeneratedReports\CoverageReport.xml"
exit /b %errorlevel%

:RunReportGeneratorOutput
"%ReportGeneratorExe%" ^
 -reports:"%~dp0\GeneratedReports\CoverageReport.xml" ^
 -targetdir:"%~dp0\GeneratedReports\ReportGenerator Output"
exit /b %errorlevel%

:RunLaunchReport
start "report" "%~dp0\GeneratedReports\ReportGenerator Output\index.htm"
exit /b %errorlevel%
© . All rights reserved.