系列目錄html
爲了支持跨平臺,微軟爲.net平臺提供了.net core test sdk,這樣第三方測試框架諸如Nunit,Xunit等只須要按照sdk提供的api規範進行開發即可以被dotnet cli工具調用,這樣就解決了在持續集成過程當中第三方框架依賴於windows平臺上的各自runner的問題,使得測試框架開發者不須要花費很大功夫就能夠快速遷移到.net core平臺,同時封裝了各測試框架的實現細節,對外暴露統一調用接口,大大減小devops開發者的工做量.web
做爲單元測試基礎知識介紹,這裏只介紹經常使用單元測試框架Nunit和Xunit如何在.net core平臺上使用,並介紹因爲.net core的變化所引發的須要注意的測試代碼的相應改變,對於如何在Jenkins環境中自動完成測試的相關內容Jenkins基礎知識裏面介紹正則表達式
考慮到實際工做中可能有的項目組已經使用或者嘗試使用xunit,而且.net core對xunit支持較好,諸多開源項目的單元測試也都使用的是Xunit,本章節做爲補充對Xunit基礎知識進行講解,以幫助還不太瞭解這個框架的同窗快速入門.windows
咱們知道在.net framework下相要對mvc項目進行集成測試很是困難,一方面.net http管道里有不少黑盒子,開發者對它的實現細節一無所知,兩者須要mock的對象太多,工做量巨大.所以很難在持續集成環境中對web項目進行集成測試.開發者或者測試人員大都依賴postman,fiddler,以及瀏覽器的http請求插件來進行集成測試,這樣帶來的一個很大問題這些http請求很難複用,更難以有效的組織管理.即便使用postman這樣強大的http工具若是測試接口過多代碼也會變得一塌糊塗,過一段時間後想要知道哪一個方法是測試哪一個接口用的就須要經過搜索來導航到指定的測試方法,而且不少時候有於各模塊有相同名稱的方法,每每須要先找到方法所在的area,而後再找到controller而後再找到相應方法...若是出現問題的代碼過多每每把開發者搞的焦頭爛額,苦不堪言.
幸運的是在.net core裏很容易模擬一個httpt管道,這一方面使得集成測試在持續集成環境中使用提供了可能,另外一方http請求寫成程序裏,能夠很方便的導航到指定的測試方法,極大提供可維護性.本章節最後會介紹如何搭建一個.net core web項目的selfhost環境以供在單元測試框架中使用.api
下面咱們將簡要介紹如何在vs中配置xunt環境以及Xunit斷言的基本使用瀏覽器
Xunit是.net平臺下的一款單元測試工具,相似Nunit.可是更爲輕量,更加專一於單元測試而不像Nunit提供了不少額外的功能
sass
.net core對Xunit支持較好,VisualStudio 2017提供有一個Xunit單元測試模板能夠很方便的建立一個Xunit單元測試項目.mvc
如圖,在visual studio裏建立項目時,選擇.net core項目,而後從模板裏面找到Xunit單元測試項目即可以建立一個Xunit單元測試項目了.框架
咱們打開剛建立的項目右鍵選擇"Nuget包管理",從包管理工具裏咱們能夠看到,實際上這個模板引用了xunit,和xunit.runner.visualstudio這兩個包.這樣,咱們也能夠本身手動建立一個.net core類型的庫文件,而後引入這兩個包,能達到一樣的效果.工具
這裏建議你們經過模板來建立單元測試項目,由於單元測試框架不一樣版本可能須要引用不一樣的包,沒有經驗的同窗經常因爲引用的包不對致使單元測試項目跑不起來,搞得灰頭土臉,很是鬱悶.
咱們編寫如下單元測試代碼
public class UnitTest1 { [Fact] public void Test1() { int intt = 3 + 2; Assert.True(intt==5); } }
經過以上代碼咱們看到Xunit就測試斷言和Nunit很相似(這裏指Nunit3,早期版本Nunit差別較大,建議大這在工做中也儘可能選用Nunit3,而不是1或者2)
這裏有一點差別須要指出,Xunit並不須要對單元測試類進行註解(Nunit是須要的,不然沒法識別),只須要在須要測試的方法上加上fact註解便可.
單元測試方法的運行也和前面講的Nunit單元測試運行方法相同,這裏再也不贅述.
雖然Xunit和Nunit在斷言上有不少類似的地方,而且有愈來愈像的趨勢,可是仍然有很多差異,所以這裏仍然會對Xunit的斷言功能進行一個全面的列舉,以供你們速查.而且有時候會指出它和Nunit的差異或者指出Nunit中比較難以實現或者技巧性很強的功能如何在Xunit裏實現.若是有讀者直接閱讀本章節而沒有了解過Nunit,能夠有選擇的略過兩者比較的內容.
這裏首先指出一個很大的差異.Xunit裏並無像Nunit裏的stringAssertion,FileAssertion和CollectionAssertion,而是全部的斷言都在Assert靜態類裏,方法也不是不少,語義也相對更加明確,很適應沒有單元測試基礎的同窗快速入門.
下面開始介紹Xunit裏的斷言方法
Assert.Null
用於斷言一個對象是不是Null
這個方法有一個相對含義的斷言就是Assert.NotNull,不少其它的方法也有帶Not的斷言,很容易理解.
Assert. Assert.Equal
此方法有不少重載,用於比較兩個字符串,int,decimal或者對象類型是否相等.
注意這裏比較兩個對象是否相等時,至關於Object.equals()來比較兩個對象是否相等
這個方法用於比較兩個double類型值是否相等時,能夠指定精度.
Assert.StrictEqual
從字面上來看,它用於比較兩個對象是不是嚴格相等,然而它的表現行爲和以上Equal方法很是相似,並非比較兩個對象內存地址是否相等
.實際上它是在比較的時候指定一個默認的比較器
.這個方法着實很是讓人困惑.
Assert.same
用於比較兩個對象運行是是否指定同一塊內存地址,若是要比較兩個對象是否徹底相等,則使用它.
注意,雖然Assert.same接收的是兩個object類型對象,可是不建議用它來比較簡單類型,它實際上是用於比較兩個對象是否指向同一內存地址,所以只有比較引用對象纔是有意義的.這個方法應該設計成泛型方法才比較好,不知道爲何要這樣設計.
Assert.StartsWith Assert.EndsWith
用於斷言一個字符串是否以特定字符(串)開頭(結尾),而且這兩個方法都有一個重載用於指定是否忽略大小寫
用過Nunit的同窗可能知道,Nunit裏要實現區分大小寫的StartsWith有點麻煩.
Assert.True Assert.False
用於斷言兩個布爾變量(包括可空)的值是不是真(假).
Assert.All
用於斷言集合裏的全部元素是否都知足經過測試,奇怪的是這個方法接收的是Action
下面舉個用於斷言集合裏的元素值是否都大於0的例子來看看如何使用它
[Fact] public void Test1() { int[] intt = {3, 4, 5, 9, 22}; Assert.All(intt, t => Assert.True(t > 0)); }
注意以上寫法,因爲不接收Func<T,bool>類型委託,所以以上方法不能想固然的寫爲 Assert.All(intt, t => t>0);
這樣將致使編譯錯誤.
Assert.Contains
這個方法有多個重載,功能也很是多,可是語義都很是明確.
用於斷言字符串是否包含指定字符串
至關於字符串裏的Contains,而且表現行爲相似,也有一個重載支持不區分大小寫
用於斷言集合是否包含指定元素
請看如下代碼
[Fact] public void Test1() { int[] intt = {3, 4, 5, 9}; Assert.Contains(4, intt); }
以上代碼用於斷言集合intt裏是否包含元素4,顯然是包含的
注意,對於包含引用對象的集合判斷是否包含某一元素這一個元素必須和集合中的某一個元素的引用地址同樣.這不少時候並非咱們想要的行爲,多數時候引用對象的對應的字段分別相等時咱們就認爲它相等,更極端的狀況是某些狀況下兩個對象只有某一個或者少數幾個字段相等時咱們也認爲相等,這要看具體實際業務.前面講Nunit時對這個問題有過詳細講解.這裏Contains方法一樣有一個重載以支持一個
比較器
,用於自定義相等性邏輯.
還有一點須要指出,Contains方法只能斷言集合是否包含某
一個
元素,而不能斷言是否包含某幾個元素(也即一個集合是不是另外一個集合的子集),Nunit裏並無提供直接方法用於處理這樣的問題.有些同窗可能認爲Assert.Subset是用來解決這個問題的,然而並非,Subset只能用於實現了ISet接口的集合,不少時候並非特別有幫助.
用於斷言集合中是否包含指定類型的元素
這個重載方法語義稍顯不是很明確,它其實至關於linq裏的any方法,只要有一個(一些)知足條件的元素就會返回true
[Fact] public void Test1() { int[] intt = {3, 4, 5, 9}; Assert.Contains(intt, a => a > 3); }
以上方法用於斷言intt集合中是否包含大於3的元素,顯然是包含的.
用於斷言集合是否不包含任何元素,也即集合是不是一個空集合
Assert.Matches
此方法接收兩個參數,第一個表示要匹配的正則規則,第二個表示要測試的字符串,語義相似正則表達式裏的IsMatch
Assert.InRange
用於斷言指定元素是否在指定的範圍內
[Fact] public void Test1() { Assert.InRange(20, 3, 20); }
以上代碼片斷斷言20是否在3到20這個範圍內,顯然是在的.
此方法支持一個重載接收一個Icomparer參數用於自定義一個比較器,這樣就能夠判斷任意對象是否在某一範圍內,有這方面需求的同窗能夠研究一下
Assert.Single
用於斷言集合只包含 一個
元素,這個方法有幾個重載.
用於斷言集合中是僅包含一個元素,這個重載可能大部分時候不是頗有用
[Fact] public void Test1() { Assert.Single(new[] {3}); }
[Fact] public void Test1() { Assert.Single(new[] {3,4,5,9},3); }
以上代碼斷言集體中只有一個元素是3
此方法至關於對集合執行linq的first方法
[Fact] public void Test1() { Assert.Single(new[] {3,4,5,9},a=>a>5); }
以上方法斷言集合中的這個是否只包含一個大於5的元素.
此方法至關於linq裏面的single方法的有參重載
Assert.IsAssignableFrom
用於斷言實例對象的類型是不是一個類型的子類(或者自己)
這個方法Nunit裏也有,和反射裏的
IsAssignableFrom
語義相同
Assert.IsType
用於斷言實例對象的類型是不是某一指定類型
和IsAssignableFrom相比,此方法要求實例對象類型必須確切地是某一類型