GitLab CI - 在 Merge Request(MR) 中檢視 PHP 測試代碼覆蓋 (Code Coverage) 情況
2022.06.30 Update
於GitLab CI/CD 手冊上發現 artifacts:reports:cobertura
在 GitLab 15.0 中移除,替換為 artifacts:reports:coverage_report
,因此更新底下內容。
2021.06.14 Update
在上一篇 在 Pipeline 檢視 PHPUnit 單元測試報告,透過 artifacts:reports:junit
的機制,使每次 Pipeline 執行後,就能馬上看到單元測試報告,有了測試報告之後,可能就會開始思考,那 Code Coverage 測試代碼覆蓋的狀況,是不是也可以在 Merge Request 的過程中就看到呢?
答案是可以的,而且在 GitLab CI/CD 的免費版本中就有這個功能。在 GitLab 12.9 版後,只需要透過 artifacts:reports:coverage_report
並作相關設定,就可以搜集 Cobertura XML 格式的報表就可以完成。這部分與 artifacts:reports:junit
的原理是一樣的,只需要讓 Pipeline 的工作可以產出所需要的格式的檔案,透過 artifacts:reports:coverage_report
將檔案搜集起來,就可以在 Merge Request 的畫面中看到視覺化的測試代碼覆蓋情況。
那麼,在 PHP 該怎麼做出符合Cobertura XML格式的測試程式碼覆蓋狀況檔案呢?
如上圖(取自官方Test coverage visualization文件圖片),在圖片中,呈現綠色
線條的部分,代表測試有執行到的部分,而橘色
的部分則代表沒有測試程式覆蓋到。
在 GitLab 官方文件上提到了幾個語言及其支援的工具或外掛,如:
- Ruby - simplecov-cobertura
- Golang - gocover-cobertura
- JavaScript - Istanbul
- Python - Coverage.py
在 PHP 搭配 PHPUnit 該如何產出 Cobertura XML 呢?
一、讓 PHPUnit 輸出 Coverage Cobertura XML 格式的報表
在 PHPUnit 9.5 版的手冊中,關於 coverage 的章節中,可以看到,目前手冊上顯示如果要輸出報表,總共支援了底下的六種格式:
- clover
- crap4j
- html
- php
- text
- xml
其中,並沒有提到 GitLab CI/CD 要使用的 Cobertura XML 格式,因此甚至有人寫了轉換工具soyhuce/phpunit-to-cobertura,但仔細探究 PHPUnit 的原始碼,搜尋「cobertura」後發現了一道曙光phpunit/Builder.php at sebastianbergmann/phpunit),在 phpunit 的指令中,支援了 coverage-cobertura
關鍵字。
於是實際驗證,在已經開啟 xdebug 的 PHP 環境中,執行:
1 | php vendor/bin/phpunit --coverage-cobertura=cobertura.xml |
真的順利產出 Cobertura XML 格式的報表,樣式如下:
1 |
|
這代表至少在 PHPUnit 9.x 的版本中,可以支援 --coverage-cobertura
來產出 Cobertura XML 格式報表。
二、如何在 phpunit.xml 中宣告要產出 Cobertura XML 格式的報表呢?
同樣的,在 PHPUnit 的官方手冊中,是沒辦法找到在 PHPUnit 設定檔中應該如何產出 Cobertura XML 格式報表的,但如同在第一章中驗證的方法,在 coverage 的 report 做了 cobertura 的宣告:
1 | <coverage processUncoveredFiles="true"> |
同樣產出了 Cobertura XML 格式報表,因此這在 phpunit.xml
或 phpunit.xml.dist
是可行的。
三、如何在 GitLab CI/CD 中整合,讓PHPUnit 產出 Cobertura XML 報表格式
在這次的範例,直接取用中上一篇在 Pipeline 檢視 PHPUnit 單元測試報告相同的原始碼,但由於 PHPUnit 要產出 Code Coverage 相關的資訊時,必須搭配 xdebug 使用,因此這邊改採 jorge07/alpine-php:8.0-dev
docker image 作為執行環境,同樣以 PHP 8.0 作為 PHP 的版本。
1. GitLab CI 執行環境
- PHP 8.0
- Docker Image jorge07/alpine-php:8.0-dev
- GitLab 13.12
- GitLab Runner 13.12
- 範例原始碼 GitLab CodeCoverage Report Demo
2. 在 GitLab 共用的模板
1 | .test_template: |
在底下的範例中,使用的模板都使用以上的共用安裝過程及共用的 docker image jorge07/alpine-php:8.0-dev
。值得一提的地方是,在 PHP 8.0 搭配 XDebug 3.0 後,在取得 Coverage 時,必須讓 XDebug 知道 XDEBUG_MODE
為 coverage
。
四、在 GitLab CI 中執行 PHPUnit 的 Coverage 檢查,並產出 Cobertura XML 格式報表
1. 在 PHPUnit Command Line 執行指令中設定 Cobertura XML Report 格式
如前面所提到的,在 Command Line 中要得到 Cobertura XML 格式的報表,必須在 PHPUnit 執行的指令中加上 --coverage-cobertura filePath
參數,在 .gitlab-ci.yml
中,根據 上一篇 的範例原始碼,script
的部分必須再增加 --coverage-cobertura
,增加後的 .gitlab-ci.yml 如下:
1 | test:phpunit-with-command-line: |
如上,再增加後,可以在對應的 Merge Request 馬上看到成果:
如上圖,在範例的 PHP 程式碼中,刻意的不測試 isFalse
這個方法,因此方法中的原始碼呈現 No test coverage。
2. 透過 phpunit.xml.dist
或 phpunit.xml
設定 Cobertura XML 格式 Coverage 報表
同樣的在第二段中,有提到如果要將 Cobertura XML 設定在 phpunit.xml
中,則 Coverage 的部分必須增加 report 並且增加 cobertura 的段落,範例如下:
1 | <coverage processUncoveredFiles="true"> |
這邊的 phpunit.xml 將 Cobertura 格式的檔案輸出到 build/report.cobertura.xml
這個檔案路徑。因此對應的 GitLab CI Pipeline 描述,也需要針對報表的路徑做調整,如下:
1 | test:phpunit-with-phpunit-file: |
3. 在 ParaTest 中產出 Cobertura XML 格式 Coverage 報表
在 PHP 語言中,為了讓 PHPUnit 可以執行的更快,開始有一些加強的方案,如很多人常用的平行化處理方案,透過多執行序來同時執行 PHP 的單元測試以加快完成速度,其中 ParaTest paratestphp/paratest: Parallel testing for PHPUnit 就是這中間很有名的一個工具。如上一篇提到 ParaTest 大部分的指令都可以與 PHPUnit 支援的相容,在經過測試後,發現 Coverage Report 產出 Cobertura XML 格式報表的部分,是相容的,因此幾乎不太需要更動。如下是在 ParaTest 的指令模式中產出 Cobertura XML 格式報表:
1 | test:paratest-with-phpunit-file: |
上面內容與上一篇一樣 mkdir -p build
是為了避免無法寫入檔案造成無法產出報表。其他的如 PHPUnit 產出 Cobertura XML 格式報表,僅加入了 artifacts:reports:cobertura
來取得 Cobertura XML 格式報表對應的檔案。
4. 接下來就是使用 Command Line 產出報表的範例:
1 | test:paratest-with-command-line: |
同上一個範例中,也同樣有 mkdir -p build
這段產出 build 資料夾的部分。其它的如 PHPUnit 在 Command Line 一樣,要產出 Cobertura XML 格式的報表必須要透過 --coverage-cobertura build/cobertura.xml
參數。
五、結論
在 GitLab CI 中使 PHP 的測試工作 PHPUnit 執行後產出 JUnit XML 格式的報表,主要倚靠 PHPUnit 自身的功能搭配 GitLab CI artifacts:reports:junit
機制來完成,而,如果需要更有效的看到視覺化的 Code Coverage 則可以透過 artifacts:reports:cobertura
,在 PHP 的環境中,透過小祕技產出 Cobertura XML 其實只是增加一兩段指令,不會太難,最難的部分反而是從 PHPUnit 原始法中找到 coverage-cobertura
這個宣告。
希望這篇文章,希望對大家有幫助。
六、參考連結
- 對應之範例 GitLab Repo GitLab PlayGround / Feature Demo / GitLab CodeCoverage Report Demo · GitLab
- 可查看視覺化 Code Coverage 效果的 Demo Cobertura Code Coverage Format (!1) · Merge requests · GitLab PlayGround / Feature Demo / GitLab CodeCoverage Report Demo · GitLab
- Test coverage visualization | GitLab
- GitLab CI - Cobertura coverage XML files
- PHPUnit 的手冊 The XML Configuration File
- paratestphp/paratest: Parallel testing for PHPUnit
当前网速较慢或者你使用的浏览器不支持博客特定功能,请尝试刷新或换用Chrome、Firefox等现代浏览器