之前的项目中做单元测试一直用的是NUnit,这次做新项目,负责人要求统一用MsTest,理由是MsTest是Visual Studio内置的。用就用吧,我没什么意见。不过用了两天,我就发现一个大问题:MsTest并不支持参数化测试(也有叫行测试的)。

什么是参数化测试?简单的说,就是同样的逻辑,根据输入参数不同给出不同的结果。因为只是参数不同,所以并不希望把测试写多遍,但是又希望对每个参数的测试成为一个独立的测试用例。举例说,假定我有一个数学计算的方法是把数字*2,我希望证明这个方法对于正数、负数和0都是通过的。在NUnit中可以通过TestCaseAttribute来为测试提供参数:

[TestCase(, )]
[TestCase(, )]
[TestCase(-, -)]
public void TestDouble(int value, int result)
{
Assert.AreEqual(result, Calc.Double(value));
}

但是MsTest中并没有类似功能的Attribute。怎么办呢?最简单粗暴的方法当然是写一个循环提供参数了。不过这并不是我想要的结果,一是写循环遍历的代码有点无谓;更重要的是循环只能作为一个整体的测试用例来执行,如果出错的话不自己写信息就无法分辨出到底哪个参数出错了。

网上找了找,发现问类似问题的人还真不少。基本上回答集中在下面几种方案:

1. VS2012 Update1以后提供了DataRow属性,但是只能在Windows Store Apps使用。(个人觉得这一点好奇葩,一个测试功能还有必要专门优待 Store用户吗?)总之我们做的是普通类库,这个法子不适用。

2. 用DataSourceAttribute,按照文档这个标注可以提供OleDB数据源、XML或者CSV格式的文件作为数据源。对于简单的参数测试这个方案实在有点太重了,再说按照定义使用了外部文件或数据库的单元测试还能算是单元测试吗?

3. 用PostSharp增强代码的方法来扩展测试。该方案我大概看了一下也放弃了,毕竟PostSharp是比较非主流的技术,再说使用它会明显增加编译过程的复杂性,对持续集成也有点不友好。

4. 按照MsTest对象模型来写一些扩展属性。老实说在寻找解决方案之前我已经心里判断应该会走这条路,而且按照网络的示例真的写了几个扩展属性出来测试,编译倒是正常,但测试就是死活运行不起来。再仔细看说明,原来要在Visual Studio运行扩展测试还要修改几个注册表项....好吧我们开发组十几号人都去折腾注册表的话才能测试的话,还让不让小伙伴们开心的一起玩耍了。总之这个方案也Pass。

看来看去,就没什么令人满意的办法,唯一还算可行的只有用DataSource了。当然我是不会用数据库这么重量级的数据源的,那对单元测试来说完全是高射炮打蚊子。用文件的话,从存粹的敏捷开发理念来说也是有问题的,但文件毕竟还算相对容易控制。于是我用XML文件测试了一下,通过了,但是有几个小坑需要注意,这里记录一下。

代码示例如下,很简单,不解释了:

[TestClass]
[DeploymentItem(@"Fixtures\add.xml")]
public class UnitTest1
{
public TestContext TestContext { get; set; } [TestMethod]
[DataSource("Microsoft.VisualStudio.TestTools.DataSource.XML",
@"|DataDirectory|\Fixtures\add.xml",
"row",
DataAccessMethod.Sequential)]
public void TestMethod1()
{
int a = Convert.ToInt32(TestContext.DataRow["a"]);
int b = Convert.ToInt32(TestContext.DataRow["b"]);
int expected = Convert.ToInt32(TestContext.DataRow["expected"]);
var result = new Class1().Add(a, b);
Assert.AreEqual(expected, result);
}
}

测试用的XML文件:

<rows>
<row a="1" b="2" expected="3" />
<row a="2" b="-1" expected="-1" />
<row a="3" b="0" expected="3" />
</rows>

对测试有几点需要注意:

  1. 测试类必须加一个TestContext属性;
  2. XML文件编译属性的 Copy to output directory 应该设置为 Copy always 或者 Copy if newer;
  3. 要在远程服务器上测试成功(比如CI服务器),需要加DeployItem标注,表示这个文件要和程序集一起部署到测试位置;
  4. DataSource的第二个参数里DataDirectory是指什么,MSDN里只拿数据库为例子,没有对XML/CSV的情况做说明。从结果看,应该就是程序输出的位置。

结果是可用的,但是老实说,这样的测试代码从观感上来说远不如NUnit那么简单优雅。我觉得微软与其把Visual Studio的测试界面搞得那么复杂,还不如给MsTest增加点实用的核心功能。当然这些是题外话了。

