文章目录
1.自动化测试综述
1.为什么要进行自动化测试
1.可以在任何时间进行测试。
2.测试速度要比人快。
3.非常可靠。
2.自动化测试的分类
- 单元测试:测试某个类或者类下的某个方法
- 集成测试
- 皮下测试
- UI 测试
测试的是 public ,private不太好测试,需要修改代码
2.测试的三个阶段 AAA
- Arrange:(序列,安排),这里做一些先决的设定,例如创建对象实例,数据,输入等等。
- Act ,在这里执行生产代码并返回结果,例如调用方法和设置属性。
- Assert:(主张)在这里检测结果,测试通过或者失败。
xUnit 是一个测试框架,可以针对 .net /core 进行测试。
代码部分:
1.先看目录结构
- 命名规则:在类的名字后边加 test 。
- 命名规则:测试方法的方法名用 ShouldAdd 。
- 测试的项目,添加 xUnit.net 测试项目。
Cakulator 类
public class Cakulator
{
public int Add(int a, int b)
{
return a + b;
}
}
CakulatroTest 类
public class CakulatroTest
{
[Fact] //根据这个特性判断出来是个测试方法。
public void ShouldAdd()
{
// Arrange
var sut = new Cakulator();// system Under Test
// Act
var result = sut.Add(1, 2);
// Assert
Assert.Equal(3, result);//结果等于3
}
}
进行测试:
在要准备测试的类和方法上直接右键运行。
3.Assert
- Assert基于代码的返回值,对象的最终状态,事件是否发生等情况来评估测试结果。
- Assert的结果可能是 pass 也有可能是 Fail,如果所有的 Assert 都是 Pass ,那么整个测试就 pass 了。如果有任何的 assert fail 了,那么测试就 fail 了。
xUnit 可以进行以下的判断:
一个test里面应该有多少个 assert
- 一个 test 方法里,只能有一个 assert 。
- 一个 test 方法里,可以有多个 Asserts,只要这多个 assert 这对一个 Action 就行。
具体代码:
1.先建一个 Person 类
public class Person
{
public string FirstName { get; set; }
public string LastName { get; set; }
}
2.再建一个 patient 类
public class patient:Person
{
public patient()
{
IsNew = true; //刚 new 出来的时候,这个 isnew 是 true 。
BloodSugar = 4.9f;
History = new List<string>();//把这个要 new 出来.
}
public string FullName => $"{LastName}{FirstName}";
public bool IsNew { get; set; } //是否是刚出生的。
public float BloodSugar { get; set; }
public int HeartBeatRate { get; set; }
public void IncressHeartBeatRate() //计算心跳
{
//执行完以后的方法 + 2
HeartBeatRate = CalulateHeartBeatRate() + 2;
}
public List<string> History { get; set; }
private int CalulateHeartBeatRate() //心跳
{
var random = new Random();
return random.Next(1,100);
}
}
3.使用 xUnit 进行测试:
public class PatientShould
{
// 对 bool 类型进行判断.
[Fact]
public void BeNewWhenCreated()
{
// arrange
patient patient = new patient();
//Act
bool result = patient.IsNew;
//Assert
Assert.True(result);
// Assert.False(result);
}
//对字符串进行判断
[Fact] //表明这个是个测试方法
public void HaveCorrctFullName()
{
// Arrange (实例化一个你要检查的类)
patient patient = new patient
{
FirstName = "小明",
LastName = "张"
};
// Act 。把需要检查的属性弄出来
var fullName = patient.FullName;
//Assert 。进行判断.
Assert.Equal("张小明", fullName);
Assert.StartsWith("张", fullName);
Assert.EndsWith("明", fullName);
Assert.Contains("小", fullName);
//是小写但不是大写;
Assert.NotEqual("李", fullName);
}
//对 浮点型 进行判断
[Fact]
public void HaveDefaultBloodSugarWhenCreate()
{
patient patient = new patient();
float blooddar = patient.BloodSugar;
Assert.Equal(4.9f, blooddar, 5);
//在哪个范围内
Assert.InRange(blooddar, 3.9f, 6.1f);
}
//刚开始创建的时候,名字应该是空;
[Fact]
public void HaveNameWhenCreated()
{
patient p = new patient();
var a = p.FirstName;
Assert.Null(a);
Assert.NotNull(p);
}
//对集合进行测试
[Fact]
public void HaveHadColid()
{
var p = new patient();
p.History.Add("感冒");
p.History.Add("发烧");
p.History.Add("水痘");
p.History.Add("腹泻");
Assert.Contains("感冒", p.History);
Assert.DoesNotContain("心脏病", p.History);
//Predicate
//对集合中的元素判断是否包含
Assert.Contains(p.History, x => x.StartsWith("水"));
//对集合内的所有元素都进行判断
Assert.All(p.History, x => Assert.True(x.Length >= 2));
// 判断两个集合是否相等
var diseases = new List<string>
{
"感冒",
"发烧",
"水痘",
"腹泻"
};
Assert.Equal(p.History, diseases);
}
// 对 object 进行测试
[Fact]
public void BeAPerson()
{
var p1 = new patient();
var p2 = new patient();
Assert.IsType<patient>(p1);//p是否是 patient 类型.
Assert.IsNotType<Person>(p1);//这个就会判断处所。尽管是他的子类.
Assert.IsAssignableFrom<Person>(p1);//判断是否继承于某个类
//判断是否是一个实例
//same 是同一个实例
Assert.NotSame(p1,p2);
// Assert.Same(p1,p2);
}
// 判断异常
// 判断抛出的异常是否和我们所期待的相等.
// 对委托和事件的测试.
// 写起来有点麻烦,用到再说吧。
}
在使用 测试资源管理器的时候,如果加断点,要使用 debug 模式,不能进行直接测试
4.测试的优化
- 测试分组
- 忽略测试
- 自定义测试输出的内容
- 减少重复代码
- 共享上下文
注意,在每次测试的时候,都要重新生成一下
1.分组 [ Trait (“Name”,“Value”) ]
- 方法级
- Class级
1.代码:
public class PatientShould
{
private readonly ITestOutputHelper output;
private readonly patient _patient;
private readonly LongTimeTask _task;
public PatientShould(ITestOutputHelper output)
{
this.output = output;
_patient=new patient();
_task=new LongTimeTask();
}
// 对 bool 类型进行判断.
[Fact]
[Trait("Category","New")]
public void BeNewWhenCreated()
{
output.WriteLine("这是第一个测试");//在这里用 Console.WriteLine()是无效的;
bool result = _patient.IsNew;
Assert.True(result);
}
[Fact] //表明这个是个测试方法
[Trait("Category", "Name")]
public void HaveCorrctFullName()
{
patient patient = new patient
{
FirstName = "小明",
LastName = "张"
};
var fullName = patient.FullName;
Assert.Equal("张小明", fullName);
Assert.StartsWith("张", fullName);
Assert.EndsWith("明", fullName);
Assert.Contains("小", fullName);
//是小写但不是大写;
Assert.NotEqual("李", fullName);
}
在测试任务管理器里面,选择分组依据为特征:
2.输出测试的信息
在测试的时候,console.writeLine( ) 不管用,要使用 outputhelp.WriteLine 进行测试,构造函数引用方法如下。
3.可以跳过去某个测试
[Fact(Skip =“不需要跑这个测试”)]
4.为了防止代码重复,new 的实例,在构造函数里实现
要养成这种习惯:
具体代码如下:
public class PatientShould
{
private readonly ITestOutputHelper output;
private readonly patient _patient;
private readonly LongTimeTask _task;
public PatientShould(ITestOutputHelper output)
{
this.output = output;
// 为减少重复代码,使用构造函数重构
// 下边都使用同一个构造函数
_patient=new patient();
_task=new LongTimeTask();
}
// 对 bool 类型进行判断.
[Fact]
[Trait("Category","New")]
public void BeNewWhenCreated()
{
output.WriteLine("这是第一个测试");//在这里用 Console.WriteLine()是无效的;
//Act
bool result = _patient.IsNew;
//Assert
Assert.True(result);
// Assert.False(result);
}
//对字符串进行判断
[Fact] //表明这个是个测试方法
[Trait("Category", "Name")]
public void HaveCorrctFullName()
{
// Arrange (实例化一个你要检查的类)
patient patient = new patient
{
FirstName = "小明",
LastName = "张"
};
// Act 。把需要检查的属性弄出来
var fullName = patient.FullName;
//Assert 。进行判断.
Assert.Equal("张小明", fullName);
Assert.StartsWith("张", fullName);
Assert.EndsWith("明", fullName);
Assert.Contains("小", fullName);
//是小写但不是大写;
Assert.NotEqual("李", fullName);
}
//对 浮点型 进行判断
[Fact]
[Trait("Category","New")]
public void HaveDefaultBloodSugarWhenCreate()
{
patient patient = new patient();
float blooddar = patient.BloodSugar;
Assert.Equal(4.9f, blooddar, 5);
//在哪个范围内
Assert.InRange(blooddar, 3.9f, 6.1f);
}
//刚开始创建的时候,名字应该是空;
[Fact(Skip ="不需要跑这个测试")]
public void HaveNameWhenCreated()
{
patient p = new patient();
var a = p.FirstName;
Assert.Null(a);
Assert.NotNull(p);
}
//对集合进行测试
[Fact]
public void HaveHadColid()
{
var p = new patient();
p.History.Add("感冒");
p.History.Add("发烧");
p.History.Add("水痘");
p.History.Add("腹泻");
Assert.Contains("感冒", p.History);
Assert.DoesNotContain("心脏病", p.History);
//Predicate
//对集合中的元素判断是否包含
Assert.Contains(p.History, x => x.StartsWith("水"));
//对集合内的所有元素都进行判断
Assert.All(p.History, x => Assert.True(x.Length >= 2));
// 判断两个集合是否相等
var diseases = new List<string>
{
"感冒",
"发烧",
"水痘",
"腹泻"
};
Assert.Equal(p.History, diseases);
}
// 对 object 进行测试
[Fact]
public void BeAPerson()
{
var p1 = new patient();
var p2 = new patient();
Assert.IsType<patient>(p1);//p是否是 patient 类型.
Assert.IsNotType<Person>(p1);//这个就会判断处所。尽管是他的子类.
Assert.IsAssignableFrom<Person>(p1);//判断是否继承于某个类
//判断是否是一个实例
//same 是同一个实例
Assert.NotSame(p1,p2);
// Assert.Same(p1,p2);
}
// 判断异常
// 判断抛出的异常是否和我们所期待的相等.
// 对委托和事件的测试.
// 写起来有点麻烦,用到再说吧。
}
5.数据驱动测试
举例前边的,加法的测试,可以写多个 fact,但是比较麻烦,使用【Theory】+ 【InlineData】有简单的方法。
public class Theory_CaculatorTest
{
[Theory]
[InlineData(1,2,3)]
[InlineData(1, 3, 4)]
[InlineData(2, 2, 4)]
[InlineData(1, 9, 10)]
[InlineData(9, 2, 11)]
public void ShouldAddEquls(int x, int y, int expected)
{
var sut = new Cakulator();
var reslut = sut.Add(x,y);
Assert.Equal(expected,reslut);
}
}
除此之外,还可以直接用 从数据库或者 CSV等文件中读取后进行测试,这里没看,用到的时候再学吧
题外话
最大的是解决方案名,下边是类名
参考文献:
xUnit.Net单元测试
gitee代码