MSTest不支持参数化测试的解决方案

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

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

[TestCase(100, 200)]
[TestCase(0, 0)]
[TestCase(-123, -246)]
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增加点实用的核心功能。当然这些是题外话了。

时间: 2024-10-08 05:17:32

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

JUnit之参数化测试和成组测试的使用

JUnit之参数化测试和成组测试的简单使用 参数化测试 正如数组替代int a0,a1,a2一样,测试加法时assertEquals(3.0, h.add(1, 2), 0.1);相当于声明一个变量,要测试100个怎么办. 所以,有了参数化测试,使用一个Collection收集所有的数据--加法时每一次测试需要的几个数据构成一组,n个组构成Collection. 然后按照JUnit的用法要求,写出单元测试类.(偷懒一下,不想写被测试的业务类X了.下面的例子中假设要测试的方法是,判断一个数是否奇数

ie8以下版本(包括ie8)的浏览器不支持html5标签属性解决方案(Modernizr 2.6.2插件的使用)

今天脑抽想用html5标签设计一个网页,我本人用的是火狐浏览器,都弄好后我发现一个很严重的问题,除了ie9以下的浏览器都不能支持html5标签(article,aside,dialog,footer,header,section,footer,nav,figure,menu). 我上网找了好多中方法,有网友说使用 <!--[if lt IE9]> <script> (function() { if (! /*@[email protected]*/ 0) return; var e

JUnit实战(1) - JUnit起步(Parameterized参数化测试)

创建Java Project项目,项目名称:ch01-jumpstart Calculator.java public class Calculator { public double add(double number1, double number2) { return number1 + number2; } } CalculatorTest.java import static org.junit.Assert.*; import junit.framework.Assert; impo

Junit 4 Tutorials(Junit 4 教程) 四、Junit4 参数化测试

Junit 4 参数化测试 允许通过变化范围的参数值来测试方法.参数擦测试可以通过以下简单的步骤实现: 对测试类添加注解 @RunWith(Parameterized.class) 将需要使用变化范围参数值测试的参数定义为私有变量 使用上一步骤声明的私有变量作为入参,创建构造函数 .创建一个使用@Parameters注解的公共静态方法,它将需要测试的各种变量值通过集合的形式返回. 使用定义的私有变量定义测试方法 Junit 4 参数化测试样例 EvenNumberChecker.java 校验输

TestNG的参数化测试、共享线程池配置、参数默认值配置

在使用TestNG进行测试时,经常会使用到一些参数化配置,比如数据库.连接池.线程池数, 使用TestNG的参数@Parameter注解进行自动化读取 使用多线程的方式运行测试代码配置: 在'<suite>'标签中配置data-provider-thread-count="20" Java代码: /** * * <p> * Title: TestngParameters * </p> * * <p> * 参考配置文件testng-para

jquery 1.9版本后不在支持browser 方法的解决方案

今天对jquery 进行升级,导致项目出错,原来在1.9版本之后 jquery 不支持browser 方法了.  官方建议的又不好用,所以我所jquery 原来的代码摘除来,又扩展回去. //解决jquery 1.9版本之后不支持 browser 这里进行了扩展 var a, b; $.uaMatch = function (a) { a = a.toLowerCase(); var b = /(chrome)[ \/]([\w.]+)/.exec(a) || /(webkit)[ \/]([\

【Python】nose_parameterized使unitTest支持参数化

nose_parameterized使unitTest支持参数化 GIThttps://github.com/wolever/nose-parameterized And @parameterized.expand can be used to generate test methods in situations where test generators cannot be used (for example, when the test class is a subclass of uni

【t1】&#183;badboy跟jmeter结合的网页参数化测试(pigeon详细说)

[163网易邮箱网页的参数化测试],在网上查找的资料中学了好久,发现对于我这种小白来说,还是不够详细,我自己思考细想了很久才慢慢有点掌握,所以把参数化的详细过程梳理一遍,帮自己记录,也帮一下小白学习. [1]第一步,肯定是先将两个软件工具下载下来,两个工具打包放在百度云了,可直接使用http://pan.baidu.com/s/1micsNt2.当然你要自己官网下载也行呵呵.jmeter解压后可直接使用,badboy压缩包解压好是BadboyInstaller-2.0.5.exe,运行该文件进行

junit 单元测试 - 参数化测试

junit4.x版本需要引入如下jar包: hamcrest-core-1.3.jar junit-4.12-beta-3.jar 新建一个计算器类,如下: package com.pt; public class Calculate { /** * 加法 * @param d1 * @param d2 * @return */ public static double add(double d1,double d2){ return d1 + d2; } /** * 减法 * @param d