本章介紹軟體測試的工程實踐,包括測試環境管理、測試資料管理、持續測試整合,以及測試報告與度量。

測試計劃#

測試計劃的重要性在敏捷開發模式下依然存在,只是從一次性集中制定變成了以迭代的方式持續制定。

測試計劃的五大要素#

要素核心問題內容
測試範圍測什麼?不測什麼?明確測試邊界
測試策略先測什麼?如何測?測試優先級和方法
測試資源誰來測?在哪測?人員和環境
測試進度何時開始?何時完成?時間表和里程碑
風險預估可能出什麼問題?風險識別和應對

測試策略制定#

測試策略考慮因素:
├── 測試類型選擇
│   ├── 功能測試 ─── 核心業務流程優先
│   ├── 效能測試 ─── 關鍵效能指標
│   ├── 安全測試 ─── 高風險功能
│   └── 兼容性測試 ─── 目標用戶設備
├── 自動化策略
│   ├── 哪些適合自動化
│   ├── 框架選型
│   └── 投入產出比
└── 回歸策略
    └── 20% 精力覆蓋 80% 核心場景

測試環境管理#

環境類型#

環境用途資料
開發環境開發自測開發資料
測試環境功能測試測試資料
預發布環境上線前驗證脫敏生產資料
生產環境真實用戶使用真實資料

環境管理挑戰#

常見問題及解決方案:
├── 環境不一致 ─────────→ 容器化、基礎設施即程式碼
├── 環境爭用 ─────────────→ 環境隔離、動態創建
├── 組態管理混亂 ─────────→ 組態中心、版本控制
└── 資料同步困難 ─────────→ 資料管理平台

容器化測試環境#

# Docker Compose 測試環境示例
version: "3"
services:
  app:
    build: .
    ports:
      - "8080:8080"
    depends_on:
      - db
      - redis
    environment:
      - SPRING_PROFILES_ACTIVE=test

  db:
    image: mysql:8.0
    environment:
      - MYSQL_ROOT_PASSWORD=test
      - MYSQL_DATABASE=testdb

  redis:
    image: redis:6

基礎設施即程式碼:使用 Docker、Kubernetes 等工具將測試環境組態程式碼化,確保環境的一致性和可重複性。

測試資料管理#

資料準備策略#

策略說明適用場景
On-the-fly測試時實時創建一次性資料(訂單、優惠券)
Out-of-box預先準備好穩定資料(商品類目、品牌)
混合方式結合兩種方式實際項目中最常用

資料創建技術#

資料創建方式:
├── API 呼叫
│   ├── 優點:資料準確性高
│   └── 缺點:不是所有資料都有 API
├── 資料庫操作
│   ├── 優點:效率高、靈活
│   └── 缺點:需要維護 SQL 與程式碼同步
└── 綜合方式
    └── API 創建基礎資料,SQL 修改特定狀態

測試資料工具設計#

// 測試資料工具示例
public class TestDataFactory {

    // 創建測試用戶
    public User createUser() {
        return createUser(UserType.NORMAL);
    }

    public User createUser(UserType type) {
        User user = apiClient.createUser(generateUserData());
        if (type == UserType.VIP) {
            // 通過 SQL 修改用戶類型
            jdbcTemplate.update(
                "UPDATE users SET type = 'VIP' WHERE id = ?",
                user.getId()
            );
        }
        return user;
    }

    // 創建測試訂單
    public Order createOrder(User buyer, Product product) {
        return apiClient.createOrder(
            buyer.getId(),
            product.getId()
        );
    }
}

資料隔離原則#

測試資料污染是自動化測試不穩定的主要原因之一。每個測試用例應該創建自己的資料,或使用唯一標識區分。

資料隔離策略:
├── 唯一標識 ─── 測試資料帶唯一前綴/後綴
├── 事務回滾 ─── 測試結束後回滾資料變更
├── 獨立資料集 ─── 每個測試用例使用獨立資料
└── 清理策略 ─── 測試後自動清理測試資料

持續測試(CI/CD 整合)#

測試金字塔在 CI/CD 中的應用#

┌─────────────────────────────────────────────────────────┐
│                    CI/CD 測試流水線                      │
│                                                         │
│  ┌─────────────────────────────────────────────────┐   │
│  │ 程式碼提交                                         │   │
│  └────────────────────┬────────────────────────────┘   │
│                       ↓                                 │
│  ┌─────────────────────────────────────────────────┐   │
│  │ 單元測試 (秒級)                                  │   │
│  │ - 每次提交都執行                                 │   │
│  │ - 阻斷部署條件:失敗                             │   │
│  └────────────────────┬────────────────────────────┘   │
│                       ↓                                 │
│  ┌─────────────────────────────────────────────────┐   │
│  │ 整合測試 (分鐘級)                                │   │
│  │ - 每次提交或合併請求執行                         │   │
│  │ - 阻斷部署條件:失敗                             │   │
│  └────────────────────┬────────────────────────────┘   │
│                       ↓                                 │
│  ┌─────────────────────────────────────────────────┐   │
│  │ E2E 測試 (10-30 分鐘)                           │   │
│  │ - 部署到測試環境後執行                           │   │
│  │ - 阻斷部署條件:關鍵用例失敗                     │   │
│  └────────────────────┬────────────────────────────┘   │
│                       ↓                                 │
│  ┌─────────────────────────────────────────────────┐   │
│  │ 效能/安全測試 (定時或手動觸發)                   │   │
│  └─────────────────────────────────────────────────┘   │
└─────────────────────────────────────────────────────────┘

