好代码是管出来的——.Net Core集成测试与数据驱动测试

软件的单元测试关注是的软件最小可执行单元是否能够正常执行,但是软件是由一个个最小执行单元组成的集合体,单元与单元之间存在着种种依赖或联系,所以在软件开发时仅仅确保最小单元的正确往往是不够的,为了保证软件能够正确运行,单元与单元之间的集成测试是非常必要。
  另外上一篇文章只是介绍了如何使用xUnit.net对.Net Core程序进行简单(无参)的单元测试以及计算代码的覆盖率,但是在实际的测试工作中,往往会通过语句覆盖、条件/分支覆盖(白盒)方式以及等价类、边界值等(黑盒)方式来设计测试用例,这些用例的测试的关键点在于传入测试方法的参数是不同的,如果使用无参测试方法那么针对不同的测试用例就需要编写大量的测试方法,这是不现实的。
  本文将从以下几个方面,在单元测试的基础上介绍如何完成数据驱动测试以及代码依赖的集成测试:

  • 集成测试简介

  • 使用xUnit.Net实现简单的数据库集成测试

  • 可回归的数据库集成测试

  • 数据驱动测试简介

  • 基于xUnit.Net的数据驱动测试

    • Theory&InlineData

    • 基于excel的数据驱动测试

  • 小结

集成测试简介

  集成测试简单的理解就是在单元测试的基础上,将各个单元根据其依赖关系集成起来,检查代码是否能够正确运行,集成测试根据软件开发方式的不同或者软件架构不同也有不同的集成方式,比如面向过程的设计方式和面向对象设计方式、单体架构以及微服务分布式架构等等。
  本文涉及到的仅仅是面向对象编程中类与类之间依赖的集成测试。

使用xUnit.Net实现简单的数据库集成测试

  数据库是大部分软件系统不可缺少的组件,所以在集成测试时与数据库集成是一种常见的测试场景,下面就开始介绍如何通过xUnit.Net来测试。
  1. 编写被测试代码:
  在被测试项目中引入EFCore以及相关组件:

  640?wx_fmt=png

  添加DBContext以及相应的数据操作代码:

  640?wx_fmt=png

  注:此处使用LocalDB作为数据库完成测试,如果使用SQL Server修改连接字符串即可。

  640?wx_fmt=png

  用户仓储中实现了用户添加以及根据姓名查询的方法。
  注:完成代码编写后,需要将实体代码迁移到数据库,先通过Add-Migration添加迁移代码,然后通过update-database命令将数据更新到数据库,迁移方法可参考:https://docs.microsoft.com/en-us/ef/core/get-started/full-dotnet/new-db
  2.编写测试代码:

  640?wx_fmt=png

  测试代码也非常简单,就是创建一个SQLServer的用户仓储实例,然后通过构造的方式将其注入到UserManager类型中使用,后续UserManager的创建、查询用户的方法将通过该仓储实现。
  3.测试运行结果:

  640?wx_fmt=png

可回归的数据库集成测试

  这里的回归指的是回归测试,回归测试是指当修改了旧的代码后需要重新对旧代码进行测试确认此次修改没有影响到已有代码。一般来说使用xUnit.Net实现的测试均是可回归的,因为测试代码不变,且测试代码可以重复执行,另外测试代码也被代码版本管理工具管理,当修改代码后重新执行所有测试方法即可。
  但是与数据库相关的测试又有所区别,数据库是数据持久化工具,对数据的每一次操作都会被持久化,假设有两个测试用例,第一是添加一条数据,第二是查询这条数据的数量是否为1,那么这两个测试在第一次运行的时候是没有问题的,但是再次运行时第一个用例可能主键冲突无法被添加,或者添加成功后第二个用例查询结果为2,导致测试失败,这样的测试视为不可回归。
  下面就介绍如何使用xUnit.Net实现数据库集成的回归测试:

