之前的项目中做单元测试一直用的是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. git 版本控制系统初学

    Git -The stupid content tracker, 傻瓜内容跟踪器,是一个由Linux内核开发者Linus为了更好地管理Linux内核开发而创立的分布式版本控制软件. 1.建立本地git ...

  2. 【转载】为什么不建议<=3G的情况下使用CMS GC

    之前曾经有讲过在heap size<=3G的情况下完全不要考虑CMS GC,在heap size>3G的情况下也优先选择ParallelOldGC,而不是CMS GC,只有在暂停时间无法接 ...

  3. Magento中直接使用SQL语句

    原理: magento是基于Zend Framework的,所以底层用的还是zend的zend db 在文件app/code/core/Mage/Catalog/model/Resource/Eav ...

  4. 浅试WebStorm配置Node.js开发环境

    web前端开发IDE一直喜欢用WebStorm,这里简单介绍如何用WebStorm搭建一个Node.js开发环境. 首先,需要在本地安装好node.js,以及npm包管理工具.你也可以吧node.js ...

  5. jquery_ajax

    一.调用 <script type="text/javascript" src="jquery-1.11.2.min.js"></script ...

  6. 理解Java的引用对象

    SoftReferenceWeakReference 的特性基本一致, 最大的区别在于 SoftReference会尽可能长的保留引用,不会在GC时就回收对象,而是直到JVM 内存不足时才会被回收(虚 ...

  7. gluster 安装配置基本指南

    基于网络上的多篇文章,做了一些调整. gluster安装 ###  Installing Gluster wget -P /etc/yum.repos.d http://download.gluste ...

  8. linux---基本查找命令

    基本查找命令 一.文件查找命令:find 最大特点:功能强大,可以使用文件的各种属性作为查找条件来查找文件 文件属性:文件权限.文件所有者.文件大小.修改时间.文件类型 语法:find[起始查找目录] ...

  9. SQL SERVER 与ACCESS、EXCEL的数据导入导出转换

    * 说明:复制表(只复制结构,源表名:a 新表名:b)      select * into b from a where 1<>1 * 说明:拷贝表(拷贝数据,源表名:a 目标表名:b) ...

  10. MySQL备份方案

    下面将分别模拟不同场景数据库宕机解决方案:这里应用到的技术分别为innobackuper及binlog日志来进入还原数据 一.主从库情况下(为了不影响主库的性能,备份都放在从库上进行)当主库宕机时,如 ...