Jenkins Pipeline 示例#

pipeline {
    agent any

    stages {
        stage('Build') {
            steps {
                sh 'mvn clean compile'
            }
        }

        stage('Unit Tests') {
            steps {
                sh 'mvn test'
            }
            post {
                always {
                    junit 'target/surefire-reports/*.xml'
                    jacoco(execPattern: '**/target/jacoco.exec')
                }
            }
        }

        stage('Integration Tests') {
            steps {
                sh 'mvn verify -P integration-test'
            }
        }

        stage('Deploy to Test') {
            steps {
                sh 'deploy-to-test.sh'
            }
        }

        stage('E2E Tests') {
            steps {
                sh 'mvn verify -P e2e-test'
            }
            post {
                always {
                    publishHTML([
                        reportDir: 'target/e2e-reports',
                        reportFiles: 'index.html',
                        reportName: 'E2E Test Report'
                    ])
                }
            }
        }
    }

    post {
        failure {
            slackSend channel: '#dev-alerts',
                      message: "Build Failed: ${env.JOB_NAME} ${env.BUILD_NUMBER}"
        }
    }
}

測試失敗處理策略#

策略說明適用場景
快速失敗發現失敗立即停止單元測試
繼續執行記錄失敗,繼續其他測試整合測試、E2E 測試
重試機制失敗後自動重試不穩定的 E2E 測試
智能跳過根據程式碼變更選擇性執行大型測試套件

測試報告與度量#

關鍵測試指標#

測試度量指標:
├── 測試覆蓋率
│   ├── 需求覆蓋率
│   └── 程式碼覆蓋率(行/分支/條件)
├── 測試效率
│   ├── 用例執行時間
│   ├── 缺陷發現率
│   └── 缺陷逃逸率
├── 測試品質
│   ├── 用例通過率
│   ├── 缺陷重開率
│   └── 自動化穩定性
└── 測試進度
    ├── 用例完成率
    └── 缺陷趨勢

缺陷報告要素#

要素說明
標題在什麼情況下發生了什麼問題
概述缺陷本質的概括性描述
影響對用戶或業務的影響
環境復現所需的環境資訊
前置條件開始復現前的系統狀態
復現步驟可操作的、連貫的步驟
期望/實際結果應該發生什麼 vs 實際發生什麼
優先級/嚴重程度修復的緊急程度和影響程度

好的缺陷報告不是大量資訊的堆疊,而是以高效的方式提供準確有用的資訊。

測試報告自動化#

自動化測試報告生成:
├── JUnit/TestNG XML 報告
├── JaCoCo 覆蓋率報告
├── Allure 富報告
│   ├── 測試用例詳情
│   ├── 歷史趨勢
│   ├── 附件(截圖、日誌)
│   └── 缺陷關聯
└── 自定義 Dashboard
    └── Grafana + InfluxDB/Prometheus

測試團隊協作#

測試工程師的角色#

測試工程師是項目的「潤滑劑」:
├── 對接產品經理 ─── 確保需求正確實現
├── 對接開發人員 ─── 確保缺陷及時修復
├── 對接運維人員 ─── 確保環境穩定
└── 對接用戶 ─────── 確保用戶體驗

敏捷測試實踐#

實踐說明
測試左移測試人員早期介入需求分析
持續測試自動化測試融入 CI/CD
探索性測試邊測試邊學習,發現未知問題
結對測試開發和測試結對工作
BDD行為驅動開發,用自然語言描述測試

BDD 示例(Cucumber)#

# login.feature
Feature: 用戶登錄
  作為一個註冊用戶
  我希望能夠登錄系統
  以便使用系統功能

  Scenario: 正確的用戶名和密碼登錄成功
    Given 我已經是一個註冊用戶
    And 我的用戶名是 "testuser"
    And 我的密碼是 "password123"
    When 我在登錄頁面輸入用戶名和密碼
    And 我點擊登錄按鈕
    Then 我應該看到首頁
    And 我應該看到歡迎資訊 "Hello, testuser"

  Scenario: 錯誤的密碼登錄失敗
    Given 我已經是一個註冊用戶
    And 我的用戶名是 "testuser"
    When 我輸入錯誤的密碼 "wrongpassword"
    And 我點擊登錄按鈕
    Then 我應該看到錯誤資訊 "用戶名或密碼錯誤"

測試能力成熟度#

測試能力成熟度等級:
├── Level 1: 初始級
│   └── 測試是無序的、隨機的
├── Level 2: 可重複級
│   └── 有基本的測試流程,可重複執行
├── Level 3: 已定義級
│   └── 測試流程標準化,有專門的測試團隊
├── Level 4: 量化管理級
│   └── 測試過程可度量,有明確的質量指標
└── Level 5: 持續最佳化級
    └── 持續改進測試過程,追求卓越

測試不是終點,而是持續改進的過程。保持學習心態,關注測試技術的發展,不斷提升測試能力。