Alan Tsai 的學習筆記


學而不思則罔,思而不學則殆,不思不學則“網貸” 記錄軟體開發的點點滴滴 著重於微軟技術、網頁開發、DevOps、C#, Asp .net Mvc、Azure、AI、Chatbot、Docker、Data Science

[iThome第8屆鐵人賽 16]OpenCover 整合篇

在上篇介紹了OpenCover的基本運作概念和為什麼要使用OpenCover,在這篇將會實際把OpenCover整合到Build Script裡面。

準備Build Script

要把OpenCover整合進入Build script需要做幾個事情:

  1. 把OpenCover加入到Build專案
  2. 建立一個Helper用來執行OpenCover
  3. 準備好執行Helper的參數
  4. 調整測試呼叫方式

把OpenCover加入到Build專案

這個部分需要先用Nuget把Opencover加入(Install-Package Opencover),之後,在Build Script裡面會多增加一個property

$openCoverExe = (Get-PackagePath $packageDirectoryPath "OpenCover") +

		"\tools\OpenCover.Console.exe"

建立一個Helper用來執行OpenCover

在上篇提到,其實opencover有一個profiler,這個profiler會執行Test Runner,然後profiler會監控test runner記錄執行測試的涵蓋率。

因此,變成不直接呼叫TestRunner了,而是透過OpenCover,因此建立一個helper方法會方便呼叫測試。

OpenCover其實有滿多的設定,下面會一個一個介紹:

target
這個是用來執行Test Runner的路徑
targetargs
這邊是指要傳入給target的參數
output
這邊指的是Opencover的涵蓋率結果要儲存的位置
register
一直有提到OpenCover有一個profiler,這個profiler其實是一個com的library,因此要使用的話需要註冊和給權限。這邊我們使用參數user指的是profiler的權限同等於 目前user,因此避免到時候換build server或者換環境會有環境設定問題
filter
還記得上篇提到關於filter用來決定那些Assembly要涵蓋進來那些要排除,這個就是這邊傳入。
excludebyattribute
上篇提到透過attribute方式設定那些要過濾
excludebyfile
上篇提到,透過檔名過濾的地方
skipautoprops
這個指的是 程式碼裡面用的Property (常說的getter和setter,例如:public string Name{get;set;}),因為一般沒有邏輯,所以加入這個參數表示那些不要進入涵蓋範圍
mergebyhash
這個指的是,同一個dll可能會被多次載入(不同test framework等),加入這個設定表示,不管載入幾次,只要hash一樣,永遠算1次
mergeoutput
還記得提到說有不同test framework如何整合結果在一起?只要有設定這個參數,加上所有的output path一致,就會把結果整合
hideskipped
上面雖然有提供一些過濾方式,但是最後報表還是會有包含,只是說那些被忽略而已。因此這個參數能夠把被忽略的不在報告顯示。如果要讓報告乾淨一些,就可以讓他們不顯示
returntargetcode
這個指的是,最後的exit code要用target的作為回傳,這樣如果執行test有失敗,才能夠看到

對於幾個參數有了解之後,在helper就增加了一個Run-TestWithOpenCover

function Run-TestWithOpenCover {

	[CmdletBinding()]

	param([Parameter(Position=0,Mandatory=1)]$testRunnerExe,

		 [Parameter(Position=1,Mandatory=1)]$testRunnerArg,

		 [Parameter(Position=2,Mandatory=1)]$openCoverExe,

		 [Parameter(Position=3,Mandatory=1)]$openCoverResult,

		 [Parameter(Position=4,Mandatory=1)]$filter,

		 [Parameter(Position=5,Mandatory=1)]$excludeAttribute,

		 [Parameter(Position=6,Mandatory=1)]$excludeFiles)



	Exec { &$openCoverExe "-target:$testRunnerExe" `

						"-targetargs:$testRunnerArg" `

						"-output:$openCoverResult" `

						-register:user `

						"-filter:$filter" `

						-excludebyattribute:$excludeAttribute `

						-excludebyfile:$excludeFiles `

						-skipautoprops `

						-mergebyhash `

						-mergeoutput `

						-hideskipped:All `

						-returntargetcode}

}
在上有些參數有用雙引號包住,例如"-targetargs:$testRunnerArg" `,這個原因是在Powershell如果參數有空白,要連參數名一起用雙引號包住。

準備好執行Helper的參數

Helper準備好了之後,在default.ps1要準備好幾個會傳入的參數,最主要是filter的參數的部分。所以,和其他參數一樣,現在Property裡面定義:

$openCoverResult = "$buildTestCoverageDirectory\openCover.xml"

$openCoverFilter = "+[*]* -[xunit.*]* -[*.NunitTest]* -[*.Tests]* -[*.XunitTest]*"

$openCoverExcludeAttribute = "System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute"

$openCoverExcludeFie = "*\*Designer.cs;*\*.g.cs;*\*.g.i.cs"

這些參數的用意透過剛剛介紹的參數作用應該很清楚,這邊就不做額外介紹。

在結束之前,還有一個地方要調整,就是BundleConfig.cs

這邊將會用ExcludeFromCodeCoverageAttribute加入到他的Class裡面,用來把它排除在Coverage裡面

[ExcludeFromCodeCoverage]

public class BundleConfig

{

....

調整測試呼叫方式

最後,就是調整3個測試的執行方式。做法都一樣,把本來呼叫exec改成呼叫在第二步建立的helper,有差別的地方都是在testRunnerExetestRunnerArg

首先是Xunit:

$xmlResult = "$xunitTestResultDirectory\xUnit.xml"

$htmlResult = "$xunitTestResultDirectory\xUnit.html"



$targetArg = "$testAssembly -xml $xmlResult -html $htmlResult -nologo -noshadow"

Run-TestWithOpenCover -testRunnerExe $xunitExe `

			-testRunnerArg $targetArg `

			-openCoverExe $openCoverExe `

			-openCoverResult $openCoverResult `

			-filter $openCoverFilter `

			-excludeAttribute $openCoverExcludeAttribute `

			-excludeFiles $openCoverExcludeFie `

再來是NUnit:

$targetArg = "$testAssembly --result=$nunitTestResultDirectory\nUnit.xml"



Run-TestWithOpenCover -testRunnerExe $nunitExe `

			-testRunnerArg $targetArg `

			-openCoverExe $openCoverExe `

			-openCoverResult $openCoverResult `

			-filter $openCoverFilter `

			-excludeAttribute $openCoverExcludeAttribute `

			-excludeFiles $openCoverExcludeFie `

最後是MSTest:

$targetArg = "$testAssembly /Logger:trx"



Run-TestWithOpenCover -testRunnerExe $msTestExe `

			-testRunnerArg $targetArg `

			-openCoverExe $openCoverExe `

			-openCoverResult $openCoverResult `

			-filter $openCoverFilter `

			-excludeAttribute $openCoverExcludeAttribute `

			-excludeFiles $openCoverExcludeFie `

執行結果

以上都做完之後,就可以執行做測試,並且會看到Coverage分數:

image
看到結果分數

結語

在這篇調整了build script,讓opencover進入並且產生出了測試涵蓋率的結果。

但是,這個結果畢竟比較偏summary,看不出到底那些沒cover到,所以在下篇將會進一步去看OpenCover所產生的結果xml,和如何把它轉換成人看得懂的格式


如果文章對您有幫助,就請我喝杯飲料吧
街口支付QR Code
街口支付QR Code
街口支付QR Code
支付寶QR Code
街口支付QR Code
微信支付QR Code
comments powered by Disqus