导读
为什么要编写自动化测试程序(Automated Tests)?
- 可以频繁的进行测试
- 可以在任何时间进行测试,也可以按计划定时进行,例如:可以在半夜进行自动测试。
- 肯定比人工测试要快。
- 可以更快速的发现错误。
- 基本上是非常可靠的。
- 测试代码与生产代码紧密结合。
- 使得开发团队更具有幸福感!
自动化测试的分类:
纵轴表示测试的深度,也就是说测试的细致程度。
横轴则表示测试的覆盖程度。
- Unit Test 单元测试, 它可以测试一个类,或者一个类的某个功能,它具有很好的深度,但是对整个应用来说它不具备很好的覆盖面。
- Integration Test 集成测试,它没有单元测试那么细致,但是具有相对较好的测试覆盖面。例如它可以测试功能的组合,以及像数据库或文件系统这样的外部资源等。
- Subcutaneous Test 皮下测试,这种测试作用于UI层的下面一层,这也意味着它对整个应用来说有很好的覆盖率,但是深度欠佳。那一个MVC结构的应用来说,它就是针对刚好在Controller下面一层的测试,对于Web service来说,它就是对节点下面那层的测试。
- UI测试,它的测试覆盖面很广,直接从UI层面进行测试,但是深度欠佳。
从速度来看 单元是最快的,而UI测试是最慢的。
从脆弱性来看 UI测试是最差的,程序修改后极有可能需要修改测试代码,而单元测试是最好的。
是测试行为还是测试私有方法(private method)?
public void IncreaseHeartBeatRate()
{
HeartBeatRate = CalculateHeartBeatRate() + ;
} private int CalculateHeartBeatRate()
{
var random = new Random();
return random.Next(, );
}
大多数情况下单元测试都应该是针对类的行为进行测试的,也就是public方法。当然也纯在不同的观点。
如果想要对private方法进行测试的话,是有很多缺点的:
- 首先需要修改方法的访问限制需要从private改为public,这就破坏了面向对象的封装性。
- 再者,这其实测试的是类的具体实现细节,而不是类的行为。如果我们想要对类的内部进行重构的话,就会破坏测试,导致测试也必须重构。如果必须对private方法进行测试,那么首先建议您把private修饰符改成internal,然后修改该项目(project)的AssemblyInfo.cs,它在项目的Debug或者Release文件夹下。代码如下:
[assembly: InternalsVisibleTo("Hospital.Tests")]
这表示Hospital.Tests这个测试项目可以访问该项目生产代码(production code)的internal方法。
测试的三个阶段 AAA
- Arrange,这里做一些先决的设定。例如创建对象实例,数据,输入等等。
- Act,在这里执行生产代码并返回结果。例如调用方法,或者设置属性(Properties)。
- Assert,在这里检查结果。测试通过或者失败。
xUnit.net
xUnit是一个测试框架,可以针对.net/core进行测试。
测试项目需引用被项目从而对其进行测试,测试项目同时需要引用xUnit库。测试编写好后,用Test Runner来运行测试。Test Runner可以读取测试代码,并且会知道我们所使用的测试框架,然后执行,并显示结果。目前可用的Test Runner包括vs自带的Test Explorer,或者dotnet core命令行,以及第三方工具,例如resharper等等。
xUnit支持的平台:
.net full, .net core, .net standard, uwp, xamarin.
xUnit的例子:
[Fact]
public void TestIncreaseHeartBeatRate()
{
var patient = new Patient(); // Arrange
patient.IncreaseHeartBeatRate(); // Act
Assert.InRange(patient.HeartBeatRate, , ); // Assert
}
安装配置xUnit.net
a.使用Visual Studio 2017
首先建立一个C# library项目,叫Hospital(下面部分截图有个拼写错误,应该是Hospital),然后建立一个xUnit Test项目,叫Hospital.Tests:
可以看到Hospital.Tests已经包含里这几个库:
然后为Hospital.Tests添加到Hospital项目的引用。
b.使用.net core 命令行
首先把刚才建立的Hospital.Tests项目移除(目录需要手动删除).
然后打开项目位置:
按住shift打开命令行:
用命令行创建项目:
创建 Hospital.Tests目录,进入目录,使用命令dotnet new xunit
创建xUnit单元测试项目。
添加项目的引用:
最后添加项目到解决方案:
回到VS界面,提示重新加载:
确认后,VS中解决方案结构如:
做第一个测试
对测试项目的文件名进行一些重构,编写以下代码,并进行Build:
从Test Explorer我们可以看到一个待测试的项目。
在这里,我们可以对测试项目进行分组和排序,如图:
想要运行所有的测试,就点击上面的Run All按钮。如果像运行单个测试,那么右击选择Run Selected Tests:
运行后,可以看到结果,Passed:
我们同样可以通过命令行来进行测试:
进入到Tests目录,执行 dotnet test
命令,所有的测试都会被发现,然后被执行:
因为我们并没有在测试方法中写任何的Assert,所以测试肯定是通过的,但这个测试也是个无效的测试。
Assert
Assert做什么?Assert基于代码的返回值、对象的最终状态、事件是否发生等情况来评估测试的结果。Assert的结果可能是Pass或者Fail。如果所有的asserts都pass了,那么整个测试就pass了;如果有任何assert fail了,那么测试就fail了。
xUnit提供了以下类型的Assert:
- boolean:True/False
- String:相等/不等,是否为空,以..开始/结束,是否包含子字符串,匹配正则表达式
- 数值型:相等/不等,是否在某个范围内,浮点的精度
- Collection:内容是否相等,是否包含某个元素,是否包含满足某种条件(predicate)的元素,是否所有的元素都满足某个assert
- Raised events:Custom events,Framework events(例如:PropertyChanged)
- Object Type:是否是某种类型,是否某种类型或继承与某种类型
一个test里应该有多少个asserts?
一种建议的做法是,每个test方法里面只有一个assert。
而还有一种建议就是,每个test里面可以有多个asserts,只要这些asserts都是针对同一个行为就行。
第一个Assert
目标类:
public class Patient
{
public Patient()
{
IsNew = true;
} public string FirstName { get; set; }
public string LastName { get; set; }
public string FullName => $"{FirstName} {LastName}";
public int HeartBeatRate { get; set; }
public bool IsNew { get; set; } public void IncreaseHeartBeatRate()
{
HeartBeatRate = CalculateHeartBeatRate() + ;
} private int CalculateHeartBeatRate()
{
var random = new Random();
return random.Next(, );
}
}
测试类:
public class PatientShould
{
[Fact]
public void HaveHeartBeatWhenNew()
{
var patient = new Patient(); Assert.True(patient.IsNew);
}
}
运行测试:
结果符合预期,测试通过。
改为Assert.False()的话:
测试Fail。
String Assert
测试string是否相等:
[Fact]
public void CalculateFullName()
{
var p = new Patient
{
FirstName = "Nick",
LastName = "Carter"
};
Assert.Equal("Nick Carter", p.FullName);
}
然后你需要Build一下,这样VS Test Explorer才能发现新的test。
运行测试,结果Pass:
同样改一下Patient类(别忘了Build一下),让结果失败:
从失败信息可以看到期待值和实际值。
StartsWith, EndsWith
[Fact]
public void CalculateFullNameStartsWithFirstName()
{
var p = new Patient
{
FirstName = "Nick",
LastName = "Carter"
};
Assert.StartsWith("Nick", p.FullName);
} [Fact]
public void CalculateFullNameEndsWithFirstName()
{
var p = new Patient
{
FirstName = "Nick",
LastName = "Carter"
};
Assert.EndsWith("Carter", p.FullName);e);
}
Build,然后Run Test,结果Pass:
忽略大小写 ignoreCase:
string默认的Assert是区分大小写的,这样就会失败:
可以为这些方法添加一个参数ignoreCase设置为true,就会忽略大小写:
包含子字符串 Contains
[Fact]
public void CalculateFullNameSubstring()
{
var p = new Patient
{
FirstName = "Nick",
LastName = "Carter"
};
Assert.Contains("ck Ca", p.FullName);
}
Build,测试结果Pass。
正则表达式,Matches
测试一下First name和Last name的首字母是不是大写的:
[Fact]
public void CalculcateFullNameWithTitleCase()
{
var p = new Patient
{
FirstName = "Nick",
LastName = "Carter"
};
Assert.Matches("[A-Z]{1}{a-z}+ [A-Z]{1}[a-z]+", p.FullName);
}
Build,测试通过。
数值 Assert
首先为Patient类添加一个property: BloodSugar。
public class Patient
{
public Patient()
{
IsNew = true;
_bloodSugar = 5.0f;
} private float _bloodSugar;
public float BloodSugar
{
get { return _bloodSugar; }
set { _bloodSugar = value; }
}
...
Equal:
[Fact]
public void BloodSugarStartWithDefaultValue()
{
var p = new Patient();
Assert.Equal(5.0, p.BloodSugar);
}
Build,测试通过。
范围, InRange:
首先为Patient类添加一个方法,病人吃饭之后血糖升高:
public void HaveDinner()
{
var random = new Random();
_bloodSugar += (float)random.Next(, ) / ; // 应该是1000
}
添加test:
[Fact]
public void BloodSugarIncreaseAfterDinner()
{
var p = new Patient();
p.HaveDinner();
// Assert.InRange<float>(p.BloodSugar, 5, 6);
Assert.InRange(p.BloodSugar, , );
}
Build,Run Test,结果Fail:
可以看到期待的Range和实际的值,这样很好。如果你使用Assert.True(xx >= 5 && xx <= 6)
的话,错误信息只能显示True或者False。
因为HaveDinner方法里,表达式的分母应该是1000,修改后,Build,Run,测试Pass。
使用xUnit为.net core程序进行单元测试(上)的更多相关文章
-
使用xUnit为.net core程序进行单元测试(1)
导读 为什么要编写自动化测试程序(Automated Tests)? 可以频繁的进行测试 可以在任何时间进行测试,也可以按计划定时进行,例如:可以在半夜进行自动测试. 肯定比人工测试要快. 可以更快速 ...
-
使用xUnit为.net core程序进行单元测试(中)
第一部分: http://www.cnblogs.com/cgzl/p/8283610.html 下面有一点点内容是重叠的.... String Assert 测试string是否相等: [Fact] ...
-
使用xUnit为.net core程序进行单元测试(3)
第1部分: http://www.cnblogs.com/cgzl/p/8283610.html 第2部分: http://www.cnblogs.com/cgzl/p/8287588.html 请使 ...
-
使用xUnit为.net core程序进行单元测试(4)
第1部分: http://www.cnblogs.com/cgzl/p/8283610.html 第2部分: http://www.cnblogs.com/cgzl/p/8287588.html 第3 ...
-
使用xUnit为.net core程序进行单元测试 -- Assert
第一部分: http://www.cnblogs.com/cgzl/p/8283610.html Assert Assert做什么?Assert基于代码的返回值.对象的最终状态.事件是否发生等情况来评 ...
-
使用xUnit为.net core程序进行单元测试(2)
第一部分: http://www.cnblogs.com/cgzl/p/8283610.html 下面有一点点内容是重叠的.... String Assert 测试string是否相等: [Fact] ...
-
使用xUnit为.net core程序进行单元测试
第1部分: http://www.cnblogs.com/cgzl/p/8283610.html 第2部分: http://www.cnblogs.com/cgzl/p/8287588.html ...
-
好代码是管出来的——.Net Core中的单元测试与代码覆盖率
测试对于软件来说,是保证其质量的一个重要过程,而测试又分为很多种,单元测试.集成测试.系统测试.压力测试等等,不同的测试的测试粒度和测试目标也不同,如单元测试关注每一行代码,集成测试关注的是多个模块是 ...
-
ubuntu上部署windows开发的dotnet core程序
目标:完成windows上开发的dotnet core程序部署至linux服务器上(Ubuntu 14.04) windows上开发dotnet core很简单,安装好VS2017,建立相关类型的项目 ...
随机推荐
-
在ASP.NET MVC的Action中直接接受客户端发送过来的HTML内容片段
出于安全的考虑,默认情况下,如果从客户端发送过来的数据中直接包括了HTML内容,ASP.NET会自动启动保护措施,你会收到下面的错误提示 这当然是一个不错的设计,只不过在某些特殊的事情,如果我们确实需 ...
-
Java 线程综述
线程重在 线程同步和线程通信的编程 1.线程与进程? 线程是指程序在执行过程中,能够执行程序代码的一个执行单元.线程的状态:运行.就绪.挂起(suspend).结束; 进程是指一段正在执行的程序. ...
-
使用ASP.Net WebAPI构建REST服务(六)——Self-Host
Asp.Net WebAPI生成的是一个程序集,并不是独立的进程,因此,要运行的时候必须将其承载在相应的宿主上,一般比较常见的是IIS承载.很多时候,我们为了简化部署或者功能集成,需要将其承载到独立的 ...
-
sql常识-IN 操作符
IN 操作符 IN 操作符允许我们在 WHERE 子句中规定多个值. SQL IN 语法 SELECT column_name(s) FROM table_name WHERE column_name ...
-
柯南君:看大数据时代下的IT架构(4)消息队列之RabbitMQ--案例(Helloword起航)
柯南君:看大数据时代下的IT架构(4)消息队列之RabbitMQ--案例(Helloword起航) 二.起航 本章节,柯南君将从几个层面,用官网例子讲解一下RabbitMQ的实操经典程序案例,让大家重 ...
-
objective-c 中数据类型之中的一个 几何数据类型(CGPoint,CGSize,CGRect)
// CGPoint 结构体数据原型, 用于声明一个点: /* Points. */ struct CGPoint { CGFloat x; CGFloat y; }; typedef struct ...
-
阿里云主机试用之自建站点和ftp上传所遇的2个问题
1.Access to the requested object is only available from the local network 其实我并没有自建站点,只是使用了XAMPP来建了ap ...
- ARM Cortex M0 程序映像和启动流程
-
IDEA或Webstorm设置Ctrl+滚轮调整字体大小
按Ctrl+Shift+A,出现搜索框 输入mouse: 点击打开这个设置:勾选 点击ok,之后就可以通过Ctrl+滚轮 调整字体大小了.
-
在 Anaconda下解决国内安装tensorflow等下载慢和中断,出错,异常问题的一点思路
把镜像地址改为清华大学开源软件镜像站,打开 管理员身份打开cmd 输入conda config --add channels https://mirrors.tuna.tsinghua.edu.cn/ ...