[Test] 单元测试艺术(1) 基础知识
单元测试不是软件开发的新概念,在1970年就一直存在,屡屡被证明是最理想的方法之一。
本系列将分成3节:
- 单元测试基础知识
- 打破依赖,使用模拟对象,桩对象,测试框架
- 创建优秀的单元测试
本节索引:
单元测试与集成测试
单元测试几乎总是基于框架来写的,因为框架可以为我们提供统一的API来管理测试。
常用的框架有Unit Test(MS Test),NUnit(开源)
定义
单元测试是一段代码调用另一段代码,随后检验一些假设的正确性。(单元指的是一个方法或函数)
集成测试是指把2个或多个互相依赖的软件模块作为一组进行测试。
优秀的单元测试准则
- 自动的,可重复
- 容易实现
- 持续可用
- 简单
- 快速
测试驱动(TDD)开发
对于TDD确切的含义,有很多不同的观点,有人觉得就是测试优先的开发,有人觉得意味着大量的测试,有人觉得是一种设计方法。
TDD的流程:
写测试 写代码 重构 写下一个测试
它显示了TDD是增量性质的,每次一小步,最终完成高质量的软件。(重构可以在完成每个测试后进行,也可以在完成几个测试后进行。重构是非常有价值意义的。)
TDD的优点:
- 较高的代码测试覆盖率
- 测试是可信赖的
- 辅助设计,减少代码复杂度
MS Test和NUnit
所有的测试框架都共享相同的核心特性:Test Declaration, Test Execution, and Assertions.
在.Net中一般使用特性标签来添加额外的信息,下面就是MS Test和NUnit在特性标签上不同的地方。
MS Test Attribute | NUnit Attribute | 用途 |
[TestClass] | [TestFixture] | 定义一个测试类,里面可以包含很多测试函数和初始化、销毁函数(以下所有标签和其他断言)。 |
[TestMethod] | [Test] | 定义一个独立的测试函数。 |
[ClassInitialize] | [TestFixtureSetUp] | 定义一个测试类初始化函数,每当运行测试类中的一个或多个测试函数时,这个函数将会在测试函数被调用前被调用一次(在第一个测试函数运行前会被调用)。 |
[ClassCleanup] | [TestFixtureTearDown] | 定义一个测试类销毁函数,每当测试类中的选中的测试函数全部运行结束后运行(在最后一个测试函数运行结束后运行)。 |
[TestInitialize] | [SetUp] | 定义测试函数初始化函数,每个测试函数运行前都会被调用一次。 |
[TestCleanup] | [TearDown] | 定义测试函数销毁函数,每个测试函数执行完后都会被调用一次。 |
[AssemblyInitialize] | -- | 定义测试Assembly初始化函数,每当这个Assembly中的有测试函数被运行前,会被调用一次(在Assembly中第一个测试函数运行前会被调用)。 |
[AssemblyCleanup] | -- | 定义测试Assembly销毁函数,当Assembly中所有测试函数运行结束后,运行一次。(在Assembly中所有测试函数运行结束后被调用) |
[DescriptionAttribute] | [Category] | 定义标识分组。 |
第一个单元测试
安装
对于MS Test,只要安装VS则会自动安装。在工具栏==测试==窗口==测试资源管理器打开。
对于NUnit,点击链接,下载安装即可。
编码
- 配置对象
- 操作对象
- 断言结果
- [TestClass]
- public class BlogTests
- {
- public DbContext Db { get; set; }
- /// <summary>
- /// 每个测试方法执行前都会执行
- /// </summary>
- [TestInitialize]
- public void Init()
- {
- //1 配置对象
- Db = new DbContext();
- }
- [TestMethod]
- public void TestAdd()
- {
- var blog = new Blog { Title = "单元测试的艺术", Content = "单元测试是一门艺术" };
- //2 操作对象
- Db.Add(blog);
- //3 断言结果
- Assert.IsTrue(blog.Id > );
- }
- /// <summary>
- /// 每个测试方法执行后都会执行
- /// </summary>
- [TestCleanup]
- public void Clean()
- {
- Db = null;
- }
- }
异常的测试
有时候,测试里面上需要抛出异常,这是业务上的正确性。在单元测试里,也有对应特性用来实现。如
- [ExpectedException(typeof(OutOfMemoryException), AllowDerivedTypes = true)]//默认异常的子类也会不通过测试的
- [TestMethod]
- public void TestAdd()
- {
- var blog = new Blog { Title = "单元测试的艺术", Content = "单元测试是一门艺术" };
- //2 操作对象
- Db.Add(blog);
- throw new OutOfMemoryException();
- //3 断言结果
- Assert.IsTrue(blog.Id > );
- }
忽略的测试
有时候,测试写的有问题,代码没问题。我们可以暂时忽略该测试
- [Ignore]
- [TestMethod]
- public void TestAdd()
- {
- var blog = new Blog { Title = "单元测试的艺术", Content = "单元测试是一门艺术" };
- //2 操作对象
- Db.Add(blog);
- throw new OutOfMemoryException();
- //3 断言结果
- Assert.IsTrue(blog.Id > );
- }
对测试分组
当我们只想测试某一类测试的时候,也有对应的特性
- [TestCategory("change db")]
- [TestMethod]
- public void TestAdd()
- {
- var blog = new Blog { Title = "单元测试的艺术", Content = "单元测试是一门艺术" };
- //2 操作对象
- Db.Add(blog);
- //3 断言结果
- Assert.IsTrue(blog.Id > );
- }
- [TestCategory("no change")]
- [TestMethod]
- public void TestRead()
- {
- //2 操作对象
- var blogs = Db.GetBlogs();
- //3 断言结果
- Assert.IsTrue(blogs.Length > );
- }
运行选定的测试即可
测试
命名规范
SUT Kind | SUT |
项目 | 新建一个【被测项目】.Tests的测试项目 |
类 | 至少为每个被测试类新建一个【被测类名】Tests的类 |
方法 |
至少为每个方法名新建一个【方法名】【测试场景】【预期行为】的方法 或者使用Test【方法名】的简单命名 |
备注:SUT("system under test")代表被测系统,有些人喜欢CUT("code under test")。通常SUT。
本文作者:Never、C
本文链接:http://www.cnblogs.com/neverc/p/4742654.html
[Test] 单元测试艺术(1) 基础知识的更多相关文章
- 在Eclipse在使用JUnit4单元测试(0基础知识)
自这篇文章: http://www.devx.com/Java/Article/31983/0/page/1 我们在编写大型程序的时候,须要写成千上万个方法或函数.这些函数的功能可能非常强大,但我们在 ...
- selenium自动化基础知识
什么是自动化测试? 自动化测试分为:功能自动化和性能自动化 功能自动化即使用计算机通过编码的方式来替代手工测试,完成一些重复性比较高的测试,解放测试人员的测试压力.同时,如果系统有不份模块更改后,只要 ...
- ReactiveCocoa基础知识内容
本文记录一些关于学习ReactiveCocoa基础知识内容,对于ReactiveCocoa相关的概念如果不了解可以网上搜索:RACSignal有很多方法可以来订阅不同的事件类型,ReactiveCoc ...
- [Test] 单元测试艺术(2) 打破依赖,使用模拟对象,桩对象,隔离框架
在上节中,完成了第一个单元测试,研究了各种特性,在本节,将介绍一些更实际的例子.SUT依赖于一个不可操控的对象,最常见的例子是文件系统,线程,内存和时间等. 本系列将分成3节: 单元测试基础知识 打破 ...
- web前端基础知识及快速入门指南
web前端基础知识及快速入门指南 做前端开发有几个月了,虽然说是几个月,但是中间断断续续的上课.考试以及其它杂七杂八的事情,到现在居然一直感觉自己虽然很多前端的知识很眼熟,却也感觉自己貌似也知识在门口 ...
- Spring框架基础知识
本人博客文章网址:https://www.peretang.com/basic-knowledge-of-spring-framework/ Spring框架简介 Spring , 一个开源的框架 , ...
- Android查缺补漏(IPC篇)-- 进程间通讯基础知识热身
本文作者:CodingBlock 文章链接:http://www.cnblogs.com/codingblock/p/8479282.html 在Android中进程间通信是比较难的一部分,同时又非常 ...
- 韩天峰博客 php基础知识学习记录
http://rango.swoole.com 写好PHP代码真的不容易,给大家几个建议: 慎用全局变量,全局变量不好管理的,会导致你的代码依赖于全局变量,而耦合度太高. 一定不要复制粘贴代码,可重用 ...
- Magento 架构基础知识概述
Megento 架构基础知识概述 Magento整合了面向对象的基于PHP的应用程序的核心架构原则.这些一般原则的综合讨论既有在线的,也有印刷形式.以下讨论主要关注这些主题如何直接应用于Magento ...
随机推荐
- 搞了个基于zookeeper的Leader/Follower切换Demo
基于zookeeper写了个Leader选举类库demo,场景如下: 上图中的Program1..4可以部署在1台server上,也可以部署在多台server上,也可以是一个进程中的多个线程. 运行效 ...
- CSS计数器的趣味时光
CSS计数器是“啊太好了,竟不知道CSS可以做这啊”这类非常有趣的众多特性之一.简言之,用CSS使你持续某增加某个量,而无需JavaScript. 简单计数器 我们从这个简单的分页示例开始: 你见到的 ...
- 高并发WCF配置
在使用WCF做服务接口时,TCP模式肯定比Http效率高,Binary/MTOM格式的绑定也会Text格式的绑定高效. 两个endpoint,一个用来调试:ms-mex的binding是用来方便WCF ...
- hadoop错误之ClassNotFoundException
http://www.cnblogs.com/kaizhangzhang/p/3495438.html 在win7下运行hadoop-1.1.2 worldcount代码的时候出现下面的错误,折腾了差 ...
- dwz_bootstrap + thinkphp
http://www.thinkphp.cn/code/936.html 回去继续学习 SuperWebSocket
- Pro ASP.NET MVC –第四章 语言特性精华
C#语言有很多特性,并不是所有的程序员都了解本书我们将会使用的C#语言特性.因此,在本章,我们将了解一下作为一个好的MVC程序员需要了解C#语言的特性. 每个特性我们都只是简要介绍.如果你想深入了解L ...
- 入手Cubieboard2之制作最小Linux系统
前言 昨天终于入手了一块Cubieboard2板子,今年4月入职从事的就是与之相关的工作,因此趁现在有时间就好好熟悉一下. 一.主机环境 1.PC主机WIN 7旗舰版 1.虚拟机VM7.0 2.ubu ...
- asp.net首页设置
在web.config中设置首页 <configuration> <system.web> <compilation debug="true" tar ...
- Android NDK中的C++调试踩坑标记
RT, Android NDK中的C++调试, GDB调试比较麻烦,在ADT Eclipse中: 1.配置好NDK给工程加上Native Support 2.编译中加上NDK_DEBUG=1 3.然后 ...
- 支付SDK的安全问题——隐式意图可导致钓鱼攻击
该漏洞涉及到app所使用的intent和intent filter. intent是一个可用于从一个app组件请求动作或处理事件的“消息对象”.Intent负责对应用中一次操作的动作.动作涉及数据. ...