使用xUnit.net 对 .net core 进行单元测试
文章目錄
- 1.自動(dòng)化測(cè)試綜述
- 1.為什么要進(jìn)行自動(dòng)化測(cè)試
- 2.自動(dòng)化測(cè)試的分類(lèi)
- 2.測(cè)試的三個(gè)階段 AAA
- 代碼部分:
- 3.Assert
- 具體代碼:
- 4.測(cè)試的優(yōu)化
- 1.分組 [ Trait ("Name",“Value”) ]
- 1.代碼:
- 2.輸出測(cè)試的信息
- 3.可以跳過(guò)去某個(gè)測(cè)試
- 4.為了防止代碼重復(fù),new 的實(shí)例,在構(gòu)造函數(shù)里實(shí)現(xiàn)
- 5.數(shù)據(jù)驅(qū)動(dòng)測(cè)試
- 題外話
1.自動(dòng)化測(cè)試綜述
1.為什么要進(jìn)行自動(dòng)化測(cè)試
1.可以在任何時(shí)間進(jìn)行測(cè)試。
2.測(cè)試速度要比人快。
3.非常可靠。
2.自動(dòng)化測(cè)試的分類(lèi)
- 單元測(cè)試:測(cè)試某個(gè)類(lèi)或者類(lèi)下的某個(gè)方法
- 集成測(cè)試
- 皮下測(cè)試
- UI 測(cè)試
測(cè)試的是 public ,private不太好測(cè)試,需要修改代碼
2.測(cè)試的三個(gè)階段 AAA
- Arrange:(序列,安排),這里做一些先決的設(shè)定,例如創(chuàng)建對(duì)象實(shí)例,數(shù)據(jù),輸入等等。
- Act ,在這里執(zhí)行生產(chǎn)代碼并返回結(jié)果,例如調(diào)用方法和設(shè)置屬性。
- Assert:(主張)在這里檢測(cè)結(jié)果,測(cè)試通過(guò)或者失敗。
xUnit 是一個(gè)測(cè)試框架,可以針對(duì) .net /core 進(jìn)行測(cè)試。
代碼部分:
1.先看目錄結(jié)構(gòu)
- 命名規(guī)則:在類(lèi)的名字后邊加 test 。
- 命名規(guī)則:測(cè)試方法的方法名用 ShouldAdd 。
- 測(cè)試的項(xiàng)目,添加 xUnit.net 測(cè)試項(xiàng)目。
Cakulator 類(lèi)
public class Cakulator{public int Add(int a, int b){return a + b;}}CakulatroTest 類(lèi)
public class CakulatroTest{[Fact] //根據(jù)這個(gè)特性判斷出來(lái)是個(gè)測(cè)試方法。public void ShouldAdd(){// Arrangevar sut = new Cakulator();// system Under Test// Actvar result = sut.Add(1, 2);// AssertAssert.Equal(3, result);//結(jié)果等于3}}進(jìn)行測(cè)試:
在要準(zhǔn)備測(cè)試的類(lèi)和方法上直接右鍵運(yùn)行。
3.Assert
- Assert基于代碼的返回值,對(duì)象的最終狀態(tài),事件是否發(fā)生等情況來(lái)評(píng)估測(cè)試結(jié)果。
- Assert的結(jié)果可能是 pass 也有可能是 Fail,如果所有的 Assert 都是 Pass ,那么整個(gè)測(cè)試就 pass 了。如果有任何的 assert fail 了,那么測(cè)試就 fail 了。
xUnit 可以進(jìn)行以下的判斷:
一個(gè)test里面應(yīng)該有多少個(gè) assert
- 一個(gè) test 方法里,只能有一個(gè) assert 。
- 一個(gè) test 方法里,可以有多個(gè) Asserts,只要這多個(gè) assert 這對(duì)一個(gè) Action 就行。
具體代碼:
1.先建一個(gè) Person 類(lèi)
public class Person{public string FirstName { get; set; }public string LastName { get; set; }}2.再建一個(gè) patient 類(lèi)
public class patient:Person{public patient(){IsNew = true; //剛 new 出來(lái)的時(shí)候,這個(gè) isnew 是 true 。BloodSugar = 4.9f;History = new List<string>();//把這個(gè)要 new 出來(lái).}public string FullName => $"{LastName}{FirstName}";public bool IsNew { get; set; } //是否是剛出生的。public float BloodSugar { get; set; }public int HeartBeatRate { get; set; }public void IncressHeartBeatRate() //計(jì)算心跳{//執(zhí)行完以后的方法 + 2HeartBeatRate = CalulateHeartBeatRate() + 2;}public List<string> History { get; set; }private int CalulateHeartBeatRate() //心跳{var random = new Random();return random.Next(1,100);}}3.使用 xUnit 進(jìn)行測(cè)試:
public class PatientShould{// 對(duì) bool 類(lèi)型進(jìn)行判斷.[Fact]public void BeNewWhenCreated(){// arrangepatient patient = new patient();//Actbool result = patient.IsNew;//AssertAssert.True(result);// Assert.False(result);}//對(duì)字符串進(jìn)行判斷[Fact] //表明這個(gè)是個(gè)測(cè)試方法public void HaveCorrctFullName(){// Arrange (實(shí)例化一個(gè)你要檢查的類(lèi))patient patient = new patient{FirstName = "小明",LastName = "張"};// Act 。把需要檢查的屬性弄出來(lái)var fullName = patient.FullName;//Assert 。進(jìn)行判斷.Assert.Equal("張小明", fullName);Assert.StartsWith("張", fullName);Assert.EndsWith("明", fullName);Assert.Contains("小", fullName);//是小寫(xiě)但不是大寫(xiě);Assert.NotEqual("李", fullName);}//對(duì) 浮點(diǎn)型 進(jìn)行判斷[Fact]public void HaveDefaultBloodSugarWhenCreate(){patient patient = new patient();float blooddar = patient.BloodSugar;Assert.Equal(4.9f, blooddar, 5);//在哪個(gè)范圍內(nèi)Assert.InRange(blooddar, 3.9f, 6.1f);}//剛開(kāi)始創(chuàng)建的時(shí)候,名字應(yīng)該是空;[Fact]public void HaveNameWhenCreated(){patient p = new patient();var a = p.FirstName;Assert.Null(a);Assert.NotNull(p);}//對(duì)集合進(jìn)行測(cè)試[Fact]public void HaveHadColid(){var p = new patient();p.History.Add("感冒");p.History.Add("發(fā)燒");p.History.Add("水痘");p.History.Add("腹瀉");Assert.Contains("感冒", p.History);Assert.DoesNotContain("心臟病", p.History);//Predicate//對(duì)集合中的元素判斷是否包含Assert.Contains(p.History, x => x.StartsWith("水"));//對(duì)集合內(nèi)的所有元素都進(jìn)行判斷Assert.All(p.History, x => Assert.True(x.Length >= 2));// 判斷兩個(gè)集合是否相等var diseases = new List<string>{"感冒","發(fā)燒","水痘","腹瀉"};Assert.Equal(p.History, diseases);}// 對(duì) object 進(jìn)行測(cè)試[Fact]public void BeAPerson(){var p1 = new patient();var p2 = new patient();Assert.IsType<patient>(p1);//p是否是 patient 類(lèi)型.Assert.IsNotType<Person>(p1);//這個(gè)就會(huì)判斷處所。盡管是他的子類(lèi).Assert.IsAssignableFrom<Person>(p1);//判斷是否繼承于某個(gè)類(lèi)//判斷是否是一個(gè)實(shí)例//same 是同一個(gè)實(shí)例Assert.NotSame(p1,p2);// Assert.Same(p1,p2);}// 判斷異常// 判斷拋出的異常是否和我們所期待的相等.// 對(duì)委托和事件的測(cè)試.// 寫(xiě)起來(lái)有點(diǎn)麻煩,用到再說(shuō)吧。}在使用 測(cè)試資源管理器的時(shí)候,如果加斷點(diǎn),要使用 debug 模式,不能進(jìn)行直接測(cè)試
4.測(cè)試的優(yōu)化
- 測(cè)試分組
- 忽略測(cè)試
- 自定義測(cè)試輸出的內(nèi)容
- 減少重復(fù)代碼
- 共享上下文
注意,在每次測(cè)試的時(shí)候,都要重新生成一下
1.分組 [ Trait (“Name”,“Value”) ]
- 方法級(jí)
- Class級(jí)
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();}// 對(duì) bool 類(lèi)型進(jìn)行判斷.[Fact][Trait("Category","New")]public void BeNewWhenCreated(){output.WriteLine("這是第一個(gè)測(cè)試");//在這里用 Console.WriteLine()是無(wú)效的;bool result = _patient.IsNew;Assert.True(result);}[Fact] //表明這個(gè)是個(gè)測(cè)試方法[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);//是小寫(xiě)但不是大寫(xiě);Assert.NotEqual("李", fullName);}在測(cè)試任務(wù)管理器里面,選擇分組依據(jù)為特征:
2.輸出測(cè)試的信息
在測(cè)試的時(shí)候,console.writeLine( ) 不管用,要使用 outputhelp.WriteLine 進(jìn)行測(cè)試,構(gòu)造函數(shù)引用方法如下。
3.可以跳過(guò)去某個(gè)測(cè)試
[Fact(Skip =“不需要跑這個(gè)測(cè)試”)]
4.為了防止代碼重復(fù),new 的實(shí)例,在構(gòu)造函數(shù)里實(shí)現(xiàn)
要養(yǎng)成這種習(xí)慣:
具體代碼如下:
public class PatientShould{private readonly ITestOutputHelper output;private readonly patient _patient;private readonly LongTimeTask _task;public PatientShould(ITestOutputHelper output){this.output = output;// 為減少重復(fù)代碼,使用構(gòu)造函數(shù)重構(gòu)// 下邊都使用同一個(gè)構(gòu)造函數(shù)_patient=new patient();_task=new LongTimeTask();}// 對(duì) bool 類(lèi)型進(jìn)行判斷.[Fact][Trait("Category","New")]public void BeNewWhenCreated(){output.WriteLine("這是第一個(gè)測(cè)試");//在這里用 Console.WriteLine()是無(wú)效的;//Actbool result = _patient.IsNew;//AssertAssert.True(result);// Assert.False(result);}//對(duì)字符串進(jìn)行判斷[Fact] //表明這個(gè)是個(gè)測(cè)試方法[Trait("Category", "Name")]public void HaveCorrctFullName(){// Arrange (實(shí)例化一個(gè)你要檢查的類(lèi))patient patient = new patient{FirstName = "小明",LastName = "張"};// Act 。把需要檢查的屬性弄出來(lái)var fullName = patient.FullName;//Assert 。進(jìn)行判斷.Assert.Equal("張小明", fullName);Assert.StartsWith("張", fullName);Assert.EndsWith("明", fullName);Assert.Contains("小", fullName);//是小寫(xiě)但不是大寫(xiě);Assert.NotEqual("李", fullName);}//對(duì) 浮點(diǎn)型 進(jìn)行判斷[Fact][Trait("Category","New")]public void HaveDefaultBloodSugarWhenCreate(){patient patient = new patient();float blooddar = patient.BloodSugar;Assert.Equal(4.9f, blooddar, 5);//在哪個(gè)范圍內(nèi)Assert.InRange(blooddar, 3.9f, 6.1f);}//剛開(kāi)始創(chuàng)建的時(shí)候,名字應(yīng)該是空;[Fact(Skip ="不需要跑這個(gè)測(cè)試")]public void HaveNameWhenCreated(){patient p = new patient();var a = p.FirstName;Assert.Null(a);Assert.NotNull(p);}//對(duì)集合進(jìn)行測(cè)試[Fact]public void HaveHadColid(){var p = new patient();p.History.Add("感冒");p.History.Add("發(fā)燒");p.History.Add("水痘");p.History.Add("腹瀉");Assert.Contains("感冒", p.History);Assert.DoesNotContain("心臟病", p.History);//Predicate//對(duì)集合中的元素判斷是否包含Assert.Contains(p.History, x => x.StartsWith("水"));//對(duì)集合內(nèi)的所有元素都進(jìn)行判斷Assert.All(p.History, x => Assert.True(x.Length >= 2));// 判斷兩個(gè)集合是否相等var diseases = new List<string>{"感冒","發(fā)燒","水痘","腹瀉"};Assert.Equal(p.History, diseases);}// 對(duì) object 進(jìn)行測(cè)試[Fact]public void BeAPerson(){var p1 = new patient();var p2 = new patient();Assert.IsType<patient>(p1);//p是否是 patient 類(lèi)型.Assert.IsNotType<Person>(p1);//這個(gè)就會(huì)判斷處所。盡管是他的子類(lèi).Assert.IsAssignableFrom<Person>(p1);//判斷是否繼承于某個(gè)類(lèi)//判斷是否是一個(gè)實(shí)例//same 是同一個(gè)實(shí)例Assert.NotSame(p1,p2);// Assert.Same(p1,p2);}// 判斷異常// 判斷拋出的異常是否和我們所期待的相等.// 對(duì)委托和事件的測(cè)試.// 寫(xiě)起來(lái)有點(diǎn)麻煩,用到再說(shuō)吧。}5.數(shù)據(jù)驅(qū)動(dòng)測(cè)試
舉例前邊的,加法的測(cè)試,可以寫(xiě)多個(gè) fact,但是比較麻煩,使用【Theory】+ 【InlineData】有簡(jiǎn)單的方法。
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);}}除此之外,還可以直接用 從數(shù)據(jù)庫(kù)或者 CSV等文件中讀取后進(jìn)行測(cè)試,這里沒(méi)看,用到的時(shí)候再學(xué)吧
題外話
最大的是解決方案名,下邊是類(lèi)名
參考文獻(xiàn):
xUnit.Net單元測(cè)試
gitee代碼
總結(jié)
以上是生活随笔為你收集整理的使用xUnit.net 对 .net core 进行单元测试的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: uip架构和局限
- 下一篇: c语言程序运行结果怎么看,c语言程序的运