.netcore持续集成测试篇之Xunit数据驱动测试一
Nunit里提供了丰富的数据测试功能,虽然Xunit里提供的比较少,但是也能满足很多场景下使用了,如果数据场景非常复杂,Nunit和Xunit都是无法胜任的,有不少测试者选择自己编写一个数据提供程序,但是更建议使用AutoFixture框架,一是因为自己工作中写的往往只是为了解决某个或者部分问题,只能随着业务逻辑的扩展才能不断的健壮起来,二是这样的框架往往缺少良好文档,主要由核心开发者口口相传,这就导致后来者遇到不明白了功能就去问核心开发者,影响这些开发者的其它工作.
下面介绍一下Xunit里的数据提供方式.
InlineData
InlineData相当于Nunit里的TestCase,用注解的方式给测试方法提供数据.
我们通过以下代码片段了解它的基本用法
[Theory]
[InlineData(1, 2)]
[InlineData(5, 9)]
public void Test1(int x,int y)
{
int result = x + y;
Assert.Equal(x + y, result);
}
以上方法与普通测试方法相比最大的区别是它使用的是Theory注解,而不是fact注解.使用Theory注解的方法必须提供相应的参数,否则会报编译错误.
以上测试我们提供了两组InlineData,这样在测试运行的时候测试方法就会根据这些数据生成两个方法实例.同Nunit里的表现行为相似.
MemberData
MemberData顾名思义,就是成员数据,它类似于Nunit里的TestCaseSource但是不同的是Xunit的MemberData的数据提供者必须是当前测试类的成员,测试数据提供者和测试方法耦合在一块可能不是太好的设计,如果需要大量测试数据,建议使用AutoFixture.
数据提供者之属性提供数据
通过属性提供测试数据适应于一些比较简单的场景,这些数据是简单的,确定的.
下面看一个示例
[Theory]
[MemberData(nameof(UnitTest1.ProvideData))]
public void Test1(int x,int y)
{
int result = x + y;
Assert.Equal(x + y, result);
}
public static IEnumerable<object[]> ProvideData
{
get
{
yield return new object[] { 3, 4 };
yield return new object[] { 5, 9 };
yield return new object[] { 11, 13 };
}
}
以上代码中,测试方法和数据提供者必须位于同一个类中,并且数据提供者必须是一个公开的,静态的属性.并且它的集合元素类型必须是Object类型.像以上Test1方法虽然需要的是int类型参数,但是提供者类型也必须是object类型,而不能是具体类型.
以上数据提供属性一共yield了三组数据,因此测试方法会生成三个测试实例.
数据提供者之方法提供数据
[Theory]
[MemberData(nameof(UnitTest1.ProvideData))]
public void Test1(int x,int y)
{
int result = x + y;
Assert.Equal(x + y, result);
}
public static IEnumerable<object[]> ProvideData()
{
yield return new object[]{3,4 };
yield return new object[] {5, 9};
yield return new object[] { 11, 13 };
}
你可能会感觉以上方法和属性并没太大的区别,其实方法的功能更为强大,因为属性无法动态指定参数,而方法可以,我们可以指定方法接收动态运行时需要的参数,然后在MemberData的构造函数里传入参数来动态获取数据.
数据提供者之成员提供数据
成员提供数据可以把外部对象作为本类成员,然后给测试方法提供数据.外部对象须继承自TheoryData.
我们定义一个MyDataprovider
public class MyDataprovider<TData1,TData2>:TheoryData<TData1,TData2>
{
public MyDataprovider(IEnumerable<TData1> dataSource1,IEnumerable<TData2> datasource2)
{
if (dataSource1 == null || datasource2 == null || !dataSource1.Any() || !datasource2.Any())
throw new Exception("集合不为能空或者null");
foreach (TData1 data1 in dataSource1)
{
foreach (TData2 data2 in datasource2)
{
Add(data1, data2);
}
}
}
}
我们再看测试类
public class UnitTest1
{
public static MyDataprovider<int, int> myprovider =
new MyDataprovider<int, int>(new[] {3, 4, 5}, new[] {6, 7, 8});
[Theory]
[MemberData(nameof(UnitTest1.myprovider))]
public void Test1(int x,int y)
{
int result = x + y;
Assert.Equal(x + y, result);
}
}
我们在new MyDataprovider的时候通过构造函数传入两个集合,MyDataprovider继承了TheoryData的Add方法,把数据添加到theorydata中.
以上方法实际上生成了一个笛卡尔集{{3,6},{3,7},{3,8},{4,6},{4,7},{4,8},{5,6},{5,7},{5,8}}类似于Nunit里的values注解不加sequential,这个行为很多时候可能并不是我们想要的,我们想要的可能是{{3,6},{4,7},{5,8}}这样的组合,这其实是可以在MyDataprovider里自定义的.
我们把MyDataprovider改为如下就可以了
public class MyDataprovider<TData1,TData2>:TheoryData<TData1,TData2>
{
public MyDataprovider(IEnumerable<TData1> dataSource1,IEnumerable<TData2> datasource2)
{
if (dataSource1 == null || datasource2 == null || !dataSource1.Any() || !datasource2.Any())
throw new Exception("集合不为能空或者null");
var count1 = dataSource1.Count();
var count2 = datasource2.Count();
if (count1 != count2) throw new ArgumentException("两个集合长度必须相等");
for (int i = 0; i < count1; i++)
{
Add(dataSource1.ElementAt(i), datasource2.ElementAt(i));
}
}
}
这样虽然可以把数据提供者转移到外部了,然而去把简单的问题搞的相当复杂!
数据提供者之类数据提供者
前面介绍的数据提供者除了InlineData比较常用外,其它几个都不是很实用,因为数据和测试方法混合在一个类中,违反了职责单一的原则,最后一个看似比较好的解开了耦合,实际上却带来了更高的复杂度.这里介绍ClassDataAttribute,类数据提供者.
类数据提供者需要实现IEnumerable<Object[]>泛型接口,Xunit会自动的调用其GetEnumerator方法来遍历数据然后提供给测试类.
我们看以下数据提供类
public class MyDataClassProvider:IEnumerable<object[]>
{
public IEnumerator<object[]> GetEnumerator()
{
yield return new object[] {3, 4};
yield return new object[] {5, 9};
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
}
以上类型的GetEnumerator继承自接口,我们这里只提供了一些简单数据,当然带可以编写更为复杂的数据提供逻辑,比如从数据库里遍历,然后转化为可遍历集合.
下面再看看它是如何被使用的.
[Theory]
[ClassData(typeof(MyDataClassProvider))]
public void Test1(int x,int y)
{
var result = x + y;
Assert.Equal(x + y, result);
}
这里使用ClassData注解,传入一个type类型.运行的时候Xunit便可以给测试方法提供测试数据了
.netcore持续集成测试篇之Xunit数据驱动测试一的更多相关文章
- .netcore持续集成测试篇之Xunit结合netcore内存服务器发送post请求
系列目录 Web项目中,很多与用户数据交互的请求都是Post请求,想必大家都用过HttpClient构造过post请求,这里并不对HttpClient做详细介绍,只介绍一些常用的功能.并结合AutoF ...
- .netcore持续集成测试篇之开篇简介及Xunit基本使用
系列目录 为了支持跨平台,微软为.net平台提供了.net core test sdk,这样第三方测试框架诸如Nunit,Xunit等只需要按照sdk提供的api规范进行开发便可以被dotnet cl ...
- .netcore持续集成测试篇之测试方法改造
系列目录 通过前面两节讲解,我们的测试类中已经有两个测试方法了,总体上如下 public class mvc20 { private readonly HttpClient _client; publ ...
- .netcore持续集成测试篇之MVC测试
前面我们讲的很多单元测试的的方法和技巧不论是在.net core和.net framework里面都是通用的,但是mvc项目里有一种比较特殊的类是Controller,首先Controller类的返回 ...
- .netcore持续集成测试篇之搭建内存服务器进行集成测试一
系列目录 在web项目里,我们把每一层的代码的单元测试都通过并不代表程序能正常运行,因为这个过程缺失了http管道,很多时候我们还还需要把项目布在iis环境中或者在vs里启动iis express服务 ...
- .netcore持续集成测试篇之 .net core 2.1项目集成测试
系列目录 从.net到.net core以后,微软非常努力,以每年一到两个大版本的频率在演进.net core,去年相继发布了.net core 2.1和2.2,其中2.1是长期支持版,不断的快速更新 ...
- .netcore持续集成测试篇之web项目验收测试
系列目录 通过前面的单元测试,我们能够保证项目的基本模块功能逻辑是正常的,通过集成测试能够保证接口的请求是正常的.然而最终项目交付我们还需要对项目进行页面的行为进行测试,比如页面布局是否正常,按钮是否 ...
- .net持续集成测试篇之Nunit参数化测试
系列目录 在进行单元测试的时候,很多时候,很多时候我们都是在单元测试方法内部提供特定的值,但是这样测试往往造成样本数不足从而导致覆盖的结果不够全面,很多时候我们更想提供来自外部的,满足条件的一组值来进 ...
- .net持续集成测试篇之Nunit 测试配置
系列目录 在开始之前我们先看一个陷阱 用到的Person类如下 public class Person:IPerson { public string Name { get; set; } publi ...
随机推荐
- HDU 5792:World is Exploding(树状数组求逆序对)
http://acm.hdu.edu.cn/showproblem.php?pid=5792 World is Exploding Problem Description Given a sequ ...
- os.path.join用法
os.path.join()函数:连接两个或更多的路径名组件 1.如果各组件名首字母不包含’/’,则函数会自动加上 2.如果有一个组件是一个绝对路径,则在它之前的所有组件均会被舍弃 3.如果最后一个组 ...
- scrapy基础知识之 CrawlSpiders:
通过下面的命令可以快速创建 CrawlSpider模板 的代码: scrapy genspider -t crawl spidername xx.com LinkExtractors class sc ...
- mysql中id值被重置的情况
MySQL中,如果你为一张使用了innodb引擎的表指定了一auto_increment列,那么这张表会有一个auto_increment计数器,专门记录当前auto_increment的相关值,用来 ...
- springboot与springcloud的关系
1 . 问题描述 随着springboot.springcloud的不断迭代升级,开发效率不断提升,越来越多的开发团队加入到spring的大军中,今天用通俗的语言,介绍下什么是springboot,s ...
- 如何在vue中监听scroll,从而实现滑动加载更多
首先需要明确3个定义: 文档高度:整个页面的高度 可视窗口高度:你看到的浏览器可视屏幕高度 滚动条滚动高度: 滚动条下滑过的高度 当 文档高度 = 可视窗口高度 + 滚动条高度 时,滚动条正好到底. ...
- 缓存实践Cache Aside Pattern
Cache Aside Pattern旁路缓存,是对缓存应用的一个总结,包括读数据方案和写数据方案. 读数据方案 先读cache,如果命中则返回 如果miss则读db 将db的数据存入缓存 写数据方案 ...
- win10 安装mysql(图文详情)避免卡在最后一步
win10 安装mysql 本人安装mysql一般都是在镜像文件夹中下载(http://mirrors.sohu.com/),最近系统重做了之后安装mysql5.5.msi,可以安装成功.但是在最后的 ...
- 从后端到前端之Vue(三)小结以及一颗真实的大树
上一篇写了一下tab,下面整理一下用过的知识点,本想按照官网的文档,整理一下可以更清晰,结果也许是我的方法不对吧,总之更模糊了. 按照官网文档的顺序整理到了表单输入绑定之前,因为之前大致也就只涉及到这 ...
- 九、chart控件的使用(图表数据的展示)
chart属于老插件网上还有新的插件功能也更多) Chart控件是VS自带的控件,只是比较老了,功能肯定不如现在出来的某些插件强,不过对于简单的显示还是够用:那么现在来看看chart控件的使用方法: ...