MSTest不支持参数化测试的解决方案的更多相关文章

  1. 参数化测试与Mock

    参数化测试与Mock 转载自https://blog.csdn.net/sunliduan/article/details/42026509 单元测试概念 说到测试,大家都不会陌生,从我们开始学习编程 ...

  2. Python 中如何实现参数化测试?

    Python 中如何实现参数化测试? 之前,我曾转过一个单元测试框架系列的文章,里面介绍了 unittest.nose/nose2 与 pytest 这三个最受人欢迎的 Python 测试框架. 本文 ...

  3. Google C++单元测试框架GoogleTest---值参数化测试

    值参数化测试允许您使用不同的参数测试代码,而无需编写同一测试的多个副本. 假设您为代码编写测试,然后意识到您的代码受到布尔参数的影响. TEST(MyCodeTest, TestFoo) { // A ...

  4. testng入门教程10 TestNG参数化测试

    在TestNG的另一个有趣的功能是参数测试.在大多数情况下,你会遇到这样一个场景,业务逻辑需要一个巨大的不同数量的测试.参数测试,允许开发人员运行同样的测试,一遍又一遍使用不同的值. TestNG让你 ...

  5. JUnit之参数化测试、套件/成组测试的使用

    原文地址http://blog.csdn.net/yqj2065/article/details/39967065 参数化测试 正如数组替代int a0,a1,a2一样,测试加法时assertEqua ...

  6. Junit5中实现参数化测试

    从Junit5开始,对参数化测试支持进行了大幅度的改进和提升.下面我们就一起来详细看看Junit5参数化测试的方法. 部署和依赖 和Junit4相比,Junit5框架更多在向测试平台演进.其核心组成也 ...

  7. JUnit5学习之六:参数化测试(Parameterized Tests)基础

    欢迎访问我的GitHub https://github.com/zq2599/blog_demos 内容:所有原创文章分类汇总及配套源码,涉及Java.Docker.Kubernetes.DevOPS ...

  8. JUnit5学习之七:参数化测试(Parameterized Tests)进阶

    欢迎访问我的GitHub https://github.com/zq2599/blog_demos 内容:所有原创文章分类汇总及配套源码,涉及Java.Docker.Kubernetes.DevOPS ...

  9. JUnit5参数化测试的几种方式

    参数化测试一直是津津乐道的话题,我们都知道JMeter有四种参数化方式:用户自定义变量.用户参数.CSV文件.函数助手,那么JUnit5有哪些参数化测试的方式呢? 依赖 JUnit5需要添加junit ...

随机推荐

  1. 线程本地变量ThreadLocal

    一.本地线程变量使用场景 并发应用的一个关键地方就是共享数据.如果你创建一个类对象,实现Runnable接口,然后多个Thread对象使用同样的Runnable对象,全部的线程都共享同样的属性.这意味 ...

  2. CentOS下安装福昕PDF软件

    官方下载地址:http://www.foxitsoftware.cn/downloads/ tar -jxvf foxreader.tar.bz2问题:下载官方包以后解压,双击不能打开,也没有任何提示 ...

  3. CCLablettf读取显示xml文件内容显示中文

    CCDictionary *strings = CCDictionary::createWithContentsOfFile("tips2.xml"); const char *h ...

  4. 跨域方法之CORS

    跨域的方法非常之多,如果想了解其中CORS,不要浪费时间,看下面三个就够了 了解CORS   https://developer.mozilla.org/en-US/docs/Web/HTTP/Acc ...

  5. 用于主题检测的临时日志(fe4edac1-b4f4-4673-ae87-110cbb7dbb5a - 3bfe001a-32de-4114-a6b4-4005b770f6d7)

    这是一个未删除的临时日志.请手动删除它.(25ea5485-9168-424b-a30c-09cc1371e2d9 - 3bfe001a-32de-4114-a6b4-4005b770f6d7)

  6. java和html的区别

    Java 不是一门程序语言,它是一个平台,也可以说是一门技术. Java 包括 1.Java 程式语言 一个类似 C++ 或 Smalltalk 的物件导向程式语言.学习 Java 程式语言类似学人类 ...

  7. Opencv——彩色图像灰度化的三种算法

    为了加快处理速度在图像处理算法中,往往需要把彩色图像转换为灰度图像.24为彩色图像每个像素用3个字节表示,每个字节对应着RGB分量的亮度. 当RGB分量值不同时,表现为彩色图像:当RGB分量相同时,变 ...

  8. Android的自动对焦

    1,什么是自动对焦? ---安卓的自动对焦的概念是指能够在指定的位置计算出准确的焦点位置. 这个就好像是传统意义上的手动对焦.但是google是这个意思. 2.什么是追焦? ----安卓的追焦是指FO ...

  9. SQL Server调优系列进阶篇 - 如何重建数据库索引

    随着数据的数据量的急剧增加,数据库的性能也会明显的有些缓慢这个时候你可以考虑下重建索引或是重新组织索引了. DBCC SHOWCONTIG('表名') 可以查看当前表的索引碎情况. 重建索引 方法一: ...

  10. 敌情篇 ——DDoS攻击原理

    敌情篇 ——DDoS攻击原理 DDoS攻击基础 DDoS(Distributed Denial of Service,分布式拒绝服务)攻击的主要目的是让指定目标无法提供正常服务,甚至从互联网上消失,是 ...