单元测试不是软件开发的新概念,在1970年就一直存在,屡屡被证明是最理想的方法之一。

本系列将分成3节:

  1. 单元测试基础知识
  2. 打破依赖,使用模拟对象,桩对象,测试框架
  3. 创建优秀的单元测试

本节索引:

单元测试与集成测试

单元测试几乎总是基于框架来写的,因为框架可以为我们提供统一的API来管理测试。

常用的框架有Unit Test(MS Test),NUnit(开源)

定义

单元测试是一段代码调用另一段代码,随后检验一些假设的正确性。(单元指的是一个方法或函数)

集成测试是指把2个或多个互相依赖的软件模块作为一组进行测试。

优秀的单元测试准则

  1. 自动的,可重复
  2. 容易实现
  3. 持续可用
  4. 简单
  5. 快速

测试驱动(TDD)开发

对于TDD确切的含义,有很多不同的观点,有人觉得就是测试优先的开发,有人觉得意味着大量的测试,有人觉得是一种设计方法。

TDD的流程:

写测试 写代码 重构 写下一个测试

它显示了TDD是增量性质的,每次一小步,最终完成高质量的软件。(重构可以在完成每个测试后进行,也可以在完成几个测试后进行。重构是非常有价值意义的。)

TDD的优点:

  1. 较高的代码测试覆盖率
  2. 测试是可信赖的
  3. 辅助设计,减少代码复杂度

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,点击链接,下载安装即可。

编码

  1. 配置对象
  2. 操作对象
  3. 断言结果
[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) 基础知识的更多相关文章

  1. 在Eclipse在使用JUnit4单元测试(0基础知识)

    自这篇文章: http://www.devx.com/Java/Article/31983/0/page/1 我们在编写大型程序的时候,须要写成千上万个方法或函数.这些函数的功能可能非常强大,但我们在 ...

  2. selenium自动化基础知识

    什么是自动化测试? 自动化测试分为:功能自动化和性能自动化 功能自动化即使用计算机通过编码的方式来替代手工测试,完成一些重复性比较高的测试,解放测试人员的测试压力.同时,如果系统有不份模块更改后,只要 ...

  3. ReactiveCocoa基础知识内容

    本文记录一些关于学习ReactiveCocoa基础知识内容,对于ReactiveCocoa相关的概念如果不了解可以网上搜索:RACSignal有很多方法可以来订阅不同的事件类型,ReactiveCoc ...

  4. [Test] 单元测试艺术(2) 打破依赖,使用模拟对象,桩对象,隔离框架

    在上节中,完成了第一个单元测试,研究了各种特性,在本节,将介绍一些更实际的例子.SUT依赖于一个不可操控的对象,最常见的例子是文件系统,线程,内存和时间等. 本系列将分成3节: 单元测试基础知识 打破 ...

  5. web前端基础知识及快速入门指南

    web前端基础知识及快速入门指南 做前端开发有几个月了,虽然说是几个月,但是中间断断续续的上课.考试以及其它杂七杂八的事情,到现在居然一直感觉自己虽然很多前端的知识很眼熟,却也感觉自己貌似也知识在门口 ...

  6. Spring框架基础知识

    本人博客文章网址:https://www.peretang.com/basic-knowledge-of-spring-framework/ Spring框架简介 Spring , 一个开源的框架 , ...

  7. Android查缺补漏(IPC篇)-- 进程间通讯基础知识热身

    本文作者:CodingBlock 文章链接:http://www.cnblogs.com/codingblock/p/8479282.html 在Android中进程间通信是比较难的一部分,同时又非常 ...

  8. 韩天峰博客 php基础知识学习记录

    http://rango.swoole.com 写好PHP代码真的不容易,给大家几个建议: 慎用全局变量,全局变量不好管理的,会导致你的代码依赖于全局变量,而耦合度太高. 一定不要复制粘贴代码,可重用 ...

  9. Magento 架构基础知识概述

    Megento 架构基础知识概述 Magento整合了面向对象的基于PHP的应用程序的核心架构原则.这些一般原则的综合讨论既有在线的,也有印刷形式.以下讨论主要关注这些主题如何直接应用于Magento ...

随机推荐

  1. 15个最好的PDF转word的在线转换器,将PDF文件转换成doc文件

    PDF是一种文件格式,包含文本,图像,数据等,这是独立于操作系统的文件类型.它是一个开放的标准,压缩,另一方面DOC文件和矢量图形是由微软文字处理文件.该文件格式将纯文本格式转换为格式化文档.它支持几 ...

  2. 用node-webkit 开发 PC 客户端

      7月 3 2013 导言 node-webkit 是一个很神奇的桌面客户端项目,正如这个项目的名字,这个项目是由node 和 webkit 构成,简单来说,就是你可以用HTML 5和 node 进 ...

  3. IE6-IE11兼容性问题列表及解决办法总结

    相比IE6-IE9那版,主要添加IE10和IE11的新变化. 以下是目录及下载链接: 目录 概述 2 第一章:HTML 3 第一节:IE7-IE8更新 3 1. 如果缺少结束标记的 P 元素后跟 TA ...

  4. go2shell的安装与修改默认terminal方法

    go2shell的安装与修改默认terminal方法   1. 安装go2shell后,打开finder的application文件夹,找到go2shell 2. 按住command,用鼠标将go2s ...

  5. c#列举和迭代器

    列举 - Enumeration 迭代器是一个值序列(集合)上的一个只读且只向前移动的游标.迭代器要么实现了IEnumerator接口,要么实现了IEnumerator<T>接口. 从技术 ...

  6. git 基本配置及使用

    GIT是个很方便的开发伴侣,这里 随笔记录下GIT工具的基本使用,也希望能帮到别人更快速的使用GIT. 一,安装软件   toroise是最常用也最习惯的工具了,已经是有支持GIT了. 二,生成密钥文 ...

  7. IE11 Enterprise Mode

    对IE11引入的Enterprise Mode进行了一些总结,对查阅的一些参考资料直接引用了英文,需要注意的地方用中文进行了一些注解.供大家参考. 1. The purpose of introduc ...

  8. Duilib技巧:背景图片平铺

    贴图的描述 方式有两种    // 1.aaa.jpg    // 2.file='aaa.jpg' res='' restype='0' dest='0,0,0,0' source='0,0,0,0 ...

  9. 配置Pylint for Python3.5

    事件的缘由是因为在Ubuntu16.04 下面安装了Visual Studio Code, 再编辑的时候说需要Pylint来检查语法,我系统的默认的Python 版本是python2,而我现在正在学习 ...

  10. 从逆向的角度去理解C++虚函数表

    很久没有写过文章了,自己一直是做C/C++开发的,我一直认为,作为一个C/C++程序员,如果能够好好学一下汇编和逆向分析,那么对于我们去理解C/C++将会有很大的帮助,因为程序中所有的奥秘都藏在汇编中 ...