使用构造方法初始化数据库

  要实现数据库集成测试的可回归性,其实最主要的问题在于每次执行完单元测试后数据库的状态都是不同的,那么解决这个问题在每次执行测试前将数据库初始化是否就可以解决了呢?
  看下面代码:

  640?wx_fmt=png

  首先为测试类添加构造方法,在构造方法中初始化数据库。

  640?wx_fmt=png

  然后在测试方法中添加用户数量测试断言,当添加完成用户后,应该一共存在1个用户。
  执行测试方法:

  640?wx_fmt=png

  无论执行多少次测试都是通过的,这意味着每次添加用户后用户数量均为1,这样就达到了测试的可回归性。
  但是真实的开发过程中,不可能只有一个测试类型,而且如果为每一个测试类型都添加初始化数据库的代码,那么这些单元测试将会执行的非常慢(数据库的初始化非常耗时),那么要如何解决这个问题?

使用Fixture共享测试上下文

  Fixture是xUnit.Net中的一项特性,它可以用来共享测试上下文,Fixture可以译为固定装置,换句话说就是把一个内容固定住,使该内容可以在被指定的范围内使用。xUnit.Net中Fixture有两种类型,分别是ClassFixture和CollectionFixture,它们对应的是在一个测试类型里面共享和一个测试类型集合中共享上下文,Fixture的作用有很多,下面将介绍如何使用Fixture来共享数据库被初始化这一状态(不需要重复初始化):
  1. 创建一个Fixture类型:
  Fixture实际上是一个普通的C#类型,唯一需要注意的是它使用构造方法初始化数据、使用Dispose来释放或者清理数据,简单的一个Fixture类型如下:

  640?wx_fmt=png

  2. 为单个类型使用ClassFixture:

  640?wx_fmt=png

  从代码中可以看到通过构造方法初始化的代码已经被注释了,实现IClassFixture接口后,再次执行测试方法,可以看到测试仍然是可回归的。
  3. 为多个类型使用ICollectionFixture:
  首先需要在DatabaseFixture的基础上添加一个实现ICollectionFixture的类型:

  640?wx_fmt=png

  两个要点分别是需要使用CollectionDefinition特性,然后类型需要实现ICollectionFixture<T>接口。
  在测试类型上通过Collection特性,指定之前定义的Collection名称来应用该CollectionFixture:

  640?wx_fmt=png

  然后多次执行测试方法,可以发现测试仍然是可回归的:

  640?wx_fmt=png

  注:在共享测试上下数据时(包括共享数据库数据),可能会因为测试方法执行顺序导致测试失败,但是xUnit.Net中没有提供按顺序执行实现方式,默认是按照方法命名,如果需要按照一定顺序执行测试,可参考官方的例子:https://github.com/xunit/samples.xunit/tree/master/TestOrderExamples

测试数据的管理与初始化

  涉及到数据库的测试,很可能在测试之前数据库就会存在一些已有的测试数据,使用xUnit.Net来编写测试代码时,可以将测试数据的初始化放到Fixture类型中,但是要如何对这些数据进行管理呢?一般来说使用SQL脚本来管理数据库的测试数据是一种不错的方式,因为这样测试数据与代码解耦,维护数据时仅需要维护SQL脚本文件即可。
  下面就介绍一下如何在xUnit.Net中使用SQL脚本文件管理以及初始化数据:
  1.创建一个SQL脚本:

  640?wx_fmt=png

  注:需要将文件的“复制到输出目录”设置为“总是复制”或者“有更新复制”:

  640?wx_fmt=png

  2.在Fixture类型初始化数据库时,执行SQL脚本初始化数据:
  下面代码首先去Data目录下查找.sql的所有文件,然后依次执行这些SQL脚本。

  640?wx_fmt=png

  3.修改测试代码(因为脚本添加了2条数据,所以期望值应该是3条):

  640?wx_fmt=png

  4.执行测试:

  640?wx_fmt=png  

  测试成功。

数据驱动测试简介

  文章最开始提到过,不管是白盒的覆盖测试还是黑盒的边界/等价测试,它们最直接的体现就是“参数”,传入被测试方法的参数。而这些参数实际上就是“测试用例”,为每一个测试用例编写一个测试方法是不合理的,所以需要一种方法通过变换参数来完成测试,并且尽可能的重用测试代码。这就是数据驱动测试。

基于xUnit.Net的数据驱动测试

