2016年12月23日 星期五

[iThome第8屆鐵人賽 10]執行測試 1 - XUnit .Net

經過一段時間的介紹,相信對於使用psake來建制專案已經沒什麼問題了 - 我們就要開始進入建制的下個階段,也就是測試。

專案建制起來只是基本條件,但是單元測試是否有通過才是保證程式碼品質的一種方式,因此,不跑單元測試更本就不完整。

在接下來幾篇,將會介紹幾個常見的unit test的framework,先從xunit開始。

準備Xunit 測試專案

首先,我們先建立一個新的Library 專案 ,然後透過nuget安裝:

  1. Install-Package xunit -Version 2.1.0 - xunit的test framework
  2. 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的測試。

最後,如果執行成功的話,我們就可以看到結果

1. 在build專案安裝xunit的console runner

安裝xunit的console runner:Install-Package xunit.runner.console -Version 2.1.0

2. 準備build script - task 定義

首先,我們在default.ps1定義一個新的task,XunitTest

由於這個task可以被單獨執行,因此相依性也要設定好,看起來就會是:

task XunitTest -depens Compile -description "執行Xunit測試"{
 Write-Host "準備執行Xunit測試"

 Write-Host "完成執行Xunit測試"
}

3. 準備build script - 參數定義

在確認執行之前,我們要先定義好幾個參數:

取得執行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]$_ }

4. 準備執行 xunit console runner

要執行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
}

執行Xunit的測試

到目前為止,準備都完成了,這個時候執行build.ps1,我們就會看到除了建制之外,單元測試也有被執行。

image
執行的output結果

然後我們在testResult\Xunit下面也有對應檔案產生出來

image
執行完結果內容

結語

在這篇,介紹了如何建立出XUnit的測試結果,並且我們可以看到最後執行完的產出。在未來,其實可以把產出的xml做二次加工而產生出更漂亮的報告,目前來說我們先執行到這一步。

在下一篇,我們要來看看另外一個常見的test framework,NUnit的task建立方式。


沒有留言 :

張貼留言