摘要:本教程不会介绍单元测试的基本理论知识,也不会和大家讨论在实际项目中是否需要写单元测试代码的问题。但是如果你此时想使用VS中的单元测试的工具来测试某个方法是否正确,可你又从来没真正实践过,那么本教程将带你一步一步使用VS2010集成的Unit Test进行断言(Assert)式验证数据的正确性,及代码覆盖率的查看。
关键词:Unit Test、单元测试、代码覆盖率、Assert、Twifly
正文:
在本入门教程中我们假设来测试一个简单的加法运算方法是否正确。该方法能够接受任意个参数,参数类型可以是整型、字符型、浮点型,对于其他复杂类型我们这里暂时忽略。既然作为入门教程,那么下面我们按照详细的步骤开始。
1、 先创建一个空白解决方案(文件—>新建—>项目—>已安装的模版—>其他项目类型—>Visual Studio解决方案-->空白解决方案)命名为TestUnit。
2、 在新创建的解决方案(TestUnit)鼠标右键,选择添加—>新建项目—>控制台应用程序。
如下图所示:
3、 在控制台应用程序中,我们添加一个Operation类。添加一个简单的Add方法,该方法能对一个dynamic类型的列表的各项求和,简单地,我们这里假设传入的类型只可能是int、double、string类型,所以不对其他类型做异常捕捉。代码如下:
public class Operation
{
public static dynamic Add(List<dynamic> numbers)
{
dynamic sum = 0;
foreach (var n in numbers)
{
var s = n;
if (s is string)
{
s = -Convert.ToDouble(n); //我们这里故意在转换前加了一个取反运算
}
sum += s;
}
return sum;
}
}
4、 现在我们来对Add方法做下单元测试。将光标放在Add方法名上,然后右键选择“创建单元测试(C)…”,如下图所示:
5、这时会弹出“创建单元测试”窗口,如下图所示,一般情况下直接点击确定即可。
![【原创】VS2010单元测试入门实践教程 - Twilight of Twifly - Twilight of Twifly](http://img7.ph.126.net/y1bxT10jSRkEq82JOHza_Q==/1079738010679601847.jpg)
7、因为这是我们第一次创建单元测试项目,所以在输出选项中,我们选择默认的“创建新的Visual C# 测试项目”。在单击“确定”按钮后,要求我们填写测试项目的名称,名称自己随便,这里我们就用默认的TestProject1。点击“创建”即可。如果我们以后还对另一个方法进行单元测试,我们就可以在输出项目中直接选择“TestProject1”了,而不比再创建新的测试项目。如下图所示:
8、 这时,在解决方案下面,系统自动为我们创建了TestProject1测试项目和Solution Items(解决方案项)文件夹。
![【原创】VS2010单元测试入门实践教程 - Twilight of Twifly - Twilight of Twifly](http://img0.ph.126.net/hoWucLhEDHQIxGFvTDe80A==/1361775937343866990.jpg)
? 在代码文件顶部增加了一个:using Microsoft.VisualStudio.TestTools.UnitTesting;
? 在生成的OperationTest类上标记了[TestClass()],即使用了TestClassAttribute
? 对测试类的方法AddTest标记了[TestMethod()]
? 在测试类OperationTest中,定义了一个类型为TestContext的变量testContextInstance
? 附加测试特性
10、我们现在要做的就是要对AddTest方法编写测试代码,一般情况下只需要简单地将TODO部分填写完整,将默认的代码:
![【原创】VS2010单元测试入门实践教程 - Twilight of Twifly - Twilight of Twifly](http://img9.ph.126.net/tlyyPaOW_TAdcUc3uQH7Iw==/3073425270721181249.jpg)
改成如下测试代码进行第一组测试:
/// <summary>
///Add 的测试
///</summary>
[TestMethod()]
public void AddTest()
{
List<dynamic> numbers = new List<dynamic>() { 1, 2, 3, 4, 5 };
dynamic expected = 15;
dynamic actual;
actual = Operation.Add(numbers);
Assert.AreEqual(expected, actual);
}
这个方法就是对整型1、2、3、4、5累加进行测试,我们期望的结果是15。Assert类的AreEqual方法用于验证实际结果和期望值是否相等。Assert断言类包含很多方法用于比较,在测试方法中,可以调用任意数量的 Assert 类方法,如 Assert.AreEqual()。Assert 类有很多方法可供选择,其中许多方法具有若干重载。详情可以参考MSDN的Assert类。
默认生成的代码中Assert.Inconclusive 语句用于指示该测试尚未准备好,不能运行(不能确定结果是否正确),所以当我们写好测试代码后,Assert.Inconclusive语句就可以删除了。
11、运行单元测试。打开测试视图(测试-->窗口-->测试视图),测试视图中会以列表的方式显示测试方法。右键菜单选择“运行选定内容”即可执行对该方法的测试,如下图所示:
![【原创】VS2010单元测试入门实践教程 - Twilight of Twifly - Twilight of Twifly](http://img4.ph.126.net/Kim7EjKypMbFoXP-MX26bw==/2517512191717820844.jpg)
![【原创】VS2010单元测试入门实践教程 - Twilight of Twifly - Twilight of Twifly](http://img1.ph.126.net/FCmQNP3DZgThLVPQB1yO4w==/1033576114499240091.jpg)
12、上面一组单元测试(整型)结果是通过,但是我们知道对字符串操作是故意留有错误,但是实际过程中,那段代码并没有执行。所以我们还要对字符格式的数字进行测试,当然还有浮点型、负数等等,这些可以都单独测试,也可以一起测试。把测试代码改成 :
/// <summary>
///Add 的测试
///</summary>
[TestMethod()]
public void AddTest()
{
List<dynamic> numbers = new List<dynamic>() { 1, 2, 3, 4, 5 };
dynamic expected = 15;
dynamic actual;
actual = Operation.Add(numbers);
Assert.AreEqual(expected, actual);
List<dynamic> numbers2 = new List<dynamic>() { "1", "2", "3", "4" };
dynamic expected2 = 10;
dynamic actual2;
actual2 = Operation.Add(numbers2);
Assert.AreEqual(expected2, actual2);
List<dynamic> numbers3 = new List<dynamic>() { "1", 2.5, 3, "4.5", 5, 6 };
dynamic expected3 = 22;
dynamic actual3;
actual3 = Operation.Add(numbers3);
Assert.AreEqual(expected3, actual3);
}
我们再进行一次测试(第二组测试)。每次测试代码修改后,会提示我们刷新更新,直接点击刷新按钮即可。
![【原创】VS2010单元测试入门实践教程 - Twilight of Twifly - Twilight of Twifly](http://img3.ph.126.net/WsHaZh7VtZkV1bgcpULawQ==/191121509204241303.jpg)
看看测试结果如何:
![【原创】VS2010单元测试入门实践教程 - Twilight of Twifly - Twilight of Twifly](http://img5.ph.126.net/Cynmegso2edV0SnoPG6_kg==/1033576114499240125.jpg)
这个时候我们发现测试显示未通过,右键菜单单击“查看测试结果详细信息”,如下图所示:
![【原创】VS2010单元测试入门实践教程 - Twilight of Twifly - Twilight of Twifly](http://img6.ph.126.net/IfhPZuIVyj5llYLC6QHoFg==/1292251618096326196.jpg)
![【原创】VS2010单元测试入门实践教程 - Twilight of Twifly - Twilight of Twifly](http://img1.ph.126.net/7A5fXgFvLZOsjDVKMiwCmQ==/6597280872888662411.jpg)
13、错误消息提示期望指为10,但实际结果为-10,我们很容易知道是下面组数据出了问题:
List<dynamic> numbers2 = new List<dynamic>() { "1", "2", "3", "4" };
找到代码:s = -Convert.ToDouble(n); //我们这里故意在转换前加了一个取反运算,把前面的取反运算符去掉,改成:s = Convert.ToDouble(n); 再进行一次测试,测试结果会按预期的方式显示为通过。
14、调试单元测试。上面能一下子就把错误修改,是因为错误是我们故意设置的。在实际开发中,找错误也许并不明显,通常是需要调试后才容易找到。调试单元测试和平时断点测试是一样的,在需要的地方设置断点后,在测试视图中右键选择“调试选定内容”,接下来就是大家所熟悉的断点调试步骤了。如下图所示:
![【原创】VS2010单元测试入门实践教程 - Twilight of Twifly - Twilight of Twifly](http://img9.ph.126.net/pwbgBahB9AAhDpDjEg-iOA==/1011058116362388139.jpg)
15、查看代码覆盖率。单元测试的编写,涉及到很多要求,但是最基本的就是需要编写多组数据对各个分支代码都至少需要执行一遍。如我们前面第一组直接测试整型相加(1、2、3、4、5)测试结果15为通过,没找到潜在的错误,是因为有些代码没被执行。查看代码覆盖率就能帮助你检测测试数据是否会覆盖所有分支代码。
如下图所示,右键选择“覆盖率结果”,可以查看代码覆盖率。
![【原创】VS2010单元测试入门实践教程 - Twilight of Twifly - Twilight of Twifly](http://img0.ph.126.net/SC9usLx-6nZb9aVwg0ZKng==/6597206106098108240.jpg)
第一组数据测试代码覆盖率:
![【原创】VS2010单元测试入门实践教程 - Twilight of Twifly - Twilight of Twifly](http://img2.ph.126.net/VjSGeUcaPQagojGrE500-w==/2478668644931564442.jpg)
第二组数据测试代码覆盖率:
![【原创】VS2010单元测试入门实践教程 - Twilight of Twifly - Twilight of Twifly](http://img0.ph.126.net/-yIDDsT1l43i4TMxWg07Dg==/2482890769582225260.jpg)
16、代码覆盖率默认演示显示说明:
颜色代码 | 说明 |
浅蓝色 | 指示在测试运行过程中执行了整个代码行。 |
浅褐色 | 指示在测试运行过程中仅执行了代码行的部分代码块。 |
红棕色 | 指示在测试运行过程中未执行此行。 |
当然这些默认颜色可以在工具菜单下的选项中进行设置,如下图所示:
![【原创】VS2010单元测试入门实践教程 - Twilight of Twifly - Twilight of Twifly](http://img9.ph.126.net/Xnhxd7e9habWaXGa-9kqcg==/1034420539429372069.jpg)
17、如果在查看代码覆盖率中出现如下提示,则我们需要简单配置一下
![【原创】VS2010单元测试入门实践教程 - Twilight of Twifly - Twilight of Twifly](http://img8.ph.126.net/G7T4of-9m3D1JZjfYPFFYw==/996702892550141218.jpg)
在“测试视图”中,找到Solution Items(解决方案项)文件夹下的Local.testsettings,双击打开“测试设置”窗口,选择“数据和诊断”,将代码覆盖率设置为启用,然后点击“配置”对代码覆盖率进行配置,如下图所示:
![【原创】VS2010单元测试入门实践教程 - Twilight of Twifly - Twilight of Twifly](http://img2.ph.126.net/wj-MYfq99_E6X4oCqWr4dg==/3087780494533597582.jpg)
在我们的控制台应用程序前打勾,然后点击确定按钮
![【原创】VS2010单元测试入门实践教程 - Twilight of Twifly - Twilight of Twifly](http://img7.ph.126.net/yayOnGAuSos1pUFNf2NNqw==/103582791447228787.jpg)
最后对“测试设置”点击“应用”按钮完成代码覆盖率的配置。重新运行测试,就可以查看代码覆盖率了。
到这里已经完成了如何简单使用VS2010自带的单元测试工具进行断言式Assert条件测试,当然以后我们还可能接触到CollectionAssert类来比较集合对象、StringAssert 类来对字符串进行比较等等,在后面的教程中我们将接触到。
最后如果对本入门教程仍有疑问,可以参考MSND官方的教程文章。
MSDN官方参考:
演练:创建并运行单元测试
http://msdn.microsoft.com/zh-cn/library/ms182532.aspx
如何:创建和运行单元测试
http://msdn.microsoft.com/zh-cn/library/dd286656.aspx
单元测试分析
http://msdn.microsoft.com/zh-cn/library/ms182517.aspx
使用 Assert 类
http://msdn.microsoft.com/zh-cn/library/ms182530(v=vs.100).aspx
演练:运行测试并查看代码覆盖率