Theory&InlineData

  Theory和InlineData是xUnit.Net中提供的数据驱动(参数化)测试的功能特性,下面是一个theory以及InlineData的应用示例:

  640?wx_fmt=png

  运行结果:

  640?wx_fmt=png 

  通过InlineData就可以轻易的将测试用例的数据应用到测试方法上,并完成期望的测试。但是当添加新的测试用例时就需要对代码文件进行修改,测试用例放置在代码中管理也不是非常方便,有没有一种可以独立管理测试用例数据的方法呢?

基于excel的数据驱动测试

  xUnit.Net没有提供内置的Excel数据加载功能,但是它的拓展性很好,可以通过实现DataAttribute实现一个Theory的数据源提供器:

  640?wx_fmt=jpeg

  1. 实现DataAttribute抽象类,实现Excel的Theory数据提供器:
  下面是实现Excel数据加载的核心方法:

  640?wx_fmt=png

  640?wx_fmt=png

  640?wx_fmt=png

  以上方法需要注意以下几点:

  • 两个主体:Excel文件名称和测试的方法的MethodInfo,前者用于读取Excel文件,后者用来获取参数信息。

  • 通过MethodInfo获取测试方法的参数列表包括参数类型。

  • 读取Excel数据并于测试方法的参数列表匹配,简单来说就是Excel中每一行的数据就是对应测试方法的参数,有多少行数据测试方法就会被执行多少次。

  • 当Excel中数据读取为double或者float但是测试方法需要int时,需要进行转换。

  注:此处使用的Excel文件读取组件为:https://github.com/ExcelDataReader/ExcelDataReader

  DataAttribute完整代码见:https://github.com/yqszt/xUnitTestDemo/blob/master/XUnitTestProject/ExcelDataAttribute.cs

  2.使用ExcelDataAttribute:

  640?wx_fmt=png

  3. 在AdditionTestCase.xls中添加测试用例数据:

  640?wx_fmt=png

  注:需要将AdditionTestCase.xls的复制到输出目录属性设置为“总是复制”或“复制新文件”。

  4.执行测试方法:

  640?wx_fmt=png

  测试成功。

小结

  本文主要介绍了.Net Core使用xUnit.Net实现了与数据的集成测试并通过Fixture的方式实现了数据库的初始化,保证了测试的可回归性。另外还介绍了如何使用xUnit.Net来实现数据驱动测试,数据驱动测试可以简单地通过添加用例数据的方式来提高测试质量,还可以便捷的对测试用例进行管理。

本文示例代码:https://github.com/yqszt/xUnitTestDemo

参考:

  https://en.wikipedia.org/wiki/Integration_testing
  https://en.wikipedia.org/wiki/Data-driven_testing
  https://xunit.github.io/docs/getting-started-dotnet-core#write-first-theory
  http://dotnetliberty.com/index.php/2015/12/31/fast-asp-net-5-integration-testing-with-xunit/
  https://github.com/MisterJames/GenFu
  http://ikeptwalking.com/writing-data-driven-tests-using-xunit/
  https://wandering.life/data-driven-testing-xunit-vs2017/
  https://github.com/ExcelDataReader/ExcelDataReader
  http://xunitpatterns.com/Testing%20With%20Databases.html
  https://xunit.github.io/docs/shared-context

相关文章:

原文地址https://www.cnblogs.com/selimsong/p/9306221.html 

.NET社区新闻,深度好文,欢迎访问公众号文章汇总 http://www.csharpkit.com

640?wx_fmt=jpeg


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/320804.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Full_of_Boys训练7总结

题目来源&#xff1a;2016沈阳区域赛 C.Recursive sequence 矩阵快速幂&#xff0c;思路来自oldz #include <bits/stdc.h> typedef unsigned long long ll; const ll mod2147493647; using namespace std; ll A[7][7]{{1,0,0,0,0,0,0},{1,1,0,0,0,0,0},{1,2,1,0,0,0,0},{…

CF961G-Partitions【斯特林数】

