很多開發者都會說:「放心啦,我有寫測試。」
這句話聽起來很安心,但事實常常是——測試可能只跑過最表面的幾條路徑,剩下大半程式碼根本沒被觸碰。
就像消防演習,你以為所有出口都有人疏散過,結果火真燒起來才發現:某些門從來沒開過。
所以問題不是「有沒有測試」,而是「測試到底涵蓋了多少」。
這就是 pytest-cov 的價值所在:它不只是幫你跑測試,而是揭穿那句幻覺,讓數字說話。
定義:在所有程式碼裡,有多少比例實際被測試執行過。
常見的兩個指標:
行覆蓋率 (Line Coverage):哪些程式碼行被跑過。
分支覆蓋率 (Branch Coverage):if/else、迴圈等條件路徑是否都測到。
高覆蓋率 ≠ 沒 bug,但能幫你抓出「完全沒測」的死角。
就像巡邏,重點不是跑了幾次同一條路,而是 沒人走過的角落要被點亮。
pip install pytest-cov
pytest --cov=app --cov-report=term-missing
---------- coverage: platform linux, python 3.11 ----------
Name Stmts Miss Cover
----------------------------------------
app.py 20 2 90%
tests/test_worldline.py 15 0 100%
----------------------------------------
TOTAL 35 2 94%
app.py 有 20 行,2 行沒被測到。
tests/test_worldline.py 全部覆蓋。
總覆蓋率為 94%。
這比單純「測試通過」更誠實:它告訴你哪裡被忽略。
Q:是不是要追求 100% 覆蓋率?
A:不是。100% 只保證程式碼被「跑過」,不代表測試有驗證邏輯正確性。那應該怎麼設定標準?
最常見的做法是設 下限門檻,例如 80%。低於 80% → pipeline fail,避免「幾乎沒測試的程式碼」被合併。
高於 80% → 繼續追求更好的測試品質,但不必盲目追 100%。
- name: Run tests with coverage
run: |
pytest --cov=app --cov-report=xml --cov-report=term
這會生成 coverage.xml,能進一步整合到報告工具,例如:
- name: Upload coverage to Codecov
uses: codecov/codecov-action@v4
with:
file: ./coverage.xml
沒覆蓋的程式碼 = 未知風險區域
覆蓋率下限 = 最低安全保證
測試不是演習。
真正的風險,常常藏在那些你「以為測過、其實完全沒跑過」的區域。
寫測試有點像說「我每天都有運動」。
嘴上說得輕鬆,但戴上手環一量,可能只走了 2,000 步。
pytest-cov 讓你看見測試覆蓋率,不再只是「我有寫測試」的幻覺。它會很誠實地告訴你:
「這裡你根本沒動過。」
本地檢查能幫你發現死角,CI/CD 整合能讓團隊持續監控品質。
設定合理的覆蓋率下限,才能把這變成 pipeline 的一道守門規則。
我們把「測試」這件事從主觀的安心,變成客觀的數字。
只有數字能證明,你的系統真的被檢查過。
測試通過很美好,但覆蓋率數字是殘酷的。
不過殘酷也好,因為至少你知道該從哪裡開始補強。