2019年7月10日 星期三

在Azure Pipeline 裡使用 docker build 執行 asp.net core 的 unit test 後,把測試結果跟code coverage 上傳到組建裡

在Azure Pipeline 裡使用 docker build 執行 asp.net core 的 unit test 後,把測試結果跟code coverage 上傳到組建裡

在Pipeline建置時,如果要看到測試結果跟code coverage , 需要在Pipeline中建置,才能在azure devops server 的介面中看到測試結果跟程式碼含蓋範圍。像這樣
enter image description here

但是如果要把unit test 放在 docker 裡,在 multi stage builds 的過程之中執行unit test,在預設的狀況下,測試結果會在某一個build stage中,就不能使用pipeline的task來上傳測試結果。

解決方法

在docker 建置過程中做unit test , 另外產生測試結果。等到docker build 結束之後,用powershell把測試結果copy出來,然後再分別用 pipeline 的task 上傳測試結果及程式碼含蓋範圍。 就像下圖的步驟 3,4,5一樣。

enter image description here

Build docker image

因為我有好幾個測試專案,預設會產生好幾個code coverage的report 。 所以在執行dotnet test 有一些特殊的參數來讓這些report 合併成一個。

第一個是 CoverletOutputFormat=“json%2ccobertura” ,用來指定產出report的格式,注意這個 %2c 是分號 ; 的意思。 但是如果直接寫;在docker build 時會有powershell的錯誤。弄了很久才找到解法,改成%2C (是ascii code ; 的意思)就可以過了。

第二個是MergeWith=/testresults/coverage/coverage.json 。用MergeWith 來指定多個 code coverage 的report 跟誰合併,要指定report的位置在個目錄。

另外,在dockerfile 裡我有下了一個 label 叫 test=true ,這個是用來讓docker build 完之後還可以找到暫存的stage ,從裡面把我們的測試報告copy出來。

底下是我部份的dockerfile , 我的web.sln 裡面有3個程式專案及4個測試專案。

RUN dotnet restore web.sln
RUN dotnet build web.csproj -c Release -o /app/out 

# unit test
#先下一個label 
LABEL test=true
# 安裝dotnet-reportgenerator-globaltool 用來產生cobertura 格式的 code coverage report
RUN dotnet tool install dotnet-reportgenerator-globaltool --version 4.2.2 --tool-path /tools  

# %2c 是 ;(分號) 很重要!! 很重要!! 因為直接用; 會出錯。
RUN dotnet test --results-directory /testresults --logger:trx /p:CollectCoverage=true /p:CoverletOutputFormat="json%2ccobertura" /p:MergeWith=/testresults/coverage/coverage.json /p:Exclude="[xunit.*]*" /p:CoverletOutput=/testresults/coverage/ web.sln

RUN /tools/reportgenerator.exe "-reports:/testresults/coverage/coverage.cobertura.xml"  "-targetdir:/testresults/coverage/reports"  "-reporttypes:HTMLInline`;HTMLChart"

用powershell 取得測試結果

enter image description here

script說明

  1. 先找到下label=test的 docker id, 預設會新的在最上面,所以抓第 0 個
  2. 用找到的id 建立一個臨時的container
  3. 從container把測試結果copy 出來
  4. 這個臨時的container就可以移除惹
$id=$($(docker images --filter "label=test=true" -q)[0]);
docker create --name testcontainer $id;
docker cp testcontainer:/testresults ./;
docker rm testcontainer;

發行測試結果

enter image description here
測試結果格式選 VSTest
搜尋資料夾要選對,我的例子是 testresults

發行程式碼涵蓋範圍結果

enter image description here
程式碼涵蓋範圍工具 選cobertura
摘要檔案 跟 報告目錄 路徑要設對


如果都成功了,就可以在組建的摘要裡看到測試結果了,就像第一張圖一樣。 也可以在測試的tab看到詳細的結果
enter image description here

同場加映

看完上面的,有沒有感到奇怪,為什麼沒有code coverage 的詳細資料。
因為這是 Azure Devops Server 2019 目前版本的bug,但是線上版的Azure devops 是有詳細資料的。

在 2019/5/22 己經有人回報給 visual studio team了 ,MS也有回覆下個release會修好。

Code coverage tab missing in Azure DevOps Server

另外

前端(angular) 的unit test 也可以用類似的方法,產出測試報告跟上傳到devops server上,有空再來分享另一段血淚史。

沒有留言:

張貼留言