正题 题目链接:https://www.luogu.com.cn/problem/CF961G 题目大意 nnn个物品分成kkk个组&#xff0c;每个物品权值为wiw_iwi​。一个子集SSS的权值为∣S∣∑x∈Swx|S|\sum_{x\in S}w_x∣S∣∑x∈S​wx​。 求所有划分方法的权值和。 解题思路 考虑对于每个数wiw_iwi​的贡献…

【高精】【快速幂】穿越丛林(ssl 2314)

穿越丛林 ssl 2314 题目大意&#xff1a; 求2n2^n2n 原题&#xff1a; 题目描述&#xff1a; ljj 是一位富有冒险心又很喜欢研究数学的孩纸&#xff0c;有一天&#xff0c;他到一个丛林冒险&#xff0c;这里的树长有像0、4、6、8、9这样形状的洞&#xff0c;他要想穿过丛…

谈谈surging引擎的tcp、http、ws协议和如何容器化部署

1、前言分布式已经成为了当前最热门的话题&#xff0c;分布式框架也百花齐放&#xff0c;群雄逐鹿。从中心化服务治理框架&#xff0c;到去中心化分布式服务框架&#xff0c;再到分布式微服务引擎&#xff0c;这都是通过技术不断积累改进而形成的结果。esb,网关&#xff0c;ngi…

2018陕西省赛K题[watermelon_planting]

题意:有一个序列a[]&#xff0c;描述的是另一个序列ans[]每个位置单位时间的增量。每个单位时间每个位置都会增加一个单位对应增量。时间总长m&#xff0c;每个单位时间包含有两种操作中的一个&#xff1a;1.询问ans[]在[l,r]区间的和&#xff1b;2.修改&#xff1a;a[]在[l,r]…

【并查集】银河英雄传说 (luogu 1196/ssl 1225)

银河英雄传说 luogu 1196 ssl 1225 题目大意&#xff1a; 有n列船&#xff0c;每列一开始有一艘船&#xff0c;可以将某一艘船所在的列所有船接到另外一列&#xff0c;然后会问某两艘船是否在一列&#xff0c;如果在那中间有多少艘船 原题&#xff1a; 题目描述 公元五八…

P4827-[国家集训队]Crash 的文明世界【树形dp,换根法,斯特林数】

正题 题目链接:https://www.luogu.com.cn/problem/P4827 题目大意 一颗nnn个点的树&#xff0c;定义dis(i,j)dis(i,j)dis(i,j)表示树上i,ji,ji,j两点的距离&#xff0c;对于每个iii求∑j1ndis(i,j)m\sum_{j1}^ndis(i,j)^mj1∑n​dis(i,j)m 解题思路 根据斯特林数的性质我们有…

Helm - Kubernetes服务编排的利器

Helm介绍在Kubernetes中部署容器云应用&#xff08;容器或微服务编排&#xff09;是一项有挑战性的工作&#xff0c;Helm就是为了简化在Kubernetes中安装部署容器云应用的一个客户端工具。通过Helm能够帮助开发者定义、安装和升级Kubernetes中的容器云应用。同时&#xff0c;也…

【DP】优美三角剖分

优美三角剖分 题目大意&#xff1a; 有一个图形&#xff0c;通过组合可以变成新的图形&#xff0c;现在要求第n个图形 原题&#xff1a; 题目描述 小X同学为了搞好和小C同学的关系&#xff0c;特意寻找了一些优美的图像作为礼物。 这是一些由无穷无尽三角形组成的极为优美…

Loj#114-k大异或和【线性基】

正题 题目链接:https://loj.ac/problem/114 题目大意 nnn个数&#xff0c;求所有非空子集的kkk小异或和。 解题思路 我们考虑处理一下线性基&#xff0c;我们知道对于did_idi​是一定在第iii位为111。 对于一个i>ji>ji>j且did_idi​的第jjj位为111时&#xff0c;我…

.NET Core微服务之基于MassTransit实现数据最终一致性(Part 1)

一、预备知识&#xff1a;数据一致性关于数据一致性的文章&#xff0c;园子里已经有很多了&#xff0c;如果你还不了解&#xff0c;那么可以通过以下的几篇文章去快速地了解了解&#xff0c;有个感性认识即可。&#xff08;1&#xff09;左正&#xff0c;《保证分布式系统数据一…

