推荐轻量友好的.NET测试断言工具Shouldly
Shouldly是一个轻量的断言(Assertion)框架,用于补充.NET框架下的测试工具。Shouldly将焦点放在当断言失败时如何简单精准的给出很好的错误信息。
Shouldly在GitHub的开源地址:https://github.com/shouldly/shouldly
Shouldly的官方文档:http://docs.shouldly-lib.net/
为什么要Shouldly?
我们知道通常测试代码中一个断言是这样写的:
Assert.That(contestant.Points, Is.EqualTo());
当断言失败的时候,我们会得到这样的信息:
Expected but was
这样的信息让人烦恼的是,它够简练,但显然信息不够充分,可读性不高。
Shouldly充分利用了.NET框架的扩展方法,提供了更友好的处理方式。
用Shouldly编写的断言是这样的:
contestant.Points.ShouldBe();
其中ShouldBe是一个扩展方法,也可以认为是一个易于理解的语法词汇。当断言失败的时候,我们会得到这样的信息:
contestant.Points should be but was
Shouldly的优势
下面的一个例子将两种断言方式放在一起,通过对比更容易发现Shouldly的好处:
Assert.That(map.IndexOfValue("boo"), Is.EqualTo()); // -> Expected 2 but was 1
map.IndexOfValue("boo").ShouldBe(); // -> map.IndexOfValue("boo") should be 2 but was 1
Shouldly使用ShouldBe语句中的变量来报告错误,这使得更容易诊断。
另一个例子,如果你需要比较两个集合,采用Shouldly写法如下:
(new[] { , , }).ShouldBe(new[] { , , });
显然断言会失败,因为这两个集合并不相同。但Shouldly不仅如此,它会告诉你两个集合的差异所在:
should be
[, , ]
but was
[, , ]
difference
[, , **]
如果你想检查一个特殊的方法调用,它会或者不会抛出异常,它可以简单地这样写:
Should.Throw<ArgumentOutOfRangeException>(() => widget.Twist(-));
这样就可以接触到异常,借此帮助你调试出潜在的异常来源。
详细用法
Shouldly断言框架提供了相等、迭代、动态变量、字符串、字典、任务/异步,以及异常等多方面的支持。要详细的了解这些可以访问Shouldly的官方文档:http://docs.shouldly-lib.net/
后续的断言例子基于下面的范例类:
namespace Simpsons
{
public abstract class Pet
{
public abstract string Name { get; set; } public override string ToString()
{
return Name;
}
}
} namespace Simpsons
{
public class Cat : Pet
{
public override string Name { get; set; }
}
} namespace Simpsons
{
public class Dog : Pet
{
public override string Name { get; set; }
}
} namespace Simpsons
{
public class Person
{
public string Name { get; set; }
public int Salary { get; set; } public override string ToString()
{
return Name;
}
}
}
Equality 相等
ShouldBe
[Test]
public void ShouldBe()
{
var theSimpsonsCat = new Cat() { Name = "Santas little helper" };
theSimpsonsCat.Name.ShouldBe("Snowball 2");
}
失败信息:
Shouldly.ChuckedAWobbly :
theSimpsonsCat.Name
should be
"Snowball 2"
but was
"Santas little helper"
ShouldNotBe
[Test]
public void ShouldNotBe()
{
var theSimpsonsCat = new Cat() { Name = "Santas little helper" };
theSimpsonsCat.Name.ShouldNotBe("Santas little helper");
}
失败信息:
Shouldly.ChuckedAWobbly :
theSimpsonsCat.Name
should not be
"Santas little helper"
but was
"Santas little helper"
ShouldBeOfType
[Test]
public void ShouldBeOfType()
{
var theSimpsonsDog = new Cat() { Name = "Santas little helper" };
theSimpsonsDog.ShouldBeOfType<Dog>();
}
失败信息:
Shouldly.ChuckedAWobbly :
theSimpsonsDog
should be of type
Simpsons.Dog
but was
Simpsons.Cat
Enumberable 迭代
用于对列表集合进行断言
ShouldAllBe
[Test]
public void IEnumerable_ShouldAllBe_Predicate()
{
var mrBurns = new Person() { Name = "Mr.Burns", Salary=};
var kentBrockman = new Person() { Name = "Homer", Salary = };
var homer = new Person() { Name = "Homer", Salary = };
var millionares = new List<Person>() {mrBurns, kentBrockman, homer}; millionares.ShouldAllBe(m => m.Salary > );
}
失败信息:
Shouldly.ChuckedAWobbly :
millionares
should all be an element satisfying the condition
(m.Salary > )
but does not
ShouldContain
[Test]
public void IEnumerable_ShouldContain()
{
var mrBurns = new Person() { Name = "Mr.Burns", Salary=};
var kentBrockman = new Person() { Name = "Homer", Salary = };
var homer = new Person() { Name = "Homer", Salary = };
var millionares = new List<Person>() {kentBrockman, homer}; millionares.ShouldContain(mrBurns);
}
失败信息:
Shouldly.ShouldAssertException :
millionares
should contain
Mr.Burns
but does not
ShouldContain(Predicate)
[Test]
public void IEnumerable_ShouldContain_Predicate()
{
var homer = new Person() { Name = "Homer", Salary = };
var moe = new Person() { Name = "Moe", Salary=};
var barney = new Person() { Name = "Barney", Salary = };
var millionares = new List<Person>() {homer, moe, barney}; // Check if at least one element in the IEnumerable satisfies the predicate
millionares.ShouldContain(m => m.Salary > );
}
失败信息:
Shouldly.ChuckedAWobbly :
millionares
should contain an element satisfying the condition
(m.Salary > )
but does not
Dynamic 动态对象
ShouldHaveProperty
[Test]
public void DynamicShouldHavePropertyTest()
{
var homerThinkingLikeFlanders = new ExpandoObject();
DynamicShould.HaveProperty(homerThinkingLikeFlanders, "IAmABigFourEyedLameO");
}
失败信息:
Shouldly.ChuckedAWobbly :
Dynamic Object
"homerThinkingLikeFlanders"
should contain property
"IAmABigFourEyedLameO"
but does not.
String 字符串
ShouldMatch
[Test]
public void ShouldMatch()
{
var simpsonDog = new Dog() { Name = "Santas little helper" };
simpsonDog.Name.ShouldMatch("Santas [lL]ittle Helper");
}
失败信息:
Shouldly.ChuckedAWobbly :
simpsonDog.Name
should match
"Santas [lL]ittle Helper"
but was
"Santas little helper"
ShouldBeNullOrEmpty
[Test]
public void ShouldBeNullOrEmpty()
{
var anonymousClanOfSlackJawedTroglodytes = new Person() {Name = "The Simpsons"};
anonymousClanOfSlackJawedTroglodytes.Name.ShouldBeNullOrEmpty();
}
失败信息:
Shouldly.ChuckedAWobbly :
anonymousClanOfSlackJawedTroglodytes.Name
should be null or empty
Dictionary 字典
ShouldNotContainKey
[Test]
public void ShouldNotContainKey()
{
var websters = new Dictionary<string, string>();
websters.Add("Chazzwazzers", "What Australians would have called a bull frog."); websters.ShouldNotContainKey("Chazzwazzers");
}
失败信息:
Shouldly.ChuckedAWobbly :
Dictionary
"websters"
should not contain key
"Chazzwazzers"
but does
ShouldContainKeyAndValue
[Test]
public void ShouldNotContainKey()
{
var websters = new Dictionary<string, string>();
websters.Add("Chazzwazzers", "What Australians would have called a bull frog."); websters.ShouldNotContainKey("Chazzwazzers");
}
失败信息:
Shouldly.ChuckedAWobbly :
Dictionary
"websters"
should not contain key
"Chazzwazzers"
but does
Task/Async 任务/异步
CompleteIn
[Test]
public void CompleteIn()
{
var homer = new Person() { Name = "Homer", Salary = };
var denominator = ;
Should.CompleteIn(() =>
{
Thread.Sleep();
var y = homer.Salary / denominator;
}, TimeSpan.FromSeconds());
}
失败信息:
System.TimeoutException : The operation has timed out.
Exceptions 异常
ShouldThrow
[Test]
public void ShouldThrowFuncOfTask()
{
var homer = new Person() { Name = "Homer", Salary = };
var denominator = ;
Should.Throw<DivideByZeroException>(() =>
{
var task = Task.Factory.StartNew(() => { var y = homer.Salary/denominator; });
return task;
});
}
失败信息:
Shouldly.ChuckedAWobbly :
Should
throw
System.DivideByZeroException
but does not
ShouldNotThrow(Func<Task>)
这个方法支持异步方法,并且会等待操作执行直到完成。
[Test]
public void ShouldNotThrowFuncOfTask()
{
var homer = new Person() { Name = "Homer", Salary = };
var denominator = ;
Should.NotThrow(() =>
{
var task = Task.Factory.StartNew(() => { var y = homer.Salary/denominator; });
return task;
});
}
失败信息:
Shouldly.ChuckedAWobbly :
Should
not throw
System.DivideByZeroException
but does
推荐轻量友好的.NET测试断言工具Shouldly的更多相关文章
- .NET测试断言工具Shouldly
.NET测试断言工具Shouldly .NET测试 Shouldly在GitHub的开源地址:https://github.com/shouldly/shouldly Shouldly的官方文档:ht ...
- 推荐轻量高效无依赖的开源JS插件和库
目录 图片 布局 音频视频 编辑器 轮播图 弹出层 表单 存储 动画 时间 其它 CDN 图片 baguetteBox.js - 是一个简单易用的响应式图像灯箱效果脚本.demo Lightgalle ...
- RestTemplate---Spring提供的轻量Http Rest 风格API调用工具
前言 今天在学习Spring Cloud的过程中无意发现了 RestTemplate 这个Spring 提供的Http Rest风格接口之间调用的模板工具类,感觉比Apache提供的HttpClien ...
- 五款轻量型bug管理工具横向测评
五款轻量型bug管理工具横向测评 最近正在使用的本地bug管理软件又出问题了,已经记不清这是第几次了,每次出现问题都要耗费大量的时间精力去网上寻找解决方案,劳心劳力.为了避免再次出现这样的情况,我决定 ...
- 推荐一个简单、轻量、功能非常强大的C#/ASP.NET定时任务执行管理器组件–FluentScheduler定时器
在C#WINFORM或者是ASP.NET的WEB应用程序中,根据各种定时任务的需求,比如:每天的数据统计,每小时刷新系统缓存等等,这个时候我们得应用到定时器这个东东. .NET Framework有自 ...
- Furatto – 轻量,友好的响应式前端开发框架
Furatto 是一个基于 Bootstrap & Foundation 的前端开发框架,用于快速开发网站.这个框架采用流行的扁平化设计和响应式设计.除了布局和网格之外,所有的主要元素都有预定 ...
- 推荐一款轻量小众却高效免费开源windows热键脚本语言Autohotkey
写在前面的话 Autohotkey是一款轻量小众但高效免费开源的windows热键脚本语言,游戏操纵.鼠标操作.键盘快捷重定义,快捷短语等等,只有你想不到,没有它做不到,神器中的神器呀,相见恨晚. 安 ...
- Vue.js:轻量高效的前端组件化方案
转发一篇尤老师对vue.js的介绍,了解vue.js的来龙去脉.不过现在已经是2.0了,也有添加一些新的东西,当然有些东西也改了. Vue.js:轻量高效的前端组件化方案 Vue.js 是我在2014 ...
- 基于netty轻量的高性能分布式RPC服务框架forest<下篇>
基于netty轻量的高性能分布式RPC服务框架forest<上篇> 文章已经简单介绍了forest的快速入门,本文旨在介绍forest用户指南. 基本介绍 Forest是一套基于java开 ...
随机推荐
- 安装vs2013以后,链接数据库总是报内存损坏,无法写入的错误
安装vs2013以后,链接数据库总是报内存损坏,无法写入的错误 这个错误几个月以前解决过一次,但是到又碰到的时候,竟然完全忘记当时怎么解决的了, 看来上了年纪记忆真是越来越不行了... 解决方案很简单 ...
- Linux设备驱动剖析之Input(四)
static void input_pass_event(struct input_dev *dev, unsigned int type, unsigned int code, int value) ...
- 导出程序界面(UI)到图片
无意间看到这个需求,查阅了相关文章,有两篇不错的博客给出了解决方案,地址如下: 1.在WPF程序中将控件所呈现的内容保存成图像 2.随心所欲导出你的 UI 界面到 PDF 文件 主要使用的接口: Si ...
- EPLAN 软件平台中的词“点“大全
1. 中断点(Interruption Point): 在原理图绘制时,如果当前绘图区域的空间不足,需要转到其它页面继续绘制,而这两页之间存在连续的"信息流"时,可以使用& ...
- 数轴上从左到右有n个点a[0],a[1]…,a[n-1],给定一根长度为L的绳子,求绳子最多能覆盖其中的几个点。要求算法复杂度为o(n)。
#include <iostream> using namespace std; int maxCover(int* a, int n, int l) { ; ; ; while(end ...
- 在内核中异步请求设备固件firmware的测试代码
在内核中异步请求设备固件firmware的测试代码 static void ghost_load_firmware_callback(const struct firmware *fw, void * ...
- WindowsServer2012桌面图标设置
1.win+R调出运行窗口 2.输入:rundll32.exe shell32.dll,Control_RunDLL desk.cpl,,0 即可
- SmartJS 系列规划分享和背景介绍
发布了smartjs后,有朋友问:“没看懂究竟是干嘛的”.唉,打击了,每次我都想高唱其实你不懂我的心. 今天把相关的东西都整理了一遍,给大家介绍一下.里面绝大多数都已经实现过,有些则是有新的思路重做或 ...
- WPF小记——DockPanel使用不当引起界面显示问题
使用以下代码,当TextBlock文本过长,引起Button的显示位置在可见区域以外: <Window x:Class="WpfApplication11.MainWindow&quo ...
- fzu 2107 Hua Rong Dao(状态压缩)
Problem 2107 Hua Rong Dao Accept: 106 Submit: 197 Time Limit: 1000 mSec Memory Limit : 32768 K ...