wen aidev
Published on

現代軟體測試與 AI 實戰 (5):AI 輔助整合測試實戰,從 Markdown 到真實程式碼

上一篇文章中,我們成功讓 AI 扮演 QA 角色,從需求文件中產出了一份無死角的 Markdown 測試案例清單 (Test Cases)

但純文字終究只是理想,真正能把關品質的還是「實作出來的程式碼」。過去,要寫一支完整的整合測試(包含起 DB、建資料、發 Request、清除資料)非常痛苦且耗時。現在,我們將示範如何讓 Cursor / Claude Code 自動完成這最後的「落地」步驟。


理論落地:讓 AI 為你寫測試框架

從 Markdown 到真實程式碼流程

圖說:AI 結合你的 Codebase 與測試要求,瞬間產出可執行的自動化腳本。

前置需求:安裝 Docker

🐳 開始前先確認 Docker 已安裝

Testcontainers 底層依賴 Docker,請先安裝

Docker Desktop

(Windows / Mac)或 Docker Engine(Linux)。

安裝完成後,在終端機確認 Docker 正在運行:
docker ps

看到空的容器列表(不是 error)就代表 Docker 已就緒。

✅ 不需要自己 docker run 任何東西——Testcontainers 會幫你全自動處理。

準備強大的測試基礎設施

在我們請 AI 寫 Code 之前,我們必須先為專案引入正確的測試框架。為了避免第三篇文章提到的「環境迷思」(例如連錯 Staging DB 導致資料污染),我們強烈推薦使用 Testcontainers 技術。

什麼是 Testcontainers? 這是一個讓開發者可以在程式碼中直接用 Docker 啟動臨時資料庫 (如 PostgreSQL, Redis) 的函式庫。測試開始時啟動(乾淨的空資料庫),測試結束時容器就會自動被銷毀,絕不會有髒資料殘留。

依你的語言安裝對應套件:

# Node.js / TypeScript 專案
npm install --save-dev testcontainers @testcontainers/postgresql

# C# / .NET 專案
dotnet add package Testcontainers.PostgreSql

# Python 專案
pip install testcontainers[postgres]

步驟實戰:在 Cursor 中下達指令

打開 Cursor 的 Composer 功能列 (Ctrl + I 或 Cmd + I),選中我們在上一篇產出的 @test-cases.md 與你的核心業務邏輯檔案(例如 @LoginController.cs@login.ts),然後給出以下 Prompt:

🚀 整合測試實作提示詞模板

我需要為登入 API 撰寫整合測試。
請閱讀 @test-cases.md 中的所有情境,並參考 @LoginController 的實作邏輯。

請幫我產出測試檔案,並遵循以下規範:

1. 請使用 (xUnit / Jest / pytest,依你的專案填寫)。
2. 必須使用 Testcontainers 啟動一個全新的 PostgreSQL 實例,作為測試環境資料庫。
3. 每個測試執行前 (Setup),請插入必要的假資料 (Seed Data);執行後 (Teardown) 確保資源獨立。
4. 測試命名請使用「方法名*測試情境*預期結果」的格式。

請直接實作所有 Happy Path 與 Negative Cases 的程式碼。

AI 實際生成的程式碼長什麼樣

不到 30 秒,Cursor 會一口氣幫你生成完整的測試檔。以下是 Node.js + PostgreSQL 的典型輸出結果(你的 AI 也會產出類似的程式碼):

// login.integration.test.ts
// 由 Cursor 根據 test-cases.md + LoginService.ts 自動生成

import {
  PostgreSqlContainer,
  StartedPostgreSqlContainer,
} from '@testcontainers/postgresql';
import { Client } from 'pg';
import { loginUser } from '../services/LoginService';

let container: StartedPostgreSqlContainer;
let dbClient: Client;

// Setup:測試開始前自動啟動一個全新 PostgreSQL 容器
beforeAll(async () => {
  container = await new PostgreSqlContainer('postgres:15-alpine').start();

  dbClient = new Client({ connectionString: container.getConnectionUri() });
  await dbClient.connect();

  // 建立 schema 與 Seed Data
  await dbClient.query(`
    CREATE TABLE users (
      id SERIAL PRIMARY KEY,
      email TEXT UNIQUE NOT NULL,
      password_hash TEXT NOT NULL,
      failed_attempts INT DEFAULT 0,
      locked_at TIMESTAMPTZ
    )
  `);
  await dbClient.query(`
    INSERT INTO users (email, password_hash)
    VALUES ('test@example.com', '$2b$10$hashedpassword')
  `);
}, 60000); // 等待 Docker pull,給 60 秒

// Teardown:測試結束後銷毀容器,完全不留髒資料
afterAll(async () => {
  await dbClient.end();
  await container.stop();
});

// Happy Path
test('Login_ValidCredentials_ReturnsJwtToken', async () => {
  const result = await loginUser(
    'test@example.com',
    'correctPassword',
    dbClient,
  );
  expect(result.token).toBeDefined();
  expect(result.status).toBe(200);
});

// Negative Case:失敗 5 次鎖定(AI 自動用迴圈寫好)
test('Login_FailFiveTimes_AccountIsLocked', async () => {
  for (let i = 0; i < 5; i++) {
    await loginUser('test@example.com', 'wrongPassword', dbClient);
  }
  const result = await loginUser('test@example.com', 'wrongPassword', dbClient);
  expect(result.status).toBe(423); // 423 Locked
  expect(result.message).toContain('帳號已鎖定');
});

這段程式碼涵蓋了:

  • ✅ Docker 容器的自動啟動與銷毀(beforeAll / afterAll
  • ✅ Schema 建立 + Seed Data 注入
  • ✅ Happy Path 與 Negative Case 的完整驗證
  • ✅ 不依賴任何外部 Staging 環境,在任何機器上都能執行

你唯一的任務,就是確認套件已安裝(上面的 npm install 步驟),然後按下 npm test,享受滿滿的綠燈。


品質的保證:從開發到部署

透過這兩篇文章的結合,我們已經打通了「從需求 → 測試案例 → 整合測試代碼」的自動化流程。這正是現代軟體工業中 「測試左移」與「AI 賦能」 的最佳拍檔。

你的開發者不再需要花幾個小時去寫繁瑣的 Setup 程式碼,你的 QA 也可以專注於更抽象層次的探索測試。

然而,AI 的野心不僅於此。在系列文章的最終回,我們將進入最高階的應用:Agentic Testing 的閉環。如果 AI 連「自動開啟瀏覽器操作、錄影、遇錯自我修復並發 Issue」都能做到呢?

前往本系列的最終壓軸:Agentic Testing 的閉環:AI 自動執行驗收測試與除錯

支持作者 ☕

台灣用戶:

透過 LINE Pay 支持

國際用戶:

透過 Ko-fi 支持

留言討論