分享好友 编程语言首页 频道列表

[C#]使用 AltCover 获得代码覆盖率 - E2E Test 和 Unit Test

C#教程  2023-02-09 09:590

背景

在 CI/CD 流程当中,测试是 CI 中很重要的部分。跟开发人员关系最大的就是单元测试,单元测试编写完成之后,我们可以使用 IDE 或者 dot cover 等工具获得单元测试对于业务代码的覆盖率。不过我们需要一个独立的 CLI 工具,这样我们才能够在 Jenkins 的 CI 流程集成。

端到端测试(End to End Test) 是在 Preview 版本部署完成之后,需要对 Preview 版本进行自动化测试,测试完成之后输出对应的覆盖率报告。根据代码覆盖率报告,我们可以了解 QA 编写的测试用例,是否完整覆盖了所有分支流程。

实现

工具选型

单元测试框架我选择的是 xUnit,它对于 .NET Core 与 .NET Framework 的支持都不错,并且也提供了独立于 IDE 之外的 Console Runner,可以很方便地同 Jenkins 集成。

覆盖率收集工具我选择的是 AltCover,因为它能够收集到部署在 IIS 的 ASP.NET MVC 程序覆盖率指标,这样我们就能够对一些 .NET Framework 老项目进行测试覆盖率汇总计算。AltCover 可以生成多种格式的覆盖率报告,默认格式是 OpenCover。

AltCover 生成的覆盖率报告并不是直接可读的,我们需要一个工具来生成人类可以阅读理解的报告。这里我选择的是 ReportGenerator ,它支持 OpenCover 格式的覆盖率报告,并生成对应的 HTML 文件方便查看。

.NET Framework 集成

我建立了一个简单的 ASP.NET Web API 项目(.NET Framework 4.8),提供了一个 ApiTestController 控制器,暴露了一个 HTTP POST 方法 CreateOrder,内部逻辑比较简单,就是创建了一个新的 OrderAggregateRoot 实例,然后返回了一个 Success 文本。

/// <summary>
/// ApiTestController.
/// </summary>
[Route("api/test")]
public class ApiTestController : ApiController
{
    private readonly IOrderRepository _orderRepository;

    /// <summary>
    /// <see cref="ApiTestController"/>.
    /// </summary>
    public ApiTestController()
    {
        _orderRepository = new FakeOrderRepository();
    }

    /// <summary>
    /// CreateOrder.
    /// </summary>
    [HttpPost]
    [Route("api/test/create")]
    public IHttpActionResult CreateOrder(CreateOrderInputDto input)
    {
        var newOrder = new OrderAggregateRoot(null, input.Items.Select(x => new OrderItem(x.Price, x.Number)).ToList());
        _orderRepository.InsertAsync(newOrder);

        return Ok("Success");
    }
}
单元测试覆盖率报告

单元测试项目建立比较简单,我建立了一个 AltCoverTestUnitTest 项目,并且添加了 ASP.NET Web API 项目的引用,在内部添加了 AltCover 与 xUnit 相关包的引用。

AltCoverxUnit Console Runner 包安装完成之后,对于 .NET Framework 项目来说,会在对应的解决方案目录下面有一个 packages 文件夹,在里面找到 packages\altcover.8.3.838\tools\net472 目录,在这个目录里面有一个 AltCover.exe 的可执行文件,这个就是 AltCover 的 CLI 工具。

xUnit Console Runner 对应的 CLI 工具则在 packages\xunit.runner.console.2.4.2\tools\net472 中,根据自己的平台使用 xunit.console.exe 或者是 xunit.console.x86.exe 均可。

随后我们直接使用 MSBuild 命令/IDE 重新编译一下单元测试项目,转到对应的 bin\Debug 目录。在 .bin\Debug 目录中,执行以下命令,将会生成一个新的文件夹,里面会包含修改后的 DLL 文件。

这里 CLI 工具的路径,取决于你的实际路径,就在你解决方案对应的 pacakges 里面。

D:\CoverageTool\AltCoverTestRESFul\packages\altcover.8.3.838\tools\net472\AltCover.exe /o=./__UnitTestWithAltCover -s=Adapter -s=Shouldly -s=Microsoft -t="Shouldly." -s="AltCover.Monitor" -t="System." -s=xunit -e="EmptyFiles" -e=Tests -r=".\_Reports\UnitTestWithAltCover.xml"

这里我解释以下命令,其中 /o 参数指的是修改后 DLL 的输出目录,这里我指定的当前目录下的 __UnitTestWithAltCover 文件夹。-s 参数指的是需要排除的程序集名称,支持通配符与正则表达式。-e 的作用与 -s 类似,具体可以查看 Usage ,最有一个 -r 参数指定报告的输出路径,也就是 OpenCover 格式的 XML 文件输出路径。

为什么需要排除?因为我们的项目可能会引用很多第三方库,这个时候我们为了减少报告的噪音,你也不想在报告里面看到一堆 Microsoft 的代码吧,所以需要手动排除掉这些程序集。

为什么叫做修改后,因为执行命令后,AltCover 会重新生成一个新的 DLL,这个新的 DLL 反编译后可以看到会在每行代码插入 Instance.Visit() 来记录代码的访问路径。

命令执行完成之后,可以看到对应的覆盖率文件生成了,但是这里面覆盖率是 0,因为我们的单元测试还没开始跑。

随后我们执行下面的命令,使用 xUnit Console Runner 运行我们的单元测试项目。

D:\CoverageTool\AltCoverTestRESFul\packages\xunit.runner.console.2.4.2\tools\net47\xunit.console.exe ./__UnitTestWithAltCover/AltCoverTestUnitTest.dll -xml "./_Reports/UnitTestWithAltCoverReport.xml"

第一个参数是需要执行的单元测试 DLL,第二个参数 -xml 说明我们具体的执行结果输出路径,这里我们也输出到了 _Reports 文件夹,这个时候我们就有两个 XML 文件了。

切换到 _Reports 文件夹,打开终端,我们这个时候需要使用 reportgeneator 工具,根据这两个 XML 文件生成人类可读的 HTML 报告。

reportgenerator "-reports:UnitTestWithAltCover.xml;UnitTestWithAltCoverReport.xml" "-targetdir:coveragereport" -reporttypes:Html

上述命令的意思就是根据这两个 xml ,在当前目录的 coveragereport 文件夹,生成一个新的 HTML 报告。

关于 reportgenerator 的安装,可以参考官方的 线上工具,它会根据你选择的情况返回适合的安装命令。我自己直接使用的 dotnet tool install --global dotnet-reportgenerator-globaltool 命令进行的安装。

最后的效果:

IIS Web API 覆盖率报告

我们建立一个新的 IIS 站点,并将对应的 DLL 文件放到对应的目录下面。首先暂停对应 IIS 站点,并且停止对应的应用程序池。

随后执行以下命令,将会修改对应的 DLL 文件,以便后续进行覆盖率跟踪,原理跟上面的一样。

D:\CoverageTool\AltCoverTestRESFul\packages\altcover.8.3.838\tools\net472\AltCover.exe --save --inplace -i "D:\TempFiles\IIS\AltCoverTestWebSite\bin" -s=Adapter -s=Shouldly -s="Antlr3.Runtime" -s=Microsoft -t="Shouldly." -s="AltCover.Monitor" -t="System." -s=xunit -e="EmptyFiles" -e=Tests

执行完上述命令以后,将会在终端执行目录下生成两个文件,一个是 coverage.xml ,一个是 coverage.xml.acv 文件,后者是 AltCover 的控制文件,用于记录程序在运行过程中的执行代码路径。

随后启动对应的 IIS 站点与应用程序池,执行自动化测试,或者调用对应的接口。

如果需要停止测试了,需要将对应的 IIS 站点与应用程序池停止,只有停止了,AltCover 才会将已执行代码路径信息写入到对应的控制文件当中。

可以看到 coverage.xml.0.acv 文件已经有内容了,但是我们还需要将控制文件的信息合并到 coverage.xml 当中,这个时候需要执行第二个命令进行合并。

D:\CoverageTool\AltCoverTestRESFul\packages\altcover.8.3.838\tools\net472\AltCover.exe runner --collect -r "D:\TempFiles\IIS\AltCoverTestWebSite\bin"

output:

... D:\TempFiles\IIS\AltCoverTestWebSite\coverage.xml.0.acv (380b)
308 visits recorded in 00:00:00.0171096 (18,002 visits/sec)
A total of 308 visits recorded
Coverage statistics flushing took 0.04 seconds
Visited Classes 10 of 12 (83.33)
Visited Methods 14 of 22 (63.64)
Visited Points 65 of 93 (69.89)
Visited Branches 4 of 30 (13.33)
Maximum CRAP score 30
==== Alternative Results (includes all methods including those without corresponding source) ====
Alternative Visited Classes 13 of 15 (86.67)
Alternative Visited Methods 20 of 30 (66.67)
Alternative maximum CRAP score 30

可以看到控制台的输出已经有 308 visits recorded,随后我们使用 reportgenerator 工具生成 HTML 报告。

.NET Core 集成

单元测试覆盖率报告

集成方法同 .NET Framework 一样。

ASP .NET Core 覆盖率报告

这里我使用的是 dotnet tool 安装的 altcover 命令,安装命令如下,前提是你得有 .NET Core 运行时。

dotnet tool install --global altcover.global --version

随后编译对应的 ASP.NET Core 项目,并且在对应的 bin\Debug 目录打开终端,执行以下命令进行准备工作。

altcover /o=./__UnitTestWithAltCover -i .

随后使用 altcover runner 命令启动对应的程序。

altcover runner -x .\__UnitTestWithAltCover\AltCoverTestRESTFulCore.exe -r .\__UnitTestWithAltCover\

如果已经完成了测试,请终止掉对应的进程,否则 AltCover 不会将数据写入到 XML 文件,最后也使用 reportgenerator 工具生成 HTML 报告。

总结

如果你的项目是基于 .NET Core ,那么可以直接选择微软主推的 coverletAltCover 对于 .NET Framework、Mono、.NET Core 项目都有不错的支持,并且作者维护得也很勤快。

查看更多关于【C#教程】的文章

展开全文
相关推荐
反对 0
举报 0
评论 0
图文资讯
热门推荐
优选好物
更多热点专题
更多推荐文章
Windows API Reference for C#, VB.NET
不错的.net 下用API的参考站点地址在:http://www.webtropy.com/articles/Win32-API-DllImport-art9.asp 下面摘抄分类,便于大家直接就拿来用: File, Memory, Process, Threading, Time, Console, and Comm control(kernel32.dll) _hread_hwrite_lclose_lcr

0评论2023-03-16877

一个基于API的VB.net串口通讯类 vbnet串口通信如何编写
VB.net的串口通讯支持总是让人觉得有所不足,在使用VB6的MsComm32.ocx时,很多人都会在VB.net的开发中觉得很困扰。    这里讲述的VB.net串口通讯类使用native代码,并且它是通API调用实现的,你会发现VB.net的串口通讯就是这么简单。    在说明如何使

0评论2023-02-12420

[VB][ASP.NET]FileUpload控件「批次上传 / 多档案同时上传」的范例
FileUpload控件「批次上传 / 多档案同时上传」的范例 (VB语法) http://www.dotblogs.com.tw/mis2000lab/archive/2008/05/14/3986.aspx    FileUpload控件真的简单好用,不使用它来作批次上传,却要改用别的方法,实在不聪明。要用就一次用到底,公开File

0评论2023-02-10976

VB.NET调用IE,并且等待
            Dim p As New Process            '获得URL            aURL = GetURL()            '获得IE路径            p.StartInfo.FileName = System.Environment.GetFolderPath( _ 

0评论2023-02-09939

VB.NET withevent 自定义事件处理
Module Module1    Private WithEvents aemp As part2    Sub Main()        Dim chen As New part2("chen lili", 20000)        aemp = chen        Console.WriteLine(chen.Name" prevouis salary is "chen.Salary)      

0评论2023-02-09571

ASP.NET操作Cookies的问题(Bug or Not)
以下存和取都是在不同的页面中,如果是在同一个页面也没必要用cookies了。 Test1: 给Cookies赋值: const string AAA="aaa"; Response.Cookies[AAA].Value = "111;222;333"; 取值: string value = Request.Cookies[AAA].Value; // value为111 Test2: 给Cooki

0评论2023-02-09888

Asp.Net Core 自定义验证属性
  很多时候,在模型上的验证需要自己定义一些特定于我们需求的验证属性。所以这一篇我们就来介绍一下怎么自定义验证属性。  我们来实现一个验证邮箱域名的自定义验证属性,当然,最重要的是需要定义一个继承自ValidationAttribute的类,然后在实现其IsVal

0评论2023-02-09525

Asp.Net 之 枚举类型的下拉列表绑定
有这样一个学科枚举类型:/// 学科 /// /summary public enum Subject {None = 0,[Description("语文")]Chinese = 1,[Description("数学")]Mathematics = 2,[Description("英语")]English = 3,[Description("政治")]Politics = 4,[Description("物理&qu

0评论2023-02-09819

[ASP.NET笔记] 1.Web基础知识
     1:http协议:     2:web服务器:     3:静态网页的概念     4:动态网页的概念       http协议:http(hypertext transfer protocol) 即超文本传输协议,这个协议是在internet上进行信息传送的协议任何网页之间要相互沟通,必须要尊循

0评论2023-02-09663

ASP.NET邮件发送 .net 发送邮件
  今天做了个ASP.NET做发送邮件功能,发现QQ邮箱好奇怪,当你用QQ邮箱做服务器的时候什么邮件都发送不出去(QQ邮箱除外)。而且爆出这样的错误:"邮箱不可用。 服务器响应为: Error: content rejected.http://mail.qq.com/zh_CN/help/content/rejectedmail.ht

0评论2023-02-09455

由ASP.NET Core根据路径下载文件异常引发的探究
前言    最近在开发新的项目,使用的是ASP.NET Core6.0版本的框架。由于项目中存在文件下载功能,没有使用类似MinIO或OSS之类的分布式文件系统,而是下载本地文件,也就是根据本地文件路径进行下载。这其中遇到了一个问题,是关于如何提供文件路径的,通

0评论2023-02-09562

ASP.NET 后台接收前台POST过来的json数据方法
 ASP.NET前后台交互之JSON数据 https://www.cnblogs.com/ensleep/p/3319756.html

0评论2023-02-09501

Asp.Net 常用工具类之加密——对称加密DES算法(2)
     又到周末,下午博客园看了两篇文章,关于老跳和老赵的程序员生涯,不禁感叹漫漫程序路,何去何从兮!  转眼毕业的第三个年头,去过苏州,跑过上海,从一开始的凌云壮志,去年背起行囊默默回到了长沙准备买房,也想有个家(毕竟年级不小了),有盼

0评论2023-02-09995

更多推荐