Alan Tsai 的學習筆記


學而不思則罔,思而不學則殆,不思不學則“網貸” 為現任微軟最有價值專家 (MVP)、微軟認證講師 (MCT) 、Blogger、Youtuber:記錄軟體開發的點點滴滴 著重於微軟技術、C#、ASP .NET、Azure、DevOps、Docker、AI、Chatbot、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
台灣 Pay QR Code
台灣 Pay QR Code
Line Pay 一卡通 QR Code
Line Pay 一卡通 QR Code
街口支付QR Code
支付寶QR Code
街口支付QR Code
微信支付QR Code
comments powered by Disqus