這篇文章主要介紹“如何使用xUnit為.net core程序進(jìn)行單元測(cè)試”,在日常操作中,相信很多人在如何使用xUnit為.net core程序進(jìn)行單元測(cè)試問題上存在疑惑,小編查閱了各式資料,整理出簡(jiǎn)單好用的操作方法,希望對(duì)大家解答”如何使用xUnit為.net core程序進(jìn)行單元測(cè)試”的疑惑有所幫助!接下來,請(qǐng)跟著小編一起來學(xué)習(xí)吧!
創(chuàng)新互聯(lián),為您提供網(wǎng)站建設(shè)公司、網(wǎng)站制作、網(wǎng)站營(yíng)銷推廣、網(wǎng)站開發(fā)設(shè)計(jì),對(duì)服務(wù)生料攪拌車等多個(gè)行業(yè)擁有豐富的網(wǎng)站建設(shè)及推廣經(jīng)驗(yàn)。創(chuàng)新互聯(lián)網(wǎng)站建設(shè)公司成立于2013年,提供專業(yè)網(wǎng)站制作報(bào)價(jià)服務(wù),我們深知市場(chǎng)的競(jìng)爭(zhēng)激烈,認(rèn)真對(duì)待每位客戶,為客戶提供賞心悅目的作品。 與客戶共同發(fā)展進(jìn)步,是我們永遠(yuǎn)的責(zé)任!
可以頻繁的進(jìn)行測(cè)試
可以在任何時(shí)間進(jìn)行測(cè)試,也可以按計(jì)劃定時(shí)進(jìn)行,例如:可以在半夜進(jìn)行自動(dòng)測(cè)試。
肯定比人工測(cè)試要快。
可以更快速的發(fā)現(xiàn)錯(cuò)誤。
基本上是非??煽康?。
測(cè)試代碼與生產(chǎn)代碼緊密結(jié)合。
使得開發(fā)團(tuán)隊(duì)更具有幸福感!
縱軸表示測(cè)試的深度,也就是說測(cè)試的細(xì)致程度。
橫軸則表示測(cè)試的覆蓋程度。
Unit Test 單元測(cè)試, 它可以測(cè)試一個(gè)類,或者一個(gè)類的某個(gè)功能,它具有很好的深度,但是對(duì)整個(gè)應(yīng)用來說它不具備很好的覆蓋面。
Integration Test 集成測(cè)試,它沒有單元測(cè)試那么細(xì)致,但是具有相對(duì)較好的測(cè)試覆蓋面。例如它可以測(cè)試功能的組合,以及像數(shù)據(jù)庫或文件系統(tǒng)這樣的外部資源等。
Subcutaneous Test 皮下測(cè)試,這種測(cè)試作用于UI層的下面一層,這也意味著它對(duì)整個(gè)應(yīng)用來說有很好的覆蓋率,但是深度欠佳。那一個(gè)MVC結(jié)構(gòu)的應(yīng)用來說,它就是針對(duì)剛好在Controller下面一層的測(cè)試,對(duì)于Web service來說,它就是對(duì)節(jié)點(diǎn)下面那層的測(cè)試。
UI測(cè)試,它的測(cè)試覆蓋面很廣,直接從UI層面進(jìn)行測(cè)試,但是深度欠佳。
從速度來看 單元是最快的,而UI測(cè)試是最慢的。
從脆弱性來看 UI測(cè)試是最差的,程序修改后極有可能需要修改測(cè)試代碼,而單元測(cè)試是最好的。
public void IncreaseHeartBeatRate()
{
HeartBeatRate = CalculateHeartBeatRate() + 2;
}
private int CalculateHeartBeatRate()
{
var random = new Random();
return random.Next(1, 100);
}
多數(shù)情況下單元測(cè)試都應(yīng)該是針對(duì)類的行為進(jìn)行測(cè)試的,也就是public方法。當(dāng)然也純?cè)诓煌挠^點(diǎn)。
如果想要對(duì)private方法進(jìn)行測(cè)試的話,是有很多缺點(diǎn)的:
首先需要修改方法的訪問限制需要從private改為public,這就破壞了面向?qū)ο蟮姆庋b性。
再者,這其實(shí)測(cè)試的是類的具體實(shí)現(xiàn)細(xì)節(jié),而不是類的行為。如果我們想要對(duì)類的內(nèi)部進(jìn)行重構(gòu)的話,就會(huì)破壞測(cè)試,導(dǎo)致測(cè)試也必須重構(gòu)。如果必須對(duì)private方法進(jìn)行測(cè)試,那么首先建議您把private修飾符改成internal,然后修改該項(xiàng)目(project)的AssemblyInfo.cs,它在項(xiàng)目的Debug或者Release文件夾下。代碼如下:
[assembly: InternalsVisibleTo("Hospital.Tests")]
這表示Hospital.Tests這個(gè)測(cè)試項(xiàng)目可以訪問該項(xiàng)目生產(chǎn)代碼(production code)的internal方法。
Arrange,這里做一些先決的設(shè)定。例如創(chuàng)建對(duì)象實(shí)例,數(shù)據(jù),輸入等等。
Act,在這里執(zhí)行生產(chǎn)代碼并返回結(jié)果。例如調(diào)用方法,或者設(shè)置屬性(Properties)。
Assert,在這里檢查結(jié)果。測(cè)試通過或者失敗。
官網(wǎng):https://xunit.github.io/
xUnit是一個(gè)測(cè)試框架,可以針對(duì).net/core進(jìn)行測(cè)試。
測(cè)試項(xiàng)目需引用被項(xiàng)目從而對(duì)其進(jìn)行測(cè)試,測(cè)試項(xiàng)目同時(shí)需要引用xUnit庫。測(cè)試編寫好后,用Test Runner來運(yùn)行測(cè)試。Test Runner可以讀取測(cè)試代碼,并且會(huì)知道我們所使用的測(cè)試框架,然后執(zhí)行,并顯示結(jié)果。目前可用的Test Runner包括vs自帶的Test Explorer,或者dotnet core命令行,以及第三方工具,例如resharper等等。
.net full, .net core, .net standard, uwp, xamarin.
[Fact]
public void TestIncreaseHeartBeatRate()
{
var patient = new Patient(); // Arrange
patient.IncreaseHeartBeatRate(); // Act
Assert.InRange(patient.HeartBeatRate, 40, 100); // Assert
}
首先建立一個(gè)C# library項(xiàng)目,叫Hospital(下面部分截圖有個(gè)拼寫錯(cuò)誤,應(yīng)該是Hospital),然后建立一個(gè)xUnit Test項(xiàng)目,叫Hospital.Tests:
可以看到Hospital.Tests已經(jīng)包含里這幾個(gè)庫:
然后為Hospital.Tests添加到Hospital項(xiàng)目的引用。
首先把剛才建立的Hospital.Tests項(xiàng)目移除(目錄需要手動(dòng)刪除).
然后打開項(xiàng)目位置:
按住shift打開命令行:
用命令行創(chuàng)建項(xiàng)目:
創(chuàng)建 Hospital.Tests目錄,進(jìn)入目錄,使用命令dotnet new xunit創(chuàng)建xUnit單元測(cè)試項(xiàng)目。
添加項(xiàng)目的引用:
最后添加項(xiàng)目到解決方案:
回到VS界面,提示重新加載:
確認(rèn)后,VS中解決方案結(jié)構(gòu)如:
對(duì)測(cè)試項(xiàng)目的文件名進(jìn)行一些重構(gòu),編寫以下代碼,并進(jìn)行Build:
從Test Explorer我們可以看到一個(gè)待測(cè)試的項(xiàng)目。
在這里,我們可以對(duì)測(cè)試項(xiàng)目進(jìn)行分組和排序,如圖:
想要運(yùn)行所有的測(cè)試,就點(diǎn)擊上面的Run All按鈕。如果像運(yùn)行單個(gè)測(cè)試,那么右擊選擇Run Selected Tests:
運(yùn)行后,可以看到結(jié)果,Passed:
我們同樣可以通過命令行來進(jìn)行測(cè)試:
進(jìn)入到Tests目錄,執(zhí)行 dotnet test命令,所有的測(cè)試都會(huì)被發(fā)現(xiàn),然后被執(zhí)行:
因?yàn)槲覀儾]有在測(cè)試方法中寫任何的Assert,所以測(cè)試肯定是通過的,但這個(gè)測(cè)試也是個(gè)無效的測(cè)試。
Assert做什么?Assert基于代碼的返回值、對(duì)象的最終狀態(tài)、事件是否發(fā)生等情況來評(píng)估測(cè)試的結(jié)果。Assert的結(jié)果可能是Pass或者Fail。如果所有的asserts都pass了,那么整個(gè)測(cè)試就pass了;如果有任何assert fail了,那么測(cè)試就fail了。
xUnit提供了以下類型的Assert:
boolean:True/False
String:相等/不等,是否為空,以..開始/結(jié)束,是否包含子字符串,匹配正則表達(dá)式
數(shù)值型:相等/不等,是否在某個(gè)范圍內(nèi),浮點(diǎn)的精度
Collection:內(nèi)容是否相等,是否包含某個(gè)元素,是否包含滿足某種條件(predicate)的元素,是否所有的元素都滿足某個(gè)assert
Raised events:Custom events,F(xiàn)ramework events(例如:PropertyChanged)
Object Type:是否是某種類型,是否某種類型或繼承與某種類型
一種建議的做法是,每個(gè)test方法里面只有一個(gè)assert。
而還有一種建議就是,每個(gè)test里面可以有多個(gè)asserts,只要這些asserts都是針對(duì)同一個(gè)行為就行。
目標(biāo)類:
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() + 2;
}
private int CalculateHeartBeatRate()
{
var random = new Random();
return random.Next(1, 100);
}
}
測(cè)試類:
public class PatientShould
{
[Fact]
public void HaveHeartBeatWhenNew()
{
var patient = new Patient();
Assert.True(patient.IsNew);
}
}
運(yùn)行測(cè)試:
結(jié)果符合預(yù)期,測(cè)試通過。
改為Assert.False()的話:
測(cè)試Fail。
測(cè)試string是否相等:
[Fact]
public void CalculateFullName()
{
var p = new Patient
{
FirstName = "Nick",
LastName = "Carter"
};
Assert.Equal("Nick Carter", p.FullName);
}
然后你需要Build一下,這樣VS Test Explorer才能發(fā)現(xiàn)新的test。
運(yùn)行測(cè)試,結(jié)果Pass:
同樣改一下Patient類(別忘了Build一下),讓結(jié)果失?。?/p>
從失敗信息可以看到期待值和實(shí)際值。
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,結(jié)果Pass:
忽略大小寫 ignoreCase:
string默認(rèn)的Assert是區(qū)分大小寫的,這樣就會(huì)失?。?/p>
可以為這些方法添加一個(gè)參數(shù)ignoreCase設(shè)置為true,就會(huì)忽略大小寫:
包含子字符串 Contains
[Fact]
public void CalculateFullNameSubstring()
{
var p = new Patient
{
FirstName = "Nick",
LastName = "Carter"
};
Assert.Contains("ck Ca", p.FullName);
}
Build,測(cè)試結(jié)果Pass。
正則表達(dá)式,Matches
測(cè)試一下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,測(cè)試通過。
首先為Patient類添加一個(gè)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,測(cè)試通過。
范圍, InRange:
首先為Patient類添加一個(gè)方法,病人吃飯之后血糖升高:
public void HaveDinner()
{
var random = new Random();
_bloodSugar += (float)random.Next(1, 1000) / 100; // 應(yīng)該是1000
}
添加test:
[Fact]
public void BloodSugarIncreaseAfterDinner()
{
var p = new Patient();
p.HaveDinner();
// Assert.InRange<float>(p.BloodSugar, 5, 6);
Assert.InRange(p.BloodSugar, 5, 6);
}
Build,Run Test,結(jié)果Fail:
可以看到期待的Range和實(shí)際的值,這樣很好。如果你使用Assert.True(xx >= 5 && xx <= 6)的話,錯(cuò)誤信息只能顯示True或者False。
因?yàn)镠aveDinner方法里,表達(dá)式的分母應(yīng)該是1000,修改后,Build,Run,測(cè)試Pass
到此,關(guān)于“如何使用xUnit為.net core程序進(jìn)行單元測(cè)試”的學(xué)習(xí)就結(jié)束了,希望能夠解決大家的疑惑。理論與實(shí)踐的搭配能更好的幫助大家學(xué)習(xí),快去試試吧!若想繼續(xù)學(xué)習(xí)更多相關(guān)知識(shí),請(qǐng)繼續(xù)關(guān)注創(chuàng)新互聯(lián)網(wǎng)站,小編會(huì)繼續(xù)努力為大家?guī)砀鄬?shí)用的文章!
當(dāng)前文章:如何使用xUnit為.netcore程序進(jìn)行單元測(cè)試
分享路徑:http://www.rwnh.cn/article16/gshcgg.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供用戶體驗(yàn)、虛擬主機(jī)、企業(yè)建站、App開發(fā)、做網(wǎng)站、全網(wǎng)營(yíng)銷推廣
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)