public class CalculatorTests
{
[Fact]
public void ShouldAddEquals5() //注意命名规范
{
//Arrange
var sut = new Calculator(); //sut-system under test,通用命名
//Act
var result = sut.Add(3, 2);
//Assert
Assert.Equal(5, result);
}
}
[Fact]
[Trait("Category","New")]
public void BeNewWhenCreated()
{
_output.WriteLine("第一个测试");
// Arrange
var patient = new Patient();
// Act
var result = patient.IsNew;
// Assert
Assert.True(result);
}
[Fact]
[Trait("Category", "New")]
public void HaveDefaultBloodSugarWhenCreated()
{
var p = new Patient();
var bloodSugar = p.BloodSugar;
Assert.Equal(4.9f, bloodSugar,5); //判断是否相等
Assert.InRange(bloodSugar, 3.9, 6.1);//判断是否在某一范围内
}
判断null,not null#
Copy
[Fact]
public void HaveNoNameWhenCreated()
{
var p = new Patient();
Assert.Null(p.FirstName);
Assert.NotNull(_patient);
}
集合测试#
Copy
[Fact]
public void HaveHadAColdBefore()
{
//Arrange
var _patient = new Patient();
//Act
var diseases = new List<string>
{
"感冒",
"发烧",
"水痘",
"腹泻"
};
_patient.History.Add("发烧");
_patient.History.Add("感冒");
_patient.History.Add("水痘");
_patient.History.Add("腹泻");
//Assert
//判断集合是否含有或者不含有某个元素
Assert.Contains("感冒",_patient.History);
Assert.DoesNotContain("心脏病", _patient.History);
//判断p.History至少有一个元素,该元素以水开头
Assert.Contains(_patient.History, x => x.StartsWith("水"));
//判断集合的长度
Assert.All(_patient.History, x => Assert.True(x.Length >= 2));
//判断集合是否相等,这里测试通过,说明是比较集合元素的值,而不是比较引用
Assert.Equal(diseases, _patient.History);
}
测试对象#
Copy
/// /// 测试Object
///
[Fact]
public void BeAPerson()
{
var p = new Patient();
var p2 = new Patient();
Assert.IsNotType(p); //测试对象是否相等,注意这里为false
Assert.IsType(p);
Assert.IsAssignableFrom(p);//判断对象是否继承自Person,true
//判断是否为同一个实例
Assert.NotSame(p, p2);
//Assert.Same(p, p2);
}
判断是否发生异常#
Copy
/// /// 判断是否发生异常
///
[Fact]
public void ThrowException() //注意不能使用ctrl+R,T快捷键,因为会中断测试,抛出异常
{
var p = new Patient();
//判断是否返回指定类型的异常
var ex = Assert.Throws(()=> { p.NotAllowed(); });
//判断异常信息是否相等
Assert.Equal("not able to create", ex.Message);
}
判断是否触发事件#
Copy
/// /// 判断是否触发事件
///
[Fact]
public void RaizeSleepEvent()
{
var p = new Patient();
Assert.Raises(
handler=>p.PatientSlept+=handler,
handler=>p.PatientSlept -= handler,
() => p.Sleep());
}
判断属性改变是否触发事件#
Copy
/// /// 测试属性改变事件是否触发
///
[Fact]
public void RaisePropertyChangedEvent()
{
var p = new Patient();
Assert.PropertyChanged(p, nameof(p.HeartBeatRate),
() => p.IncreaseHeartBeatRate());
}
[Fact]
[Trait("Category","New")]
public void BeNewWhenCreated()
{
_output.WriteLine("第一个测试");
// Arrange
//var patient = new Patient();
// Act
var result = _patient.IsNew;
// Assert
Assert.True(result);
//Assert.False(result);
}
测试分组搜索: 可以在测试资源管理器中按分组排列、搜索、运行测试
在dotnet cli中分组测试:
Copy
dotnew test --filter “Category=New” //运行单个分类测试
dotnew test --filter “Category=New|Category=Add”//运行多个分类测试
dotnet test --filter Category --logger:trx //输出测试日志
忽略测试#
使用特性:[Fact(Skip="不跑这个测试")],可以忽略测试,忽略测试图标为黄色警告
自定义测试输出内容#
使用ITestOutputHelper可以自定义在测试时的输出内容 dotnet test --filter Category --logger:trx会输出测试日志trx结尾的文件
Copy
public class PatientShould:IClassFixture,IDisposable
{
private readonly ITestOutputHelper _output;
private readonly Patient _patient;
private readonly LongTimeTask _task;
public PatientShould(ITestOutputHelper output,LongTimeFixture fixture)
{
this._output = output;
_patient = new Patient();
//_task = new LongTimeTask();
_task = fixture.Task;
}
[Fact]
[Trait("Category","New")]
public void BeNewWhenCreated()
{
_output.WriteLine("第一个测试");
// Arrange
//var patient = new Patient();
// Act
var result = _patient.IsNew;
// Assert
Assert.True(result);
//Assert.False(result);
}
}
using Demo2;
using System;
namespace Demo2Test
{
public class LongTimeFixture : IDisposable
{
public LongTimeTask Task { get; }
public LongTimeFixture()
{
}
public void Dispose()
{
}
}
}
测试类实现IClassFixture接口,并在构造函数中获取方法
Copy
public class PatientShould:IClassFixture,IDisposable
{
private readonly ITestOutputHelper _output;
private readonly Patient _patient;
private readonly LongTimeTask _task;
public PatientShould(ITestOutputHelper output,LongTimeFixture fixture)
{
this._output = output;
_patient = new Patient();
//_task = new LongTimeTask();
_task = fixture.Task;//获取方法
}
}
using Xunit;
namespace Demo2Test
{
[CollectionDefinition("Lone Time Task Collection")]
public class TaskCollection:ICollectionFixture
{
}
}
使用,加上[Collection("Lone Time Task Collection")]
Copy
[Collection("Lone Time Task Collection")]
public class PatientShould:IClassFixture,IDisposable
{
private readonly ITestOutputHelper _output;
private readonly Patient _patient;
private readonly LongTimeTask _task;
public PatientShould(ITestOutputHelper output,LongTimeFixture fixture)
{
this._output = output;
_patient = new Patient();
//_task = new LongTimeTask();
_task = fixture.Task;//获取方法
}
}
数据共享
1. 使用[Theory],可以写有构造参数的测试方法,使用InlineData传递数据#
Copy
[Theory]
[InlineData(1,2,3)]
[InlineData(2,2,4)]
[InlineData(3,3,6)]
public void ShouldAddEquals(int operand1,int operand2,int expected)
{
//Arrange
var sut = new Calculator(); //sut-system under test
//Act
var result = sut.Add(operand1, operand2);
//Assert
Assert.Equal(expected, result);
}
2. 使用[MemberData]特性,可以在多个测试中使用#
先添加CalculatorTestData类:
Copy
using System.Collections.Generic;
namespace DemoTest
{
public class CalculatorTestData
{
private static readonly List
使用MemberData
Copy
/// /// 数据共享-MemberData
/// ///
///
///
[Theory]
[MemberData(nameof(CalculatorTestData.TestData),MemberType =typeof(CalculatorTestData))]
public void ShouldAddEquals2(int operand1, int operand2, int expected)
{
//Arrange
var sut = new Calculator(); //sut-system under test
//Act
var result = sut.Add(operand1, operand2);
//Assert
Assert.Equal(expected, result);
}
3. 使用外部数据#
先创建一个类,准备数据,这里是读取的csv文件的数据
Copy
using System.Collections.Generic;
using System.IO;
using System.Linq;
namespace DemoTest.Data
{
/// /// 读取文件并返回数据集合
///
public class CalculatorCsvData
{
public static IEnumerable TestData
{
get
{
//把csv文件中的数据读出来,转换
string[] csvLines = File.ReadAllLines("Data\\TestData.csv");
var testCases = new List();
foreach (var csvLine in csvLines)
{
IEnumerable<int> values = csvLine.Trim().Split(',').Select(int.Parse);
object[] testCase = values.Cast().ToArray();
testCases.Add(testCase);
}
return testCases;
}
}
}
}
csv数据
Copy
1,2,3
1,3,4
2,4,6
0,1,1
使用
Copy
/// /// 数据共享-MemberData-外部数据
/// ///
///
///
[Theory]
[MemberData(nameof(CalculatorCsvData.TestData), MemberType = typeof(CalculatorCsvData))]
public void ShouldAddEquals3(int operand1, int operand2, int expected)
{
//Arrange
var sut = new Calculator(); //sut-system under test
//Act
var result = sut.Add(operand1, operand2);
//Assert
Assert.Equal(expected, result);
}
4. 使用自定义特性,继承自DataAttribute#
自定义特性
Copy
using System.Collections.Generic;
using System.Reflection;
using Xunit.Sdk;
namespace DemoTest.Data
{
public class CalculatorDataAttribute : DataAttribute
{
public override IEnumerableGetData(MethodInfo testMethod)
{
yield return new object[] { 0, 100, 100 };
yield return new object[] { 1, 99, 100 };
yield return new object[] { 2, 98, 100 };
yield return new object[] { 3, 97, 100 };
}
}
}
使用
Copy
/// /// 数据共享-自定义特性继承自DataAttribute
/// ///
///
///
[Theory]
[CalculatorDataAttribute]
public void ShouldAddEquals4(int operand1, int operand2, int expected)
{
//Arrange
var sut = new Calculator(); //sut-system under test
//Act
var result = sut.Add(operand1, operand2);
//Assert
Assert.Equal(expected, result);
}