VS单元测试入门实践教程
摘要:本教程不会介绍单元测试的基本理论知识,也不会和大家讨论在实际项目中是否需要写单元测试代码的问题。但是如果你此时想使用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、这时会弹出“创建单元测试”窗口,如下图所示,一般情况下直接点击确定即可。

6、如果直接点击确定按钮,系统将按照默认的命名规则(直接加Test后缀)生成测试文件。当然你也可以点击上图中的“设置…”按钮,在弹出的“测试生成设置”中进行规则修改。如下图所示:

7、因为这是我们第一次创建单元测试项目,所以在输出选项中,我们选择默认的“创建新的Visual C# 测试项目”。在单击“确定”按钮后,要求我们填写测试项目的名称,名称自己随便,这里我们就用默认的TestProject1。点击“创建”即可。如果我们以后还对另一个方法进行单元测试,我们就可以在输出项目中直接选择“TestProject1”了,而不比再创建新的测试项目。如下图所示:

8、 这时,在解决方案下面,系统自动为我们创建了TestProject1测试项目和Solution Items(解决方案项)文件夹。

9、双击TestProject1测试项目下的OperationTest.cs文件,我们看一下系统为我们自动生成的测试代码。会发现主要有一下几点:
? 在代码文件顶部增加了一个:using Microsoft.VisualStudio.TestTools.UnitTesting;
? 在生成的OperationTest类上标记了[TestClass()],即使用了TestClassAttribute
? 对测试类的方法AddTest标记了[TestMethod()]
? 在测试类OperationTest中,定义了一个类型为TestContext的变量testContextInstance
? 附加测试特性
10、我们现在要做的就是要对AddTest方法编写测试代码,一般情况下只需要简单地将TODO部分填写完整,将默认的代码:

改成如下测试代码进行第一组测试:
/// <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接到测试的指令后,在测试完成后会自动弹出“测试结果”窗口,结果显示通过,表示测试结果值和预期结果相同。

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);
}
我们再进行一次测试(第二组测试)。每次测试代码修改后,会提示我们刷新更新,直接点击刷新按钮即可。

看看测试结果如何:

这个时候我们发现测试显示未通过,右键菜单单击“查看测试结果详细信息”,如下图所示:


13、错误消息提示期望指为10,但实际结果为-10,我们很容易知道是下面组数据出了问题:
List<dynamic> numbers2 = new List<dynamic>() { "1", "2", "3", "4" };
找到代码:s = -Convert.ToDouble(n); //我们这里故意在转换前加了一个取反运算,把前面的取反运算符去掉,改成:s = Convert.ToDouble(n); 再进行一次测试,测试结果会按预期的方式显示为通过。
14、调试单元测试。上面能一下子就把错误修改,是因为错误是我们故意设置的。在实际开发中,找错误也许并不明显,通常是需要调试后才容易找到。调试单元测试和平时断点测试是一样的,在需要的地方设置断点后,在测试视图中右键选择“调试选定内容”,接下来就是大家所熟悉的断点调试步骤了。如下图所示:

15、查看代码覆盖率。单元测试的编写,涉及到很多要求,但是最基本的就是需要编写多组数据对各个分支代码都至少需要执行一遍。如我们前面第一组直接测试整型相加(1、2、3、4、5)测试结果15为通过,没找到潜在的错误,是因为有些代码没被执行。查看代码覆盖率就能帮助你检测测试数据是否会覆盖所有分支代码。
如下图所示,右键选择“覆盖率结果”,可以查看代码覆盖率。

第一组数据测试代码覆盖率:

第二组数据测试代码覆盖率:

16、代码覆盖率默认演示显示说明:
|
颜色代码 |
说明 |
|
浅蓝色 |
指示在测试运行过程中执行了整个代码行。 |
|
浅褐色 |
指示在测试运行过程中仅执行了代码行的部分代码块。 |
|
红棕色 |
指示在测试运行过程中未执行此行。 |
当然这些默认颜色可以在工具菜单下的选项中进行设置,如下图所示:

17、如果在查看代码覆盖率中出现如下提示,则我们需要简单配置一下

在“测试视图”中,找到Solution Items(解决方案项)文件夹下的Local.testsettings,双击打开“测试设置”窗口,选择“数据和诊断”,将代码覆盖率设置为启用,然后点击“配置”对代码覆盖率进行配置,如下图所示:

在我们的控制台应用程序前打勾,然后点击确定按钮

