.net持续集成测试篇之Nunit常见断言
Nunit测试基础之简单断言
在开始本篇之前需要补充一些内容,通过前面搭建Nunit测试环境我们知道要使一个方法成为单元测试方法首先要在此方法所在类加上TestFixture注解,并且在该方法上添加上Test注解.
然而还有一点需要注意:所有进行单元测试的方法必须标识为public访问级别,否则无法识别为单元测试方法
此外,单元测试方法还有以下特征
- 单元测试方法不带返回参数,也即都是Void类型
由于单元测试方法都是用来断言特定状态的,因此返回值是没有意义的.此外也不要尝试在一个单元测试方法中调用另一个,这样做违反的单元测试的初衷(一旦出现错误不知道是哪个方法出出现的,还需要借助单元调用去发现是哪个方法出现的) 单元测试方法不能带有参数
这里说的不能是指不能像普通方法一样带有普通的参数(可以带基于注解的特殊参数)
如果像普通方法一样带参数,虽然编译能通过,但是运行时会抛出异常.单元测试方法不能重载
这里说的不能是不应该,实践中是可以的,但是重载方法会带来无尽的麻烦,读者可以自己实践一下.
进行单元测试无非就是对不同参数引起方法出现不同结果的断言(一般情况下所有的单元测试方法都有断言)下面我们来看Nunit中最基本最常用的断言
基本断言
Assert.True()
Assert.True用于断言布尔参数是否为true
Assert.True的重载方法还支持可空布尔参数
Assert.True还支持自定义错误提示
上面代码改为如下
如果返回错误的时候,我们自定义的错误信息就会显示出来.
其它的断言方法也大都有此重载
Assert.IsTrue
此断言方法为Assert.True的亲兄弟,二者功能一模一样.
ssert.False
与Assert.True断言状态相反,断言某一参数的结果为false
这里需要特别说明的是,单元测试应该力求简单,明了,断言尤其如此.
上面的断言还也可以写成
Assert.False(!firstCondition);
这和断言变量firstCondition为true最终功能一样,但是看上去很不直接明了,通常情况下我见到Assert.False第一反应就是断言一个变量为False,这里则反其道行之,实际上是断言一个变量为true,这种情况应当避免.
Assert.IsFalse
Assert.False的亲兄弟,二者表现一模一样
Nunit Assert类还有还多其它的前面带有Is的方法,它们都和不带Is的一模一样,其中带Is的是为了兼容老版本写法.
Assert.Null
用于断言一个变量是否为null,这里不再举例,但是实际中用的却比较多.
Assert.NotNull
用于断言一个变量不是null,它和Assert.Null()功能相同,只是断言的状态相反.
Nunit里还有其它的前缀有Not的方法,它和不带Not的方法用法一样,只是断言的状态相反
Assert.Throws
用于断言特定方法在运行的时候会抛出异常.此方法有泛型版本,异步版本,这里仅对异步版本进行说明
由于示例越来越复制,我们不能只在测试方法内写一些简单代码进行测试了,这里我们新建一个Person类如下
这个类里面包含一个WhetherNameContainsB方法,用于判断实例的Name是否包含字母B,
这个方法里面有三个逻辑分支,单元测试的时候每一个都要覆盖到,这里我们断言如果name为null则抛出ArgumentNullException
我们编写如下单元测试方法
运行这个测试,则会返回成功状态,因为预期的异常出现了.
Assert.IsEmpty
用于断言字段串是否为空字符串.
Assert.Positive
用于断言数字类型(int,long,float,double,decimal等)为正数(大于零的数)
其实很多断言都可以断言都可以用Assert.True来完成,比如断言一个数是否为正数,可以用Assert.True(a>0),这里由于a只是一个普通变量,使用a>0作为条件主义仍然十分清析,然而到了后面有我们不仅要判断一个变通变量,还要判断lambda表达式,如果条件过于复杂,则语义会变得不是特别清析了,使用Assert自带的静态方法主义会更加清析,可读性更高.
Assert.Negative
用于断言数字类型为负数(小于零,不包括零)
Assert.Zero
用于断言数字类型为数字零
Assert.NotZero
用于断言数字类型不是零.
很多时候,Not包含的范围非常广,进行单元测试是为了在开发阶段找出问题,解决问题,因此断言的范围越窄越好,我们不能仅仅让单元测试通过了事.
比如一个方法返回的结果是数字类型,我们要断定它是正数?大于某一个数的正数?在一定范围的正数?是一个具体的正数?而不能简单的是零,不是零.当然这还要根据业务本身来确实,有些时候范围可能确实很大,但是一定要注意单元测试原则.
Assert.Greater(OrEqual)
用于断言数字类型的变量大于(或者等于)某一个值
Assert.Less(OrEqual)
用于断言数字类型小于(或者等于)某一值
Assert.Contains
用于断言集合中是否包含某一元素.
比如以下方法,用于断言字符串数组中是否包含特定字符串
Assert.AreSame
用于断言两个对象是否相等
这个静态方法并没有提供重载参数用于指定一个比较器来比较引用对象的相等性,需要实现equals和gethashcode方法才能得到预期结果,但在实际中我们往往把比较器放在类外边,如何在比较引用对象的时候加载一个比较器在后面章节会有介绍,这里先略过.
Nunit测试基础之复杂断言
Nunit测试基础之复杂断言
上面一篇我们讲解了一些基本断言,利用这些断言我们就可以进行单元测试了,然而仅仅使用简单断言还是不够的,如果逻辑复杂度较高,使用简单的断言会导致单元测试代码量增加,最终导致单元测试本身过于复杂和难以维护.需要说明的是这里所说的复杂断言仍然在Assert的静态方法里面,本身也不是特别复杂,只是比前面讲的秒复杂一些,只是如果没有了这些方法,一些特殊功能实现起来比较费劲基本无法实现.
下面就介绍一下这些方法.
Assert.Catch
Assert.Catch有泛型和异步方法,这里只介绍其泛型方法.很多即使经常使用单元测试功能的人也未必用过这个方法.
其实这个方法和Assert.Throw用法上类似,只是有一点不同的是要测试的方法里的异常可以是catch到的异常的子类,实际开发中,如果我们能确立异常的类型,则最好捕获具体类型异常,然而不能排除有一些不够规范的代码整段代码被一个try catch包围,这时候不一定能够捕获到想要的特定异常,这时候可以使用Assert.Catch
以上代码类似上一节中讲throw时使用的代码,只是这里泛型参数里是Exception而不是具体的异常信息,我们运行这段代码,依然能够测试通过.
在单元测试中,期待的状态越具体越好,然而由于种种原因(比如立项时候没有对代码规范做过多要求,开发者水平不高,要测试的代码是别人写的,写单元测试的人对其中逻辑并不是特别清楚等)我们无法做到非常具体,这个时候可以把要获得的状态放宽以后,待条件完备了再修改单元测试以进一步收窄状态.
Assert.Ignore
Assert.Ignore和Ignore注解功能类似,可以在测试的时候忽略一个单元测试.有些情况下我们需要暂时忽略一个测试,比如说要进行测试的内容有一个外部依赖,现在外部依赖暂时不可用,如果我们不忽略的话测试将会失败,在自动化环境下,失败将导致无法进行下一步动作,此时我们可以暂时忽略这个测试.
忽略的测试前面有一个 黄色叹号标志,警示我们需要注意.
Assert. Fail
我们先看一下面一段代码
在这个单元测试本身使用到了try catch,我们知道WhetherNameContainsB方法在Person类的Name没有提供值的情况下会抛出异常,然而我们的代码并没有断言这个异常存在,此时由于catch代码块存在,会把异常吞掉,因此最终我们断言person的Age为正数的时候将会通过(我们在构造类的时候设置了Age为32)
这显然不行的,这时候我把们Assert.Fail(e.Message)取消注释,测试便会变成失败状态.
Assert.IsNaN
用于断言一个Double类型数字是否是NaN
虽然实际业务中我们并不会写以上代码,但是如果除数和被除数是通过复杂计算得来的则有可能除数和被除数都是零.
Assert.IsInstanceOf
用于断言一个对象是否是指定类型的实例,
如上psn是Person类的一个实例,而Person继承自Object,因此psn也是Object类的实例
Assert.IsAssignableFrom
此方法和以上方法作用相反,它用来断言指定类型是当前对象类型的子类.(Assert.IsInstanceOf判断的是当前对象是指定类型的子类)
这个方法语义不是很明确,很容易搞晕,使用的时候需要特别注意
Assert.Warn
用于使一个测试通过,但是出现警示信息.
.net持续集成测试篇之Nunit常见断言的更多相关文章
- .net持续集成测试篇之Nunit文件断言、字符串断言及集合断言
使用前面讲过的方法基本上能够完成工作中的大部分任务了,然而有些功能实现起来还是比较麻烦的,比如说字符串相等性比较不区分大小写,字符串是否匹配某一正则规则,集合中的每一个(某一个)元素是否符合特定规则等 ...
- .net持续集成测试篇之Nunit that断言
系列目录 that是Nunit的新语法,语义上不如简单断言,使用上也更加复杂,但是其功能更加强大. 其基本语法如下代码片段示: [Test] public void DemoTest() { bool ...
- .net持续集成测试篇之Nunit 测试配置
系列目录 在开始之前我们先看一个陷阱 用到的Person类如下 public class Person:IPerson { public string Name { get; set; } publi ...
- .net持续集成测试篇之Nunit参数化测试
系列目录 在进行单元测试的时候,很多时候,很多时候我们都是在单元测试方法内部提供特定的值,但是这样测试往往造成样本数不足从而导致覆盖的结果不够全面,很多时候我们更想提供来自外部的,满足条件的一组值来进 ...
- .netcore持续集成测试篇之开篇简介及Xunit基本使用
系列目录 为了支持跨平台,微软为.net平台提供了.net core test sdk,这样第三方测试框架诸如Nunit,Xunit等只需要按照sdk提供的api规范进行开发便可以被dotnet cl ...
- .netcore持续集成测试篇之web项目验收测试
系列目录 通过前面的单元测试,我们能够保证项目的基本模块功能逻辑是正常的,通过集成测试能够保证接口的请求是正常的.然而最终项目交付我们还需要对项目进行页面的行为进行测试,比如页面布局是否正常,按钮是否 ...
- .netcore持续集成测试篇之搭建内存服务器进行集成测试一
系列目录 在web项目里,我们把每一层的代码的单元测试都通过并不代表程序能正常运行,因为这个过程缺失了http管道,很多时候我们还还需要把项目布在iis环境中或者在vs里启动iis express服务 ...
- .netcore持续集成测试篇之Xunit结合netcore内存服务器发送post请求
系列目录 Web项目中,很多与用户数据交互的请求都是Post请求,想必大家都用过HttpClient构造过post请求,这里并不对HttpClient做详细介绍,只介绍一些常用的功能.并结合AutoF ...
- .netcore持续集成测试篇之MVC测试
前面我们讲的很多单元测试的的方法和技巧不论是在.net core和.net framework里面都是通用的,但是mvc项目里有一种比较特殊的类是Controller,首先Controller类的返回 ...
随机推荐
- java集合知识点总结
下面是java中常见的集合: List--列表:内部元素有序,可以重复, ArrayList:线程不安全,效率高.数据结构是线性表,底层结构是顺序表,也就是数组,有唯一的下标来指定元素的位置,查询快, ...
- Node中的cookie的使用
1.为什么使用cookie? 因为HTTP是无状态协议.简单地说,当你浏览了一个页面,然后转到同一个网站的另一个页面,服务器无法认识到,这是同一个浏览器在访问同一个网站.每一次的访问,都是没有任何关系 ...
- Linux/windows com串口 java 接收数据 并解析 web程序
1.首先应公司要求再 com 口本来使用 .net 由于 .net 适用 linux 太麻烦 改为java 准备工作 准备 RXTXconmm.jar(版本很重要) 因为版本问题我搞了一天. 主要讲述 ...
- 44 | 测试先行:测试驱动开发(TDD)
- leadcode的Hot100系列--二叉树创建和遍历
很多题目涉及到二叉树,所以先把二叉树的一些基本的创建和遍历写一下,方便之后的本地代码调试. 为了方便,这里使用的数据为char类型数值,初始化数据使用一个数组. 因为这些东西比较简单,这里就不做过多详 ...
- 解决Spring的java项目打包后执行出现“无法读取方案文档...“、“原因为 1) 无法找到文档; 2) 无法读取文档; 3) 文档的根元素不是...”问题
问题 一个用Spring建的java项目,在Eclipse或idea中运行正常,为什么打包后运行出现如下错误呢? 2019/07/10/19:04:07 WARN [main] org.springf ...
- Codeforces Gym101341K:Competitions(DP)
http://codeforces.com/gym/101341/problem/K 题意:给出n个区间,每个区间有一个l, r, w,代表区间左端点右端点和区间的权值,现在可以选取一些区间,要求选择 ...
- django基础知识之认识MVT MVC:
MVT Django是一款python的web开发框架 与MVC有所不同,属于MVT框架 m表示model,负责与数据库交互 v表示view,是核心,负责接收请求.获取数据.返回结果 t表示templ ...
- javascript高级笔记——内含事件,DOM,BOM等
JavaScript高级笔记 1,DOM的简单学习 1.1,功能:用于控制HTML文档的内容: 1.2,获取页面标签对象:Element *document.getElementById(" ...
- restapi(1)- 文件上传下载服务
上次对restapi开了个头,设计了一个包括了身份验证和使用权限的restful服务开发框架.这是一个通用框架,开发人员只要直接往里面加新功能就行了.虽然这次的restapi是围绕着数据库表的CRUD ...