2017-2018 ACM-ICPC Nordic Collegiate Programming Contest (NCPC 2017)

D.Distinctive Character 看到样例&#xff0c;第一个反应贪心。先写了个按这一位1和0的数目多少&#xff0c;确定0还是1的东西。感觉不够真&#xff0c;又写了个尽量加到相似的比较小的串上的贪心。在和前边的那个组合一下&#xff0c;换了换顺序。。。好吧就过了13组样例。。…

【二分】买礼物的艰辛

买礼物的艰辛 题目大意&#xff1a; 有n个物品的价格&#xff0c;还有m个人&#xff0c;m个人中的每个人都要购买一定的连续物品&#xff0c;问买下n个物品&#xff0c;花钱最大的人最少花多少钱 原题&#xff1a; 题目描述 小X同学给小C同学选了N件礼物&#xff0c;决定顺…

P4449-于神之怒加强版【莫比乌斯反演】

正题 题目链接:https://www.luogu.com.cn/problem/P4449 题目大意 TTT组询问给出n,mn,mn,m求∑i1n∑j1mgcd(i,j)k\sum_{i1}^n\sum_{j1}^mgcd(i,j)^ki1∑n​j1∑m​gcd(i,j)k 解题思路 ∑i1n∑j1mgcd(i,j)k\sum_{i1}^n\sum_{j1}^mgcd(i,j)^ki1∑n​j1∑m​gcd(i,j)k ∑d1ndk∑i…

Asp.NetCoreWebApi图片上传接口(二)集成IdentityServer4授权访问(附源码)

写在前面本文地址&#xff1a;http://www.cnblogs.com/yilezhu/p/9315644.html作者&#xff1a;yilezhu上一篇关于Asp.Net Core Web Api图片上传的文章使用的是mongoDB进行图片的存储&#xff0c;文章发布后&#xff0c;张队就来了一句&#xff0c;说没有使用GridFS。的确博主只…

Codeforces40E[Number Table]

Codeforces40E[Number Table] 解法一&#xff0c;如果有一维很小&#xff0c;可以考虑状压dp之类的&#xff0c;显然非常不优秀。 解法二&#xff0c;如果n*m较小&#xff0c;可以考虑&#xff0c;设出每个位置是否为-1&#xff0c;解xor线性方程组。再bitset优化一下之类的。然…

【DP】天平问题

天平问题 解题思路&#xff1a; 有n个砝码&#xff0c;问可以称出多少种重量&#xff0c;可以在左边或者右边放&#xff0c;也可以不放 原题&#xff1a; 题目描述 小C为了试验小X&#xff0c;便为物竞的小X出了一道物理相关的题&#xff1a;现在给出n个质量的砝码&#x…

.NET Core开发日志——从ASP.NET Core Module到KestrelServer

ASP.NET Core程序现在变得如同控制台(Console)程序一般&#xff0c;同样通过Main方法启动整个应用。而Main方法要做的事情很简单&#xff0c;创建一个WebHostBuilder类&#xff0c;调用其Build方法生成一个WebHost类&#xff0c;最后启动之。实现代码一目了然&#xff1a;要想探…

BZOJ5358: [Lydsy1805月赛]口算训练

题解&#xff1a;判断d是否整除&#xff0c;可以转化为求这段区间内d的因子的指数是否均大于d中的指数。容易想到把每个数字都分解为素因子形式&#xff0c;对每个素数出现的次数求个前缀和即可。然而&#xff0c;这样时间空间都不行。注意到对于一个数x&#xff0c;小于sqrt(x…

jzoj6800-NOIP2020.9.19模拟spongebob【枚举】

正题 题目链接:https://gmoj.net/senior/#contest/show/3222/0 题目大意 nnn个ai,bia_i,b_iai​,bi​&#xff0c;求一个xxx使得最小化∑i1n∣aixbi∣\sum_{i1}^n|a_ixb_i|i1∑n​∣ai​xbi​∣ 解题思路 每个∣aixbi∣|a_ixb_i|∣ai​xbi​∣可以视为一个分两段的函数&#…