最后对“测试设置”点击“应用”按钮完成代码覆盖率的配置。重新运行测试,就可以查看代码覆盖率了。
到这里已经完成了如何简单使用VS2010自带的单元测试工具进行断言式Assert条件测试,当然以后我们还可能接触到CollectionAssert类来比较集合对象、StringAssert 类来对字符串进行比较等等,在后面的教程中我们将接触到。
VS单元测试入门实践教程的更多相关文章
- VS2010单元测试入门实践教程
单元测试的重要性这里我就不多说了,以前大家一直使用NUnit来进行单元测试,其实早在Visual Studio 2005里面,微软就已经集成了一个叫Test的专门测试插件,经过几年的发展,这个工具现在 ...
- 最火的分布式 HTAP 数据库 TiDB - 入门实践教程
偶然在某篇博客看到了 TiDB,一个融合 OLTP 和 OLAP 的分布式开源数据库, GitHub 上 Star 很多,然后 watch 了,发现 commit 和 pull request 一直都 ...
- Redis(9)——史上最强【集群】入门实践教程
一.Redis 集群概述 Redis 主从复制 到 目前 为止,我们所学习的 Redis 都是 单机版 的,这也就意味着一旦我们所依赖的 Redis 服务宕机了,我们的主流程也会受到一定的影响,这当然 ...
- 百亿数据百亿花, 库若恒河沙复沙,Go lang1.18入门精炼教程,由白丁入鸿儒,Go lang数据库操作实践EP12
Golang可以通过Gorm包来操作数据库,所谓ORM,即Object Relational Mapping(数据关系映射),说白了就是通过模式化的语法来操作数据库的行对象或者表对象,对比相对灵活繁复 ...
- MyBatis入门学习教程-使用MyBatis对表执行CRUD操作
上一篇MyBatis学习总结(一)--MyBatis快速入门中我们讲了如何使用Mybatis查询users表中的数据,算是对MyBatis有一个初步的入门了,今天讲解一下如何使用MyBatis对use ...
- 做中学之Vim实践教程
做中学之Vim实践教程 Vim VIM是一个非常好的文本编辑器,很多专业程序员使用VIM编辑代码,即使以后你不编写程序,只要跟文本打交道,都应该学学VIM,可以浏览参考一下普通人的编辑利器--Vim这 ...
- MVC5+EF6 入门完整教程11--细说MVC中仓储模式的应用
摘要: 第一阶段1~10篇已经覆盖了MVC开发必要的基本知识. 第二阶段11-20篇将会侧重于专题的讲解,一篇文章解决一个实际问题. 根据园友的反馈, 本篇文章将会先对呼声最高的仓储模式进行讲解. 文 ...
- MVC5+EF6 入门完整教程12--灵活控制Action权限
大家久等了. 本篇专题主要讲述MVC中的权限方案. 权限控制是每个系统都必须解决的问题,也是园子里讨论最多的专题之一. 前面的系列文章中我们用到了 SysUser, SysRole, SysUserR ...
- 全文搜索引擎Elasticsearch入门实践
全文搜索引擎Elasticsearch入门实践 感谢阮一峰的网络日志全文搜索引擎 Elasticsearch 入门教程 安装 首先需要依赖Java环境.Elasticsearch官网https://w ...
随机推荐
- start_kernel——local_irq_disable
在启动初期须要关闭CPU的IRQ,原因: 因为尚未对中断代码.向量表,中断处理器进行初始化,所以必须关闭中断. 我的源码里面定义了 CONFIG_TRACE_IRQFLAGS_SUPPORT,所以调用 ...
- 一种基于Qt的可伸缩的全异步C/S架构server实现(二) 网络传输
二.网络传输模块 模块相应代码命名空间 (namespace ZPNetwork) 模块相应代码存储目录 (\ZoomPipeline_FuncSvr\network) 2.1 模块结构 ...
- nand烧写分析/内核在启动过程中式如何将这个文件映射成/目录及各子目录的?
我用的是ramdisk.image.gz,烧写在flash的0x10140000处 我不太明白内核在启动过程中式如何将这个文件映射成/目录及各子目录的? 如果ramdisk.image.gz在flas ...
- Sybase isql常用命令
isql -Usa -S服务名 --常规登录 isql -Usa -S服务名 -Jcp936 --sa用户在客户端使用字符集cp936登录 C:\Users\Administrator>isql ...
- 使用bulkCopy心得
最近一直在到excel导入,无意中发现Bulk Insert 批量导入,于是研究了一下,在测试的时候一直有问题,然后找度娘帮忙,说新增DataTable数据结构的时候,每个列要与数据库设计时字段对应, ...
- 深入char、varchar、text和nchar、nvarchar、ntext的区别详解
很多开发者进行数据库设计的时候往往并没有太多的考虑char, varchar类型,有的是根本就没注意,因为存储价格变得越来越便宜了,忘记了最开始的一些基本设计理论和原则,这点让我想到了现在的年轻人,大 ...
- struts2 <s:iterator> 遍历方法
1.MapAction.java import java.util.ArrayList; import java.util.HashMap; import java.util.List; ...
- HDU 1151 - Air Raid
很明显求最小路径覆盖 就是求最大匹配 #include <iostream> #include <cstdio> #include <cstring> #inclu ...
- phonegap安卓环境下使用BarcodeScanner插件扫描二维码教程
由于一直在使用phoneGap来开发安卓应用,而对于原生Java小白的我最近这几天一直陷入了如何使用phonegap的BarcodeScanner插件这件事情上,可以说查遍了百度和Google,虽然只 ...
- ORA-04092: COMMIT 不能在触发器中
触发器无需commit也不能写commit触发器和触发它的DML是同一个事务DML提交了,触发器的操作也提交了,要不就一起回滚了 当然,如果你一定要在触发器里写COMMIT那就用自治事务相当于一个事务 ...