「把所有的自動化測試案例一股腦全塞在 Pull Request 階段,就像是在高速路口設了一個單線道收費站——除了造成『PR 大塞車』和開發者的抱怨外,完全無法帶來高效的品質回饋。」
大家好,我是 Jane,一個每天在第一線處理跨平台(Web & App)自動化測試、跟 CI/CD Pipeline 與發版流程奮戰的自動化測試工程師(SDET)。
恭喜大家跟著我完成了第四部分關於測試資料、環境與 API 整合的討論!
從今天開始,我們要邁入將測試發揮最大價值的關鍵階段:《第五部分:讓測試真正進入 CI/CD》。
許多團隊在剛完成自動化測試框架時,最常犯的錯誤就是:
結果可想而知:開發工程師發了一個 PR,要等 45 分鐘才能知道能不能 Merge;遇到一次 Flaky 失敗,再重跑又耗掉 45 分鐘。久而久之,開發團隊開始抱怨「自動化測試拖慢開發節奏」,甚至要求 CI pipeline 允許 skip-tests。
今天這篇文章,我們就來好好聊聊:自動化測試在 CI/CD Pipeline 裡到底應該放在哪裡?如何根據『執行速度』與『風險層級』建構分層的 CI/CD 測試階段!
一個成熟的 CI/CD Pipeline,應該依照「回饋速度由快到慢、測試覆蓋由廣到精」原則,將測試分散在 5 個 key pipeline 階段:
┌────────────────────────────────────────────────────────────────┐
│ CI/CD Pipeline 5 大測試階段 │
├────────────────────────────────────────────────────────────────┤
│ 1. Commit / PR 階段 ──▶ Lint, Unit & Core API (5分鐘內) │
│ 2. Build / Post-Merge 階段──▶ Full API & Component (15分鐘內) │
│ 3. Nightly / Daily 階段 ──▶ Full UI / App E2E & Flaky (1小時)│
│ 4. Deployment / Staging ──▶ Smoke Test 冒煙測試 (5分鐘內) │
│ 5. Production 階段 ──▶ Post-deploy Health Check (1分鐘) │
└────────────────────────────────────────────────────────────────┘
main 或 develop 分支後,確保整體模組整合無誤。如何在同一個 pytest 專案中,精準指定不同的 CI 管道只跑對應層級的測試?答案就是利用 pytest Markers!
pytest.ini 中註冊測試層級標籤Ini, TOML
# pytest.ini
[pytest]
markers =
smoke: 冒煙測試,用於 Deploy 後快速驗證 (極速)
pr: 用於 PR / Commit 門檻的核心 API 與單元測試 (5分鐘內)
regression: 全套迴歸測試,用於 Nightly 或 Release 階段
ui: Web / App UI 自動化測試 (昂貴)
Python
# tests/api/test_auth_api.py
import pytest
@pytest.mark.pr
@pytest.mark.smoke
def test_login_api_success(api_client):
"""此案例既屬於 PR 門檻,也屬於 Deploy 後的 Smoke Test"""
response = api_client.login("admin", "password123")
assert response.status_code == 200
# tests/ui/test_checkout_ui.py
@pytest.mark.regression
@pytest.mark.ui
def test_full_checkout_flow_ui(page):
"""UI 全流程案例,僅在 Nightly Regression 階段執行"""
page.goto("https://staging.example.com/checkout")
...
.github/workflows/ci.yml)這是一份高效的 GitHub Actions 工作流程配置範例:
YAML
name: Automation Testing Pipeline
on:
pull_request:
branches: [ main, develop ]
schedule:
- cron: '0 18 * * *' # 每天深夜 02:00 (UTC+8) 跑 Nightly
jobs:
# 階段 1: PR 門檻檢查 (速戰速決)
pr-validation:
if: github.event_name == 'pull_request'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: '3.11'
- name: Install dependencies
run: |
pip install -r requirements.txt - name: Run PR Fast Tests (Only @pytest.mark.pr)
run: |
# 僅執行帶有 pr 標籤的高速 API/邏輯測試
pytest -m "pr" --junitxml=reports/pr_report.xml
# 階段 2: 深夜全套 Nightly Regression (包含昂貴的 UI 測試)
nightly-regression:
if: github.event_name == 'schedule'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up Python & Playwright
run: |
pip install -r requirements.txt
playwright install --with-deps chromium - name: Run Full Regression (API + UI)
run: |
# 深夜執行包含 regression 與 ui 的全套測試
pytest -m "regression or ui" --html=reports/nightly_report.html
@pytest.mark.pr?還是某個 API 測試沒有 Mock 外部服務?保護開發者的 PR 回饋速度,是 SDET 獲得團隊信任的基石。
建立了 CI/CD 測試階段後,另一個實務問題接踵而至:
「隨著案例累積到 500 條,就算分了階段,Nightly 跑一次還是要 3 個小時。我們該如何分類測試標籤?如何做到只跑受這次 Code 修改影響的測試範圍(Test Impact Analysis)?」
明天 Day 22,我們將深入探討:《 Day 22|不是所有測試都該每次全部執行:測試標籤分類與受影響範圍抽離 》。