經過一段時間的介紹,相信對於使用psake來建制專案已經沒什麼問題了 - 我們就要開始進入建制的下個階段,也就是測試。
專案建制起來只是基本條件,但是單元測試是否有通過才是保證程式碼品質的一種方式,因此,不跑單元測試更本就不完整。
在接下來幾篇,將會介紹幾個常見的unit test的framework,先從xunit開始。
sample 程式在 github devops-psake sample/chapter10
同步發表於我的部落格:http://blog.alantsai.net/2016/12/devopsSeries-runtest-XUnit.html (部落格的格式會漂亮一些)
首先,我們先建立一個新的Library 專案 ,然後透過nuget安裝:
Install-Package xunit -Version 2.1.0 - xunit的test framework
Install-Package Microsoft.AspNet.Mvc -Version 5.2.3 - 等一下測試controller,所以需要有mvc的reference
再來,我們就建立一個簡單的test測試HomeController的Contact方法:
public class HomeControllerTest
{
[Fact]
public void Contact()
{
// Arrange
HomeController controller = new HomeController();
// Act
ViewResult result = controller.Contact() as ViewResult;
// Assert
Assert.NotNull(result);
}
}
準備好了之後,我們就可以準備build script的部分。
在準備build script之前,我們需要知道,測試是如何執行的。
一般來說,如果我們是開發,可能就直接用VS的Test Runner來執行,不過每一個test framework一定有提供console執行的版本,所以我們第一件事情就是要把這個console程式下載下來。
再來,我們就可以在psake建立一個新的task,用作於執行xunit的測試。
最後,如果執行成功的話,我們就可以看到結果
安裝xunit的console runner:Install-Package xunit.runner.console -Version 2.1.0
首先,我們在default.ps1定義一個新的task,XunitTest
由於這個task可以被單獨執行,因此相依性也要設定好,看起來就會是:
task XunitTest -depens Compile -description "執行Xunit測試"{
Write-Host "準備執行Xunit測試"
Write-Host "完成執行Xunit測試"
}
在確認執行之前,我們要先定義好幾個參數:
取得執行Xunit的Console Runner位置 - $xunitExe
由於我們buildProject有加入xunit的 console runner,因此在package可以找到
測試結果要儲存的位置 - $xunitTestResultDirectory
我們 會把不同測試Framework分開放,所以會建立一個專門放Xunit
要執行測試的路徑確認 - $xunitTestPath
這個邏輯是透過看看建製出來的專案有沒有 xunit 開頭的dll - 有就算是要被執行。這裡面取得的結果是DirectoryInfo,原因我們稍後提到
$xunitExe = ((Get-ChildItem("$solutionDirectory\packages\xunit.runner.console*")).FullName |
Sort-Object $_ | select -Last 1) + "\tools\xunit.console.exe"
$xunitTestResultDirectory = "$buildTestResultDirectory\Xunit"
$xunitTestPath = Get-ChildItem $buildTempDirectory -Recurse -Filter xunit*.dll |
Select -ExpandProperty DirectoryName -Unique | % { [io.directoryinfo]$_ }
要執行xunit console runner,我們首先要找出所有要執行的dll清單,在上面我們已經找到了所有專案路徑的清單,所以可以用這個取得所有的dll清單。
建製出來的dll名稱會和專案名稱一樣,因此我們可以用for迴圈方式把每一個找到的xunit專案路徑變成對應的dll路徑,然後最後在把他這個清單組成一個空白分開的字串
# 組執行的dll
$testDlls = $xunitTestPath | % {$_.FullName + "\" + $_.Name + ".dll" }
$testDllsJoin = [string]::Join(" ", $testDlls)
再來就是要確認執行xunit console runne所會使用的參數:
$dll 路徑
這個就是上面組出來的參數
-xml $路徑
執行結果要用 xml 格式 儲存在某個路徑
-html $路徑
執行結果用html格式儲存在某個路徑
-nologo
讓執行的時候,不出現xunit相關的logo資訊 - 減少輸出的內容
-noshadow
本來執行測試的時候,xunit會複製一份出來避免執行測試的時候資源被使用。不過我們用script執行之後,能夠確認不會有其他用到,所以可以不用做複製的動作,加快執行速度。
exec{ &$xunitExe $testDllsJoin -xml $xunitTestResultDirectory\xUnit.xml `
-html $xunitTestResultDirectory\xUnit.html `
-nologo -noshadow}
如果對於還有那些參數可以傳入有興趣,可以直接執行Xunit的console,不要傳入任何參數,就會看到所有可以輸入的參數清單。
最後,加入一些日誌方面的資訊,task變成:
task XunitTest -depends Compile -description "執行Xunit測試" `
{
# 取得Xunit project的路徑
$xunitTestPath = Get-ChildItem $buildTempDirectory -Recurse -Filter xunit*.dll |
Select -ExpandProperty DirectoryName -Unique | % { [io.directoryinfo]$_ }
if(Test-Path $xunitTestPath){
Write-Host "建立Xunit測試結果的資料夾 $xunitTestResultDirectory"
New-Item $xunitTestResultDirectory -ItemType Directory | Out-Null
Write-Host "總共有 $($xunitTestPath.Count) 個專案"
Write-Host ($xunitTestPath | Select $_.Name)
Write-Host "準備執行Xunit測試"
# 組執行的dll
$testDlls = $xunitTestPath | % {$_.FullName + "\" + $_.Name + ".dll" }
$testDllsJoin = [string]::Join(" ", $testDlls)
Write-Host "執行的 Dll: $testDllsJoin"
exec{ &$xunitExe $testDllsJoin -xml $xunitTestResultDirectory\xUnit.xml `
-html $xunitTestResultDirectory\xUnit.html `
-nologo -noshadow}
Write-Host "完成執行Xunit測試"
}
}
最後,把XUnitTest加入Test的相依task
task Test -depends Compile, Clean, XunitTest -description "執行Test" {
Write-Host $testMsg
}
到目前為止,準備都完成了,這個時候執行build.ps1,我們就會看到除了建制之外,單元測試也有被執行。
然後我們在testResult\Xunit下面也有對應檔案產生出來
在這篇,介紹了如何建立出XUnit的測試結果,並且我們可以看到最後執行完的產出。在未來,其實可以把產出的xml做二次加工而產生出更漂亮的報告,目前來說我們先執行到這一步。
在下一篇,我們要來看看另外一個常見的test framework,NUnit的task建立方式。