背景

在 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#]使用 AltCover 获得代码覆盖率 - E2E Test 和 Unit Test的更多相关文章

  1. angular(转)

    学习之前可以看看 知乎上讨论angularjs优缺点 帮你选择框架的网站 同类主流框架对比 教程 angularjs在慕课网 angularjs在51cto angularjs在图灵社区 社区 Ang ...

  2. 基于vue2.0的在线电影APP,

    基于vue2.0构建的在线电影网[film],webpack + vue + vuex + vue-loader + keepAlive + muse-ui + cordova 全家桶,cordova ...

  3. Webpack单元测试,e2e测试

    此篇文章是续 webpack多入口文件.热更新等体验,主要说明单元测试与e2e测试的基本配置以及相关应用. 一.单元测试 实现单元测试框架的搭建.es6语法的应用.以及测试覆盖率的引入. 1. 需要安 ...

  4. 使用Angular CLI进行单元测试和E2E测试

    第一篇文章是: "使用angular cli生成angular5项目" : http://www.cnblogs.com/cgzl/p/8594571.html 第二篇文章是: & ...

  5. UT, FT ,E2E 测试的意思

    前端实现自动化就要借助到unit和e2e端到端测试了 一.unit测试(FT 就是Fucntion Test 功能测试,  注意不是: funciton函数 ...fucntion功能   不一样哦  ...

  6. 聊聊Go代码覆盖率技术与最佳实践

    "聊点干货" 覆盖率技术基础 截止到Go1.15.2以前,关于覆盖率技术底层实现,以下知识点您应该知道: go语言采用的是插桩源码的形式,而不是待二进制执行时再去设置breakpo ...

  7. Python 代码覆盖率统计工具 coverage.py

    coverage.py是一个用来统计python程序代码覆盖率的工具.它使用起来非常简单,并且支持最终生成界面友好的html报告.在最新版本中,还提供了分支覆盖的功能. 官方网站: http://ne ...

  8. 基于Grunt&Mocha 搭建Nodejs自动化单元测试框架(含代码覆盖率统计)

    Introduction Grunt 是一个基于任务的JavaScript 世界的构建工具 Mocha 是具有丰富特性的 JavaScript 测试框架,可以运行在 Node.js 和浏览器中,使得异 ...

  9. angular 调试 js (分 karms protractor / test e2e unit )

    首页订阅 Protractor端到端的AngularJS测试框架教程 2014年01月18日 分类:教程, JavaScript, AngularJS Protractor是一个建立在WebDrive ...

随机推荐

  1. Change Buffer 只适用于非唯一索引页?错

    最近在网上看到一些文章里说:"change buffer 只适用于非唯一索引页."其实这个观点是错的,先来看看官方文档对 change buffer 的介绍: 文档地址:https ...

  2. sort是不稳定排序

    今天才知道sort是不稳定的,WA了一个点. sort()排序不是稳定排序,sort是主要用到了快速排序(平均时间复杂度为O(nlogn)),还结合了插入排序(时间复杂度为O(n2))和堆排序(时间复 ...

  3. docker引起服务器磁盘爆满

    服务器异常 又是开开心心打开我心爱的服务器一天: 吔!这是嘛啊?我的服务器域名访问不了了,一直转圈圈超时了,好,打开ssh远程看看,吔!!!还是访问不了,宕机了?怀着一颗憋大便的心情打开了阿里云控制面 ...

  4. Docker容器编译安装Nginx

    Docker容器编译安装Nginx,最简单的Nginx配置. 创建容器&进入容器 宿主机2080映射容器的80端口 [root@localhost ~]# docker run -i -d - ...

  5. BUUCTF-假如给我三天光明

    假如给我三天光明 打开压缩包可以看到一个海报,下方有盲文显示,通过对照表得知 盲文翻译为kmdonowg 通过盲文翻译得到的字符串解压压缩包得到一个音频文件 使用Audacity打开,看样子应该是摩斯 ...

  6. Redis系列2:数据持久化提高可用性

    1 介绍 从上一篇的 <深刻理解高性能Redis的本质> 中可以知道, 我们经常在数据库层上加一层缓存(如Redis),来保证数据的访问效率. 这样性能确实也有了大幅度的提升,但是本身Re ...

  7. HashMap1.8常见面试问题

    1.hashmap转红黑树的时机: for (int binCount = 0; ; ++binCount) { if ((e = p.next) == null) { p.next = newNod ...

  8. UiPath条件判断活动Flow Decision的介绍与使用

    一.Flow Decision介绍 FlowDecision节点是一个条件节点,它根据指定条件是否成立来控制流程的两个分支. 当条件为True时,流程执行一个分支 当条件为False时,流程执行另外一 ...

  9. 我用Python做了一个咖啡馆数据分析

    在做案例前,我还想回答大家一个疑问,就是excel做数据分析可以实现Python一样的效果,那用Python的意义在哪呢? 经过这段时间学习理解,我的回答是: (https://jq.qq.com/? ...

  10. Python列表解析式的正确使用方式(一)

    先来逼逼两句: Python 是一种极其多样化和强大的编程语言!当需要解决一个问题时,它有着不同的方法.在本文中,将会展示列表解析式 (List Comprehension).我们将讨论如何使用它?什 ...