「commit message 寫的是加了什麼功能,那測試就一定是為了驗證那個功能新寫的,不是嗎?」
大部分時候是這樣沒錯。但 omnipay-ecpay 裡有一筆 commit,攤開 diff 一看,commit message 講的範圍,比程式碼實際變更的範圍還大。今天先不下結論,只是把這筆 commit 完整攤開來看。
80d3469 的完整 diff,分清楚哪些是真正新增的程式碼,哪些是新增的測試commit 80d3469,2025-11-29,訊息是這樣寫的:
Add BNPL payment support and tests for ATM, BNPL, FlexibleInstallment
- Add getBNPLFields() method for BNPL (無卡分期) payment type
- Add test cases for ATM, BNPL, and FlexibleInstallment (30N) payments
翻成白話:「新增 BNPL 付款支援,並且補了 ATM、BNPL、彈性分期(FlexibleInstallment)三種情境的測試。」
git show --stat 顯示這筆 commit 只動了兩個檔案:
src/Message/PurchaseRequest.php | 15 ++++
tests/Message/PurchaseRequestTest.php | 139 ++++++++++++++++++++++++++++++++++
2 files changed, 154 insertions(+)
src/Message/PurchaseRequest.php 這 15 行新增的內容,只有一個新方法:
/**
* BNPL 無卡分期(裕富/中租).
*
* @param string $choosePayment
* @return array
*/
private function getBNPLFields($choosePayment)
{
return in_array($choosePayment, ['ALL', 'BNPL'], true) ? [
'PaymentInfoURL' => $this->getPaymentInfoURL(),
'ClientRedirectURL' => $this->getClientRedirectURL(),
] : [];
}
再加上把這個方法接進原本的 getSendExtend() 組裝流程裡(一行 $this->getBNPLFields($sendFields['ChoosePayment']))。就這樣,程式碼變更的範圍只涵蓋 BNPL 這一種付款方式。
tests/Message/PurchaseRequestTest.php 新增了 139 行,仔細看方法名稱:
public function testATMGetData() { /* ... */ }
public function testBNPLGetData() { /* ... */ }
public function testFlexibleInstallmentGetData() { /* ... */ }
三個新測試方法,涵蓋 ATM、BNPL、彈性分期三種付款情境。
程式碼變更只碰了 BNPL;測試變更卻涵蓋 ATM、BNPL、彈性分期三種。回頭去翻 src/Traits/HasATMFields.php 跟 PurchaseRequest.php 裡處理彈性分期(CreditInstallment)的邏輯,這些程式碼不是這次新增的——getATMFields() 這個方法、CreditInstallment 相關的欄位設定,在這次 commit 之前就已經存在於程式碼裡了。
也就是說:這次 commit 真正新增的功能只有 BNPL 一種,但新增的測試涵蓋了三種——其中兩種(ATM、彈性分期)是「早就能用、但一直沒被測過」的既有功能,這次才第一次補上測試。
commit message 講的是「加了什麼」,diff 才告訴你「實際發生了什麼」——這兩者不一定是同一件事,尤其是牽涉到測試的時候。
❌ 只看 commit message 得到的理解
"這筆 commit 加了 BNPL 功能,順便補了 ATM 跟彈性分期的測試"
→ 聽起來像是三個功能都是新的,測試只是「隨手」順便寫
✅ 對照 diff 之後得到的理解
"這筆 commit 只新增了 BNPL 一種付款方式的程式碼;
ATM 跟彈性分期的程式碼其實已經存在一段時間,
這次才第一次被寫測試覆蓋到"
→ 這代表套件裡曾經有兩條「能動但沒測過」的路徑,
直到某次改動才被順路補上
你有沒有讀過一筆 commit message,後來發現實際 diff 講的故事跟 message 不完全一樣?你當時是怎麼發現的——自己去翻 diff,還是不小心踩到 bug 才回頭查?
80d3469 的訊息涵蓋 BNPL/ATM/彈性分期三種情境的測試,但程式碼變更只涉及 BNPL 一種明天拆解這個現象背後的兩種節奏:「新功能配新測試」跟「順路把舊功能的測試補上」,這兩種節奏在真實開發裡是怎麼交織在一起的,為什麼後者反而更貼近現場。