現在看到的內容是第二版,與之前所發佈的第一版內容有極大的差異。
主要是第一版的內容過於空泛和不切實際,無法真的拿來應用在實際的專案中。
所以我重新整理了內容,並且加入了更多實際可操作的指令範本和步驟。
現在 GitHub Copilot 已經成為許多開發者不可或缺的 AI 助手,但你是否發現在測試開發上,它產生的程式碼品質參差不齊?有時候格式不統一、命名不規範,甚至測試邏輯有問題?
或者是看到很多其他公司團隊會透過 Github Copilot 或其他 AI 工具來達到自動產出測試程式碼,開發團隊也躍躍欲試,但是團隊從來沒有在開發流程導入過單元測試的經驗,面臨到不知道應該怎麼讓 AI 工具幫忙產出符合團隊標準的測試程式碼。
以往我在帶新人學習單元測試的時候,並不會讓新人直接去對著他們的練習專案寫測試,而是會先讓他們把練習專案的程式碼調整為可測試的程式碼,然後再帶著他們整理出程式碼的 使用案例
,藉此瞭解他們自己程式的 業務邏輯
是什麼。
因為很多人不知道該怎麼寫單元測試的第一個難題就是程式碼不可測,接著第二個難題就是不知道怎麼把自己所寫的程式碼整理出使用案例。雖然聽起來很荒謬,但這是在很多開發人員身上都會有的狀況,因為他們可以知道程式邏輯會怎麼執行,但是卻無法整理出清楚的業務邏輯和使用案例。
所以整理出清楚的業務邏輯和使用案例之後,才會知道有多少的情境是需要測試的,然後就可以開始著手進行單元測試的練習與撰寫。經過多次的來回練習與實作後,新人們就會知道如何對自己所寫的程式碼進行測試的撰寫。
而現在是變成要讓 Github Copilot 協助我們一同來完成這樣的過程:分析業務邏輯 → 設計測試情境 → 產生測試程式碼。雖然我這邊提供的指令和設定不一定適合你的專案,但至少可以給你一個參考方向,讓你可以整理出一套能夠適合開發團隊的做法與流程。
問題場景:
解決方案:
我們用三個不同複雜度的範例來實驗這套方法:
DiscountCalculator
折扣計算服務UserService
使用者服務OrderProcessor
訂單處理流程在開始學習 GitHub Copilot 測試技巧之前,需要先完成環境準備工作。
由於本教學使用 xUnit.v3 作為測試框架,建議先安裝官方的專案範本,方便後續建立新的測試專案:
dotnet new install xunit.v3.templates
安裝成功後的輸出範例:
將安裝下列範本套件:
xunit.v3.templates
xunit.v3.templates (版本 3.0.1) 已安裝,將會以 最新版本 取代。
xunit.v3.templates::3.0.1 已成功解除安裝。
成功: xunit.v3.templates::3.0.1 已安裝下列範本:
範本名稱 簡短名稱 語言 標記
------------------------------ ---------------- ---------- ----------
xUnit.net v3 Extension Project xunit3-extension [C#],F#,VB Test/xUnit
xUnit.net v3 Test Project xunit3 [C#],F#,VB Test/xUnit
範本用途說明:
使用範例:
# 建立新的 xUnit.v3 測試專案
dotnet new xunit3 -n MyProject.Tests
完成範本安裝後,下載完整的範例專案:
# 複製專案
git clone https://github.com/kevintsengtw/30Days_in_Testing_Samples.git
# 進入 Day27 範例專案
cd 30Days_in_Testing_Samples/day27
# 建置專案
dotnet build Day27.Samples.sln
專案結構說明:
範例專案包含完整的專案結構和業務邏輯類別,但測試專案是空的,需要透過學習過程中的指令範本來建立測試程式碼。
測試環境說明:這篇文章的範例是基於 Claude Sonnet 4 模型測試的結果。你在實際操作時可能會遇到:
使用建議:
首先,我們需要建立專案的 GitHub Copilot 指導設定檔。這是整個技巧的核心 - 讓 GitHub Copilot 了解我們的專案規範。
開啟 .github/copilot-instructions.md
,你會看到以下內容:
# GitHub Copilot 測試開發指導
## 開發環境資訊
- .NET 9
- 測試框架:xUnit.v3 (3.0.1)
- NuGet Packages 安裝:
- xunit.v3
- xunit.runner.visualstudio
- 斷言庫:AwesomeAssertions (不使用 FluentAssertions)
## 測試檔案組織結構
- 測試專案命名:{ProjectName}.Tests
- 測試類別命名:{ClassName}Tests
## 測試方法命名規範(重要)
- **測試方法名稱必須使用繁體中文**
- 命名格式:方法名_測試情境_預期結果
- 範例:
- CalculateDiscountedPrice_輸入有效價格和折扣率_應回傳正確折扣價格()
- CalculateDiscountedPrice_輸入負數原始價格_應拋出ArgumentException()
## DisplayName 使用規範(重要)
- **每個測試方法都必須在 [Fact] 屬性中指定 DisplayName 參數**
- DisplayName 格式:`方法功能描述: 情境描述,預期結果`
- 範例:
[Fact(DisplayName = "計算折扣後的價格: 輸入有效的價格和折扣率,應回傳正確的折扣價格")]
public void CalculateDiscountedPrice_輸入有效價格和折扣率_應回傳正確折扣價格()
## 測試程式碼規範
- 所有測試必須遵循 AAA 模式 (Arrange-Act-Assert)
- 必須標註 // Arrange, // Act, // Assert 三個區塊
- 使用 AwesomeAssertions 的 Should() 語法進行斷言
- 變數名稱使用英文,類別、方法、屬性註解使用繁體中文
## 程式碼風格要求
- 使用繁體中文進行測試方法命名和 DisplayName
- 類別、建構式、屬性、方法以及程式註解一律使用繁體中文
- 變數名稱、函數名稱、類別名稱一律使用英文
- if 判斷式一定要有大括號 {}, 即使只有一層也不能省略
- 一個類別就是一個檔案,不要所有類別都放在同一個 cs 檔案裡
關鍵要點:
在接下來的學習中,我們統一使用 GitHub Copilot Chat 的 Agent 模式:
現在我們來學習第一個通用指令範本。這個指令可以應用到任何業務邏輯方法的分析。
請為 `[檔案路徑]/[類別名稱].cs` 中的 `[方法名稱]` 方法進行測試分析,並將結果儲存為 `[類別名稱]_TestScenario.md` 檔案:
**檔案標題格式**:# [類別名稱] 測試情境分析
**內容結構**(請嚴格按照以下編號和標題):
## [方法名稱] 方法
### 1. 方法簽名分析
列出參數類型、回傳類型、是否為非同步
### 2. 業務邏輯分析
識別主要的邏輯分支和驗證規則
### 3. 測試情境建議
涵蓋正常情境、邊界條件、異常處理的核心測試情境,每個情境包含具體輸入值、預期結果、驗證重點
### 4. 依賴關係識別
列出需要 Mock 的外部依賴(如有),如果是純函數請註明無外部依賴
**重要限制**:
- 只產生上述 4 個區段,不要增加其他內容
- 不要包含測試實作建議、測試覆蓋率目標等額外內容
- 依賴關係分析請專注於外部服務、資料庫、其他類別等,不要提及 .NET Framework 內建功能
請將完整分析結果儲存到適合您專案結構的目錄中的 `[類別名稱]_TestScenario.md` 檔案。
範例應用:
DiscountCalculator.CalculateDiscountedPrice
並儲存為 DiscountCalculator_TestScenario.md
在 VS Code 中開啟 GitHub Copilot Chat,切換到 Agent 模式,輸入以下指令:
請為 `src/Day27.Core/Services/DiscountCalculator.cs` 中的 `CalculateDiscountedPrice` 方法進行測試分析,並將結果儲存為 `DiscountCalculator_TestScenario.md` 檔案:
**檔案標題格式**:# DiscountCalculator 測試情境分析
**內容結構**(請嚴格按照以下編號和標題):
## CalculateDiscountedPrice 方法
### 1. 方法簽名分析
列出參數類型、回傳類型、是否為非同步
### 2. 業務邏輯分析
識別主要的邏輯分支和驗證規則
### 3. 測試情境建議
涵蓋正常情境、邊界條件、異常處理的核心測試情境,每個情境包含具體輸入值、預期結果、驗證重點
### 4. 依賴關係識別
列出需要 Mock 的外部依賴(如有),如果是純函數請註明無外部依賴
**重要限制**:
- 只產生上述 4 個區段,不要增加其他內容
- 不要包含測試實作建議、測試覆蓋率目標等額外內容
- 依賴關係分析請專注於外部服務、資料庫、其他類別等,不要提及 .NET Framework 內建功能
請將完整分析結果儲存到 `docs/testing/DiscountCalculator_TestScenario.md` 檔案中。
GitHub Copilot 會產生包含測試情境清單的分析結果,將完整結果儲存到 DiscountCalculator_TestScenario.md
。
不同 AI 模型的差異:
檔案內容組織建議:
無論 AI 產生什麼格式,建議測試情境檔案包含以下要素:
常見問題處理:
# 類別名稱 測試情境分析
和 ## 方法名稱 方法
重要:這個階段的目標是獲得清晰且可重複使用的測試情境清單,Agent 模式會自動將結果儲存為 {類別名稱}_TestScenario.md
檔案。
檔案命名:{類別名稱}_TestScenario.md
儲存位置:建議放在 docs/testing/
目錄下,方便團隊統一管理。
有了步驟 1-2 產生的測試情境清單後,現在我們要學習如何將這些情境轉換為完整的測試程式碼。
請在測試專案中建立 `[類別名稱]Tests.cs` 檔案,並基於 `[類別名稱]_TestScenario.md` 中的測試情境產生完整的 xUnit 測試類別:
**重要**:請嚴格遵循專案的 copilot-instructions.md 規範
**測試情境來源**:請參考您的測試文件目錄中的 `[類別名稱]_TestScenario.md` 檔案中的測試情境清單
**程式碼要求**:
- 3A Pattern 並標註註解
- DisplayName 屬性
- 依據測試情境產生對應的測試方法
在 GitHub Copilot Chat 中,切換到 Agent 模式,輸入以下指令:
請在測試專案中建立 `DiscountCalculatorTests.cs` 檔案,並基於 `DiscountCalculator_TestScenario.md` 中的測試情境產生完整的 xUnit 測試類別:
**重要**:請嚴格遵循專案的 copilot-instructions.md 規範
**測試情境來源**:請參考您的測試文件目錄中的 `DiscountCalculator_TestScenario.md` 檔案中的 CalculateDiscountedPrice 方法測試情境清單
**程式碼要求**:
- 3A Pattern 並標註註解
- DisplayName 屬性
- 依據測試情境產生對應的測試方法
Agent 會自動建立測試檔案並寫入完整程式碼。
產生測試程式碼後,必須進行建置和測試執行來驗證程式碼正確性:
使用 GitHub Copilot Chat Agent 模式
在 GitHub Copilot Chat 中,切換到 Agent 模式,輸入以下指令:
請執行以下步驟來建置專案並執行測試:
1. 建置整個解決方案
2. 執行剛產生的 CalculateDiscountedPrice 方法相關測試
3. 顯示測試結果摘要
請使用 FullyQualifiedName 篩選,只執行方法名稱包含 "CalculateDiscountedPrice" 的測試方法。
如果有建置錯誤或測試失敗,請說明問題並提供修正建議。
直接使用終端機指令
開啟 VS Code 終端機,在專案根目錄執行:
# 建置專案
dotnet build
# 方式 1:使用方法名稱前綴篩選 CalculateDiscountedPrice 相關測試
dotnet test --filter "FullyQualifiedName~CalculateDiscountedPrice" --verbosity normal
# 方式 2:使用 DisplayName 前綴篩選相同功能的測試
dotnet test --filter "DisplayName~計算折扣後的價格" --verbosity normal
# 方式 3:使用 FullyQualifiedName 篩選特定測試類別
dotnet test --filter "FullyQualifiedName~DiscountCalculatorTests" --verbosity normal
預期結果驗證:
成功的測試執行應該顯示類似以下結果:
測試摘要: 總計: X, 失敗: 0, 成功: X, 已跳過: 0
測試執行時間: X.X 秒
篩選指令說明:
FullyQualifiedName~CalculateDiscountedPrice
會執行所有方法名稱包含「CalculateDiscountedPrice」的測試DisplayName~計算折扣後的價格
會執行所有 DisplayName 包含「計算折扣後的價格」的測試(推薦新方式)FullyQualifiedName~DiscountCalculatorTests
會執行整個 DiscountCalculatorTests 類別的所有測試方式 2 的優勢:
實際驗證範例:
# 只執行「計算折扣價格」功能的測試方法
dotnet test --filter "DisplayName~計算折扣價格" --verbosity normal
常見問題處理:
建置錯誤:
using
命名空間是否正確測試失敗:
套件相關錯誤:
# 確認 AwesomeAssertions 套件版本
dotnet list package
# 如需要,重新安裝套件
dotnet add package AwesomeAssertions --version 9.1.0
重要:只有通過建置和測試執行驗證,才能確保 GitHub Copilot 產生的測試程式碼真正可用且正確。
完成階段一後,你應該能夠:
設定 GitHub Copilot 專案規範:
copilot-instructions.md
確保程式碼一致性3 個基礎測試指令範本:
標準化測試開發流程:
請使用學到的指令範本,為 DiscountCalculator
的另一個方法 CalculateBulkDiscount
產生測試:
使用指令範本 1-2 分析 CalculateBulkDiscount
方法:
請為 `src/Day27.Core/Services/DiscountCalculator.cs` 中的 `CalculateBulkDiscount` 方法進行測試分析,並將結果追加到現有的 `DiscountCalculator_TestScenario.md` 檔案中:
**追加內容結構**(請嚴格按照以下編號和標題):
## CalculateBulkDiscount 方法
### 1. 方法簽名分析
列出參數類型、回傳類型、是否為非同步
### 2. 業務邏輯分析
識別主要的邏輯分支和驗證規則
### 3. 測試情境建議
涵蓋正常情境、邊界條件、異常處理的核心測試情境,每個情境包含具體輸入值、預期結果、驗證重點
### 4. 依賴關係識別
列出需要 Mock 的外部依賴(如有),如果是純函數請註明無外部依賴
**重要限制**:
- 只產生上述 4 個區段,不要增加其他內容
- 不要包含測試實作建議、測試覆蓋率目標等額外內容
- 依賴關係分析請專注於外部服務、資料庫、其他類別等,不要提及 .NET Framework 內建功能
請將 CalculateBulkDiscount 方法的分析結果追加到現有的 `DiscountCalculator_TestScenario.md` 檔案中。
檢查分析結果:
DiscountCalculator_TestScenario.md
檔案包含兩個方法的完整分析使用指令範本 1-3 產生測試程式碼:
請在現有的 `DiscountCalculatorTests.cs` 檔案中,基於 `DiscountCalculator_TestScenario.md` 中的 CalculateBulkDiscount 方法測試情境,新增對應的測試方法:
**重要**:請嚴格遵循專案的 copilot-instructions.md 規範
**測試情境來源**:請參考 `DiscountCalculator_TestScenario.md` 檔案中的 CalculateBulkDiscount 方法測試情境清單
**程式碼要求**:
- 3A Pattern 並標註註解
- DisplayName 屬性
- 依據測試情境產生對應的測試方法
檢查程式碼規範:確認產生的程式碼是否符合 copilot-instructions.md 規範
驗證新的篩選功能:測試 DisplayName 前綴篩選功能
# 測試「計算批量折扣」功能的測試篩選
dotnet test --filter "DisplayName~計算批量折扣" --verbosity normal
# 預期應該執行 CalculateBulkDiscount 相關測試
預期成果:
DiscountCalculator_TestScenario.md
檔案包含兩個方法的完整分析DiscountCalculatorTests.cs
檔案包含兩個方法的完整測試在階段一中,我們學會了處理純業務邏輯的測試。現在進入階段二,學習處理包含依賴注入的業務服務測試。這是實際專案中最常見的測試場景。
從簡單邏輯進階到服務層測試:
實務應用價值:
首先,我們需要更新 GitHub Copilot 的指導設定,加入 Mock 框架的規範。
重要:階段二是在階段一的基礎上繼續添加內容,不是替換整個檔案。
在 .github/copilot-instructions.md
中進行以下更新:
1. 更新開發環境資訊中的 NuGet Packages:
在 xunit.runner.visualstudio
之後新增一行:
- NSubstitute (5.3.0)
2. 在檔案末尾添加階段二的新增規範:
## Mock 物件設定規範
- 使用 Substitute.For<T>() 建立 Mock 物件
- 使用 Returns() 設定回傳值(包含非同步方法)
- 使用 Received() 驗證方法呼叫
- 使用 DidNotReceive() 驗證方法未被呼叫
- 使用 Throws() 模擬異常情況
## 依賴注入測試結構
- 測試類別建構式中初始化所有 Mock 物件
- Mock 物件設定為 private readonly 欄位
- Mock 物件命名:mock{ServiceName}(例:mockUserRepository)
- 在建構式中建立待測試的服務實例
## 依賴注入測試規範
- 非同步測試使用 async/await 模式
- 依賴互動驗證要完整且精確
- Mock 設定要精確,避免過度設定
- 注意測試的獨立性,避免測試間相互影響
- 涵蓋成功路徑、驗證失敗、業務規則、依賴失敗、邊界條件等測試情境
重要變更說明:
階段二繼續使用與階段一相同的通用指令範本,但分析重點會自動調整到依賴注入服務的特性。
與階段一的一致性:
在 GitHub Copilot Chat 中,切換到 Agent 模式,輸入以下指令:
請為 `src/Day27.Core/UserService.cs` 中的 `RegisterUserAsync` 方法進行測試分析,並將結果儲存為 `UserService_TestScenario.md` 檔案:
**檔案標題格式**:# UserService 測試情境分析
**內容結構**(請嚴格按照以下編號和標題):
## RegisterUserAsync 方法
### 1. 方法簽名分析
列出參數類型、回傳類型、是否為非同步
### 2. 業務邏輯分析
識別主要的邏輯分支和驗證規則
### 3. 測試情境建議
涵蓋正常情境、邊界條件、異常處理的核心測試情境,每個情境包含具體輸入值、預期結果、驗證重點
### 4. 依賴關係識別
列出需要 Mock 的外部依賴(如有),如果是純函數請註明無外部依賴
**重要限制**:
- 只產生上述 4 個區段,不要增加其他內容
- 不要包含測試實作建議、測試覆蓋率目標等額外內容
- 依賴關係分析請專注於外部服務、資料庫、其他類別等,不要提及 .NET Framework 內建功能
請將完整分析結果儲存到 `docs/testing/UserService_TestScenario.md` 檔案中。
使用相同的指令範本分析 UserService,會產生以下特點的結果:
1. 方法簽名分析:
async Task<User>
)2. 業務邏輯分析:
3. 測試情境建議:
4. 依賴關係識別:
階段二繼續使用與階段一相同的通用指令範本,GitHub Copilot 會根據更新的 copilot-instructions.md 自動產生包含 Mock 物件的測試程式碼。
與階段一的一致性:
在 GitHub Copilot Chat 中,切換到 Agent 模式,輸入以下指令:
請在測試專案中建立 `UserServiceTests.cs` 檔案,並基於 `UserService_TestScenario.md` 中的測試情境產生完整的 xUnit 測試類別:
**重要**:請嚴格遵循專案的 copilot-instructions.md 規範
**測試情境來源**:請參考您的測試文件目錄中的 `UserService_TestScenario.md` 檔案中的 RegisterUserAsync 方法測試情境清單
**程式碼要求**:
- 3A Pattern 並標註註解
- DisplayName 屬性
- 依據測試情境產生對應的測試方法
由於 copilot-instructions.md 已包含 Mock 框架規範,GitHub Copilot 會自動:
建立 Mock 物件:
private readonly IUserRepository mockUserRepository;
private readonly IEmailService mockEmailService;
private readonly UserService userService;
設定 Mock 行為:
// Arrange
mockUserRepository.ExistsByEmailAsync("test@example.com").ReturnsAsync(false);
mockUserRepository.SaveAsync(Arg.Any<User>()).ReturnsAsync(expectedUser);
驗證依賴互動:
// Assert
await mockUserRepository.Received(1).ExistsByEmailAsync("test@example.com");
await mockUserRepository.Received(1).SaveAsync(Arg.Any<User>());
產生測試程式碼後,必須進行建置和測試執行來驗證程式碼正確性:
使用 GitHub Copilot Chat Agent 模式
在 GitHub Copilot Chat 中,切換到 Agent 模式,輸入以下指令:
請執行以下步驟來建置專案並執行測試:
1. 建置整個解決方案
2. 執行剛產生的 RegisterUserAsync 方法相關測試
3. 顯示測試結果摘要
請使用 FullyQualifiedName 篩選,只執行方法名稱包含 "RegisterUserAsync" 的測試方法。
如果有建置錯誤或測試失敗,請說明問題並提供修正建議。
直接使用終端機指令
開啟 VS Code 終端機,在專案根目錄執行:
# 建置專案
dotnet build
# 方式 1:使用方法名稱前綴篩選 RegisterUserAsync 相關測試
dotnet test --filter "FullyQualifiedName~RegisterUserAsync" --verbosity normal
# 方式 2:使用 DisplayName 前綴篩選相同功能的測試
dotnet test --filter "DisplayName~註冊新使用者" --verbosity normal
# 方式 3:使用 FullyQualifiedName 篩選特定測試類別
dotnet test --filter "FullyQualifiedName~UserServiceTests" --verbosity normal
預期結果驗證:
成功的測試執行應該顯示類似以下結果:
測試摘要: 總計: X, 失敗: 0, 成功: X, 已跳過: 0
測試執行時間: X.X 秒
篩選指令說明:
FullyQualifiedName~RegisterUserAsync
會執行所有方法名稱包含「RegisterUserAsync」的測試DisplayName~註冊新使用者
會執行所有 DisplayName 包含「註冊新使用者」的測試FullyQualifiedName~UserServiceTests
會執行整個 UserServiceTests 類別的所有測試重要:只有通過建置和測試執行驗證,才能確保 GitHub Copilot 產生的測試程式碼真正可用且正確。
完成階段二後,你應該能夠:
設定依賴注入測試環境:
copilot-instructions.md
加入 Mock 框架規範3 個統一的測試指令範本:
標準化依賴注入測試開發流程:
UserService
還有三個公開方法尚未建立測試:UpdateUserStatusAsync
、ValidatePassword
、IsValidEmail
。請使用學到的指令範本,為這三個方法產生完整的測試:
完整的 UserService 測試覆蓋:
RegisterUserAsync
的測試混合測試類型練習:
UpdateUserStatusAsync
:非同步方法,包含依賴注入ValidatePassword
:同步方法,純邏輯驗證IsValidEmail
:同步方法,純邏輯驗證階段整合驗證:
UserServiceTests.cs
檔案包含四個方法的完整測試ValidatePassword
、IsValidEmail
),GitHub Copilot 會自動產生無 Mock 的測試UpdateUserStatusAsync
),會自動包含 Mock 物件設定準備好進入階段三了嗎?請確保已完成階段二的練習,接下來就讓我們繼續下去。
在前兩階段中,我們學會了處理單一方法的測試。現在進入階段三,練習將這些技巧應用到業務流程測試場景。
練習重點:
實務應用價值:
階段三需要在現有的 Mock 框架規範基礎上,加入業務流程測試的特殊設定。
重要:階段三是在階段二的基礎上繼續添加內容,不是替換整個檔案。
在 .github/copilot-instructions.md
檔案末尾添加以下內容:
## 業務流程測試規範
- 使用 Received.InOrder() 驗證方法呼叫順序
- 針對業務流程的每個步驟設計失敗測試
- 驗證業務規則和狀態轉換邏輯
- 測試異常情況下的資料一致性
- 重點關注業務邏輯的完整性而非技術實作細節
## 複雜測試情境設計
- 正常業務流程:完整的步驟執行和結果驗證
- 業務規則驗證:狀態檢查、權限驗證、業務條件
- 異常處理測試:每個失敗點的獨立測試
- 邊界條件測試:業務邏輯的臨界值和特殊狀況
- 狀態一致性測試:確保資料狀態的正確轉換
階段三新增規範說明:
Received.InOrder()
確保業務步驟的執行順序階段三繼續使用與前兩階段相同的通用指令範本,但分析重點會自動調整到業務流程的複雜性。
與前兩階段的一致性:
在 GitHub Copilot Chat 中,切換到 Agent 模式,輸入以下指令:
請為 `src/Day27.Core/Services/OrderProcessor.cs` 中的 `CancelOrderAsync` 方法進行測試分析,並將結果儲存為 `OrderProcessor_TestScenario.md` 檔案:
**檔案標題格式**:# OrderProcessor 測試情境分析
**內容結構**(請嚴格按照以下編號和標題):
## CancelOrderAsync 方法
### 1. 方法簽名分析
列出參數類型、回傳類型、是否為非同步
### 2. 業務邏輯分析
識別主要的邏輯分支和驗證規則
### 3. 測試情境建議
涵蓋正常情境、邊界條件、異常處理的核心測試情境,每個情境包含具體輸入值、預期結果、驗證重點
### 4. 依賴關係識別
列出需要 Mock 的外部依賴(如有),如果是純函數請註明無外部依賴
**重要限制**:
- 只產生上述 4 個區段,不要增加其他內容
- 不要包含測試實作建議、測試覆蓋率目標等額外內容
- 依賴關係分析請專注於外部服務、資料庫、其他類別等,不要提及 .NET Framework 內建功能
請將完整分析結果儲存到 `docs/testing/OrderProcessor_TestScenario.md` 檔案中。
使用相同的指令範本分析 OrderProcessor 的 CancelOrderAsync 方法,會產生以下特點的結果:
1. 方法簽名分析:
2. 業務邏輯分析:
3. 測試情境建議:
4. 依賴關係識別:
階段三的重點是如何設計測試不同失敗點和業務規則的情境。
在 GitHub Copilot Chat 中,切換到 Agent 模式,輸入以下指令:
請在測試專案中建立 `OrderProcessorTests.cs` 檔案,並基於 `OrderProcessor_TestScenario.md` 中的測試情境產生完整的 xUnit 測試類別:
**重要**:請嚴格遵循專案的 copilot-instructions.md 規範
**測試情境來源**:請參考您的測試文件目錄中的 `OrderProcessor_TestScenario.md` 檔案中的 CancelOrderAsync 方法測試情境清單
**程式碼要求**:
- 3A Pattern 並標註註解
- DisplayName 屬性
- 依據測試情境產生對應的測試方法
由於 copilot-instructions.md 已包含業務流程測試規範,GitHub Copilot 會自動:
建立完整的 Mock 設定:
private readonly IOrderRepository mockOrderRepository;
private readonly IPaymentService mockPaymentService;
private readonly IInventoryService mockInventoryService;
private readonly INotificationService mockNotificationService;
private readonly OrderProcessor orderProcessor;
設定業務規則測試:
// Arrange
var existingOrder = new Order { Id = 1, Status = OrderStatus.Paid };
mockOrderRepository.GetByIdAsync(1).ReturnsAsync(existingOrder);
// Act & Assert
var exception = await Assert.ThrowsAsync<InvalidOperationException>(
() => orderProcessor.CancelOrderAsync(1));
exception.Message.Should().Be("已付款的訂單無法取消");
驗證狀態轉換:
// Assert
result.Status.Should().Be(OrderStatus.Cancelled);
await mockOrderRepository.Received(1).SaveAsync(Arg.Is<Order>(o => o.Status == OrderStatus.Cancelled));
階段三的重點是處理業務規則驗證和狀態轉換的測試。
產生測試程式碼後,進行建置和測試執行:
使用 GitHub Copilot Chat Agent 模式
請執行以下步驟來建置專案並執行測試:
1. 建置整個解決方案
2. 執行剛產生的 CancelOrderAsync 方法相關測試
3. 顯示測試結果摘要
請使用 FullyQualifiedName 篩選,只執行方法名稱包含 "CancelOrderAsync" 的測試方法。
如果有建置錯誤或測試失敗,請說明問題並提供修正建議。
直接使用終端機指令
# 建置專案
dotnet build
# 方式 1:使用方法名稱前綴篩選 CancelOrderAsync 相關測試
dotnet test --filter "FullyQualifiedName~CancelOrderAsync" --verbosity normal
# 方式 2:使用 DisplayName 前綴篩選相同功能的測試
dotnet test --filter "DisplayName~取消訂單" --verbosity normal
# 方式 3:使用 FullyQualifiedName 篩選特定測試類別
dotnet test --filter "FullyQualifiedName~OrderProcessorTests" --verbosity normal
篩選指令說明:
FullyQualifiedName~CancelOrderAsync
會執行所有方法名稱包含「CancelOrderAsync」的測試DisplayName~取消訂單
會執行所有 DisplayName 包含「取消訂單」的測試(推薦新方式)FullyQualifiedName~OrderProcessorTests
會執行整個 OrderProcessorTests 類別的所有測試重要:階段三的驗證重點在於確保業務規則和狀態轉換邏輯的正確性。
完成階段三後,你應該能夠:
OrderProcessor
還有一個更複雜的公開方法尚未建立測試:ProcessOrderAsync
。請使用學到的指令範本,為這個方法產生完整的測試:
完整的 OrderProcessor 測試覆蓋:
CancelOrderAsync
的測試ProcessOrderAsync
方法的測試多步驟業務流程測試:
ProcessOrderAsync
:包含 5 個連續步驟的複雜業務流程階段三技巧整合驗證:
OrderProcessor_TestScenario.md
檔案包含兩個方法的完整分析OrderProcessorTests.cs
檔案包含兩個方法的完整測試設定業務流程測試環境:
copilot-instructions.md
加入業務流程測試規範3 個統一的測試指令範本:
標準化業務流程測試開發流程:
經過三個階段的實驗,你應該對「如何讓 AI 幫助測試開發」有了一些具體的想法。上面所介紹的方法不是萬能的,但提供了一個思考方向:如何系統化地引導 AI 從業務邏輯分析開始,逐步產生有用的測試程式碼。
流程理解:
方法框架:
實驗心得:
文章裡所介紹的這些方法的價值在於「給你一個方向」:
嘗試應用到你的專案:
建立團隊共識:
持續迭代改進:
最後提醒:這些方法只是一個起點,重點是讓你看看怎麼設計適合自己團隊的 AI 協作流程。每個專案的需求都不同,不要期待能直接套用,而是要根據實際情況持續調整。
這是「重啟挑戰:老派軟體工程師的測試修練」的第二十七天。明天會介紹 Day 28 – TUnit 入門:下世代 .NET 測試框架探索。