iT邦幫忙

2017 iT 邦幫忙鐵人賽
DAY 10
0
DevOps

從.Net工程師的角度來看DevOps - 到底能夠幫助什麼 之 再戰江湖系列 第 10

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

  • 分享至 

  • xImage
  •  

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

sample 程式在 github devops-psake sample/chapter16

同步發表於我的部落格:http://blog.alantsai.net/2017/01/devopsSeries-opencover-intergreateBuild.html (部落格的格式會漂亮一些)

準備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,有差別的地方都是在testRunnerExe和testRunnerArg

首先是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分數:

看到結果分數

結語

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

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


上一篇
[iThome第8屆鐵人賽 15]OpenCover 介紹篇
下一篇
[iThome第8屆鐵人賽 17]OpenCover 結果 - 涵蓋率介紹篇
系列文
從.Net工程師的角度來看DevOps - 到底能夠幫助什麼 之 再戰江湖30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言