軟件的單元測試關注是的軟件最小可執行單元是否可以正常執行,可是軟件是由一個個最小執行單元組成的集合體,單元與單元之間存在着種種依賴或聯繫,因此在軟件開發時僅僅確保最小單元的正確每每是不夠的,爲了保證軟件可以正確運行,單元與單元之間的集成測試是很是必要。
另外上一篇文章只是介紹瞭如何使用xUnit.net對.Net Core程序進行簡單(無參)的單元測試以及計算代碼的覆蓋率,可是在實際的測試工做中,每每會經過語句覆蓋、條件/分支覆蓋(白盒)方式以及等價類、邊界值等(黑盒)方式來設計測試用例,這些用例的測試的關鍵點在於傳入測試方法的參數是不一樣的,若是使用無參測試方法那麼針對不一樣的測試用例就須要編寫大量的測試方法,這是不現實的。
本文將從如下幾個方面,在單元測試的基礎上介紹如何完成數據驅動測試以及代碼依賴的集成測試:php
集成測試簡單的理解就是在單元測試的基礎上,將各個單元根據其依賴關係集成起來,檢查代碼是否可以正確運行,集成測試根據軟件開發方式的不一樣或者軟件架構不一樣也有不一樣的集成方式,好比面向過程的設計方式和麪向對象設計方式、單體架構以及微服務分佈式架構等等。
本文涉及到的僅僅是面向對象編程中類與類之間依賴的集成測試。html
數據庫是大部分軟件系統不可缺乏的組件,因此在集成測試時與數據庫集成是一種常見的測試場景,下面就開始介紹如何經過xUnit.Net來測試。
1. 編寫被測試代碼:
在被測試項目中引入EFCore以及相關組件:git
添加DBContext以及相應的數據操做代碼:github
注:此處使用LocalDB做爲數據庫完成測試,若是使用SQL Server修改鏈接字符串便可。sql
用戶倉儲中實現了用戶添加以及根據姓名查詢的方法。
注:完成代碼編寫後,須要將實體代碼遷移到數據庫,先經過Add-Migration添加遷移代碼,而後經過update-database命令將數據更新到數據庫,遷移方法可參考:https://docs.microsoft.com/en-us/ef/core/get-started/full-dotnet/new-db
2.編寫測試代碼:數據庫
測試代碼也很是簡單,就是建立一個SQLServer的用戶倉儲實例,而後經過構造的方式將其注入到UserManager類型中使用,後續UserManager的建立、查詢用戶的方法將經過該倉儲實現。
3.測試運行結果:編程
這裏的迴歸指的是迴歸測試,迴歸測試是指當修改了舊的代碼後須要從新對舊代碼進行測試確認這次修改沒有影響到已有代碼。通常來講使用xUnit.Net實現的測試均是可迴歸的,由於測試代碼不變,且測試代碼能夠重複執行,另外測試代碼也被代碼版本管理工具管理,當修改代碼後從新執行全部測試方法便可。
可是與數據庫相關的測試又有所區別,數據庫是數據持久化工具,對數據的每一次操做都會被持久化,假設有兩個測試用例,第一是添加一條數據,第二是查詢這條數據的數量是否爲1,那麼這兩個測試在第一次運行的時候是沒有問題的,可是再次運行時第一個用例可能主鍵衝突沒法被添加,或者添加成功後第二個用例查詢結果爲2,致使測試失敗,這樣的測試視爲不可迴歸。
下面就介紹如何使用xUnit.Net實現數據庫集成的迴歸測試:架構
要實現數據庫集成測試的可迴歸性,其實最主要的問題在於每次執行完單元測試後數據庫的狀態都是不一樣的,那麼解決這個問題在每次執行測試前將數據庫初始化是否就能夠解決了呢?
看下面代碼:分佈式
首先爲測試類添加構造方法,在構造方法中初始化數據庫。微服務
而後在測試方法中添加用戶數量測試斷言,當添加完成用戶後,應該一共存在1個用戶。
執行測試方法:
不管執行多少次測試都是經過的,這意味着每次添加用戶後用戶數量均爲1,這樣就達到了測試的可迴歸性。
可是真實的開發過程當中,不可能只有一個測試類型,並且若是爲每個測試類型都添加初始化數據庫的代碼,那麼這些單元測試將會執行的很是慢(數據庫的初始化很是耗時),那麼要如何解決這個問題?
Fixture是xUnit.Net中的一項特性,它能夠用來共享測試上下文,Fixture能夠譯爲固定裝置,換句話說就是把一個內容固定住,使該內容能夠在被指定的範圍內使用。xUnit.Net中Fixture有兩種類型,分別是ClassFixture和CollectionFixture,它們對應的是在一個測試類型裏面共享和一個測試類型集合中共享上下文,Fixture的做用有不少,下面將介紹如何使用Fixture來共享數據庫被初始化這一狀態(不須要重複初始化):
1. 建立一個Fixture類型:
Fixture其實是一個普通的C#類型,惟一須要注意的是它使用構造方法初始化數據、使用Dispose來釋放或者清理數據,簡單的一個Fixture類型以下:
2. 爲單個類型使用ClassFixture:
從代碼中能夠看到經過構造方法初始化的代碼已經被註釋了,實現IClassFixture接口後,再次執行測試方法,能夠看到測試仍然是可迴歸的。
3. 爲多個類型使用ICollectionFixture:
首先須要在DatabaseFixture的基礎上添加一個實現ICollectionFixture的類型:
兩個要點分別是須要使用CollectionDefinition特性,而後類型須要實現ICollectionFixture<T>接口。
在測試類型上經過Collection特性,指定以前定義的Collection名稱來應用該CollectionFixture:
而後屢次執行測試方法,能夠發現測試仍然是可迴歸的:
注:在共享測試上下數據時(包括共享數據庫數據),可能會由於測試方法執行順序致使測試失敗,可是xUnit.Net中沒有提供按順序執行實現方式,默認是按照方法命名,若是須要按照必定順序執行測試,可參考官方的例子:https://github.com/xunit/samples.xunit/tree/master/TestOrderExamples
涉及到數據庫的測試,極可能在測試以前數據庫就會存在一些已有的測試數據,使用xUnit.Net來編寫測試代碼時,能夠將測試數據的初始化放到Fixture類型中,可是要如何對這些數據進行管理呢?通常來講使用SQL腳原本管理數據庫的測試數據是一種不錯的方式,由於這樣測試數據與代碼解耦,維護數據時僅須要維護SQL腳本文件便可。
下面就介紹一下如何在xUnit.Net中使用SQL腳本文件管理以及初始化數據:
1.建立一個SQL腳本:
注:須要將文件的「複製到輸出目錄」設置爲「老是複製」或者「有更新複製」:
2.在Fixture類型初始化數據庫時,執行SQL腳本初始化數據:
下面代碼首先去Data目錄下查找.sql的全部文件,而後依次執行這些SQL腳本。
3.修改測試代碼(由於腳本添加了2條數據,因此指望值應該是3條):
4.執行測試:
測試成功。
文章最開始提到過,不論是白盒的覆蓋測試仍是黑盒的邊界/等價測試,它們最直接的體現就是「參數」,傳入被測試方法的參數。而這些參數實際上就是「測試用例」,爲每個測試用例編寫一個測試方法是不合理的,因此須要一種方法經過變換參數來完成測試,而且儘量的重用測試代碼。這就是數據驅動測試。
Theory和InlineData是xUnit.Net中提供的數據驅動(參數化)測試的功能特性,下面是一個theory以及InlineData的應用示例:
運行結果:
經過InlineData就能夠輕易的將測試用例的數據應用到測試方法上,並完成指望的測試。可是當添加新的測試用例時就須要對代碼文件進行修改,測試用例放置在代碼中管理也不是很是方便,有沒有一種能夠獨立管理測試用例數據的方法呢?
xUnit.Net沒有提供內置的Excel數據加載功能,可是它的拓展性很好,能夠經過實現DataAttribute實現一個Theory的數據源提供器:
1. 實現DataAttribute抽象類,實現Excel的Theory數據提供器:
下面是實現Excel數據加載的核心方法:
以上方法須要注意如下幾點:
注:此處使用的Excel文件讀取組件爲:https://github.com/ExcelDataReader/ExcelDataReader
DataAttribute完整代碼見:https://github.com/yqszt/xUnitTestDemo/blob/master/XUnitTestProject/ExcelDataAttribute.cs
2.使用ExcelDataAttribute:
3. 在AdditionTestCase.xls中添加測試用例數據:
注:須要將AdditionTestCase.xls的複製到輸出目錄屬性設置爲「老是複製」或「複製新文件」。
4.執行測試方法:
測試成功。
本文主要介紹了.Net Core使用xUnit.Net實現了與數據的集成測試並經過Fixture的方式實現了數據庫的初始化,保證了測試的可迴歸性。另外還介紹瞭如何使用xUnit.Net來實現數據驅動測試,數據驅動測試能夠簡單地經過添加用例數據的方式來提升測試質量,還能夠便捷的對測試用例進行管理。
本文示例代碼:https://github.com/yqszt/xUnitTestDemo
參考:
https://en.wikipedia.org/wiki/Integration_testing
https://en.wikipedia.org/wiki/Data-driven_testing
https://xunit.github.io/docs/getting-started-dotnet-core#write-first-theory
http://dotnetliberty.com/index.php/2015/12/31/fast-asp-net-5-integration-testing-with-xunit/
https://github.com/MisterJames/GenFu
http://ikeptwalking.com/writing-data-driven-tests-using-xunit/
https://wandering.life/data-driven-testing-xunit-vs2017/
https://github.com/ExcelDataReader/ExcelDataReader
http://xunitpatterns.com/Testing%20With%20Databases.html
https://xunit.github.io/docs/shared-context