iT邦幫忙

2026 iThome 鐵人賽

DAY 7
0
IT Operation

AI 輔助開發下,測試如何保住品質防線系列 第 7

Day 07:覆蓋率報表設定得很齊全,卻沒人在看

  • 分享至 

  • xImage
  •  

前言:覆蓋率報表設定好了,為什麼還要關掉?

「既然都設定好覆蓋率報表了,為什麼 CI 上還要特地加一個參數把它關掉?」

這是這個套件最反直覺的地方:phpunit.xml 裡對覆蓋率報表的設定寫得很完整,但 CI 執行測試時,卻用一個參數把它整個關掉。今天就把這個矛盾拆開來看。

今日目標

  • 看懂 phpunit.xml 裡覆蓋率報表的設定內容
  • 確認 CI 實際執行測試的指令,以及它做了什麼
  • 理解「覆蓋率設定存在」跟「覆蓋率有沒有人在看」是兩回事
  • 知道覆蓋率工具本身要跑起來,其實不是零成本的事

phpunit.xml 裡寫的覆蓋率設定

<coverage>
    <include>
        <directory suffix=".php">src</directory>
    </include>
    <report>
        <clover outputFile="build/logs/clover.xml"/>
        <html outputDirectory="build/coverage"/>
        <text outputFile="build/coverage.txt"/>
    </report>
</coverage>

這段設定告訴 PHPUnit:只計算 src/ 目錄的覆蓋率(測試檔案自己不算),輸出三種格式的報表——clover(給 CI 平台如 Codecov、Scrutinizer 讀的機器格式)、HTML(人可以點開來看每一行有沒有被測到)、純文字(快速在終端機看摘要)。

看起來像是一套認真規劃過的覆蓋率追蹤機制。

CI 實際執行的指令,把它整個關掉

.github/workflows/tests.yml 裡真正執行測試的那一步是:

- name: Execute tests
  run: vendor/bin/phpunit --testdox --no-coverage

--no-coverage 這個參數告訴 PHPUnit:這次執行不要收集覆蓋率資料,不管 phpunit.xml 裡設定了什麼報表格式,這次都不會產生。也就是說,phpunit.xml 裡那段設定,目前只有在本機手動下指令、而且沒加 --no-coverage 時才會真的發生作用;在 CI 這個「理論上應該持續追蹤品質趨勢」的地方,它其實從未被執行過。

為什麼會這樣:一個合理的推測,加上一個實測發現

這個套件的維護紀錄裡沒有明講「為什麼 CI 用 --no-coverage」,只能推測。但有一件事是可以實際驗證的:要讓覆蓋率報表真的跑起來,本身就有額外的技術門檻

我在一份本機的暫存複本上實際測試過:直接執行 vendor/bin/phpunit --coverage-text,PHPUnit 給出的結果是:

There was 1 PHPUnit test runner warning:

1) No code coverage driver available

OK, but there were issues!

意思是本機的 PHP 環境沒有裝 pcov 或 Xdebug 這類覆蓋率驅動,PHPUnit 根本無法產生覆蓋率數字。我接著嘗試用 pecl install pcov 補裝,結果編譯過程中因為系統缺少 pcre2.h 這個底層依賴而失敗。

這不是在說這個套件的維護者當初就是因為裝不起來才放棄——我沒有證據能證明這是真正的原因,這只是我自己在另一個環境上重現時撞到的真實狀況。但它足以說明一件事:「幫 CI 開啟覆蓋率」不是加一個參數就結束,背後牽涉到「CI 執行環境有沒有裝對覆蓋率驅動」這個常常被低估的前置成本。這也是一個合理的推測:對很多專案來說,--no-coverage 是圖方便的選擇,不一定是「不重視覆蓋率」,可能只是「權衡之下,先讓測試能穩定跑過比較重要」。

❌ vs ✅:覆蓋率設定「存在」跟「有效」的差別

❌ 看起來有覆蓋率把關,實際上沒有
# phpunit.xml 設定了完整的 coverage 報表
# CI 卻執行:
run: vendor/bin/phpunit --testdox --no-coverage
# 結果:沒有人知道現在的覆蓋率是多少,PR review 時也看不到覆蓋率變化
✅ 覆蓋率設定跟 CI 執行方式一致
# CI 安裝好 pcov 之後執行:
run: |
  vendor/bin/phpunit --coverage-clover build/logs/clover.xml
# 額外接一步上傳到 Codecov 或在 PR 留言顯示覆蓋率變化

正例不是這篇文章的重點在教你怎麼設定 CI(那部分等第四部動手做的時候再細講),這裡想強調的是:光是把 <coverage> 區塊寫進 phpunit.xml,不會讓覆蓋率自動被守住——它只是定義了「如果有人去跑,會產生什麼格式的報表」,真正決定「這次測試有沒有被拿來檢查覆蓋率」的,是執行指令裡有沒有那個 --no-coverage

這件事留給後面的伏筆

覆蓋率報表這個問題,這個系列後面還會回來處理兩次:

  • 第二部會看到,即使沒有覆蓋率門檻擋著,某些程式碼路徑還是靠開發者自己覺得「這裡該補測試了」被補上——覆蓋率數字不是唯一能推動補測試的力量,但它至少能讓「哪裡沒被測到」這件事變得可見,而不是要等出事才發現
  • 第四部會實際動手,在一個環境裡把覆蓋率驅動裝起來、跑出真正的百分比數字,看看現在的覆蓋率到底是多少,而不是像今天這樣,先卡在「連驅動都裝不起來」這一步

今日思考題

你的專案 CI 裡有沒有類似的落差——設定檔裡寫了一套機制,但實際執行指令卻加了參數把它繞過去?你知道加那個參數的原因是什麼,還是也只是「一直都這樣」?

今日重點回顧

  • phpunit.xml 定義了完整的覆蓋率報表輸出格式,但只在沒加 --no-coverage 時才會真正產生
  • CI 目前執行測試時用 --no-coverage,覆蓋率報表從未在 CI 上真的被產出過
  • 覆蓋率驅動(pcov/Xdebug)本身要正確裝起來,在某些環境下不是零成本的事,這是一個實測驗證過的真實阻礙,不代表就是這個套件當初關掉覆蓋率的真正原因
  • 「覆蓋率設定存在」不等於「覆蓋率真的被拿來把關」,兩者要分開看

明日預告

第一部到這裡告一段落。明天進入第二部,會拆開一筆真實的 commit(80d3469),看看在沒有覆蓋率門檻推著走的情況下,測試實際上是怎麼被補上的。


上一篇
Day 06:不用 Mockery,這個套件怎麼假裝自己打過綠界 API
下一篇
Day 08:一筆 commit,兩種說法
系列文
AI 輔助開發下,測試如何保住品質防線10
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言