{"id":"dd7469e6-7509-4a8e-98bb-7d6848159577","shortId":"nWXVwb","kind":"skill","title":"dotnet-testing-test-naming-conventions","tagline":"測試命名規範與最佳實踐的專門技能。當需要為測試方法命名、改進測試可讀性、建立命名標準時使用。涵蓋三段式命名法、中文命名建議、測試類別命名等。\nMake sure to use this skill whenever the user mentions test naming, how to name tests, test readability, or test method naming conventions, even if they don't explicitly ask for naming guidance.\nKeywords: test","description":"# .NET 測試命名規範指南\n\n## 測試方法命名規範\n\n### 標準格式\n\n使用底線分隔的三段式命名法：\n\n```text\n[被測試方法名稱]_[測試情境/輸入條件]_[預期行為/結果]\n```\n\n### 各段說明\n\n| 區段                  | 說明                     | 範例                                       |\n| --------------------- | ------------------------ | ------------------------------------------ |\n| **被測試方法名稱**    | 正在測試的方法名稱       | `Add`、`ProcessOrder`、`IsValidEmail`      |\n| **測試情境/輸入條件** | 描述測試的前置條件或輸入 | `輸入1和2`、`輸入null`、`輸入有效訂單`     |\n| **預期行為/結果**     | 描述預期的輸出或行為     | `應回傳3`、`應拋出Exception`、`應回傳True` |\n\n## 命名範例對照表\n\n### 好的命名 vs 不好的命名\n\n三段式命名可以使用中文或英文，依團隊慣例選擇。以下同時展示兩種風格：\n\n| 不好的命名 | 中文命名（推薦）                                    | 英文命名                                                      | 原因                       |\n| ------------- | --------------------------------------------------- | ------------------------------------------------------------- | -------------------------- |\n| `TestAdd`     | `Add_輸入1和2_應回傳3`                              | `Add_WhenGiven1And2_ShouldReturn3`                            | 清楚說明測試情境與預期結果 |\n| `Test1`       | `Add_輸入負數和正數_應回傳正確結果`                 | `Add_WhenGivenNegativeAndPositive_ShouldReturnCorrectResult`  | 有意義的描述               |\n| `EmailTest`   | `IsValidEmail_輸入有效Email_應回傳True`             | `IsValidEmail_WhenValidEmail_ShouldReturnTrue`                | 完整的三段式命名           |\n| `OrderTest`   | `ProcessOrder_輸入null_應拋出ArgumentNullException` | `ProcessOrder_WhenNull_ShouldThrowArgumentNullException`      | 明確的例外情境             |\n\n## 實際範例\n\n### 基本運算測試\n\n```csharp\n// ✅ 正常路徑測試\n[Fact]\npublic void Add_輸入1和2_應回傳3()\n\n// ✅ 邊界條件測試\n[Fact]\npublic void Add_輸入0和0_應回傳0()\n\n// ✅ 負數測試\n[Fact]\npublic void Add_輸入負數和正數_應回傳正確結果()\n```\n\n### 驗證邏輯測試\n\n```csharp\n// ✅ 有效輸入測試\n[Fact]\npublic void IsValidEmail_輸入有效Email_應回傳True()\n\n// ✅ 無效輸入 - null\n[Fact]\npublic void IsValidEmail_輸入null值_應回傳False()\n\n// ✅ 無效輸入 - 空字串\n[Fact]\npublic void IsValidEmail_輸入空字串_應回傳False()\n\n// ✅ 無效輸入 - 格式錯誤\n[Fact]\npublic void IsValidEmail_輸入無效Email格式_應回傳False()\n```\n\n### 業務邏輯測試\n\n```csharp\n// ✅ 處理流程測試\n[Fact]\npublic void ProcessOrder_輸入有效訂單_應回傳處理後訂單()\n\n// ✅ 例外處理測試\n[Fact]\npublic void ProcessOrder_輸入null_應拋出ArgumentNullException()\n\n// ✅ 格式化測試\n[Fact]\npublic void GetOrderNumber_輸入有效訂單_應回傳格式化訂單號碼()\n```\n\n### 計算邏輯測試\n\n```csharp\n// ✅ 正常計算\n[Fact]\npublic void Calculate_輸入100元和10Percent折扣_應回傳90元()\n\n// ✅ 無效輸入 - 負數\n[Fact]\npublic void Calculate_輸入負數價格_應拋出ArgumentException()\n\n// ✅ 邊界值測試\n[Fact]\npublic void Calculate_輸入0元價格_應正常處理()\n\n// ✅ 含稅計算\n[Fact]\npublic void CalculateWithTax_輸入100元和5Percent稅率_應回傳105元()\n```\n\n### 狀態變化測試\n\n```csharp\n// ✅ 初始狀態測試\n[Fact]\npublic void Increment_從0開始_應回傳1()\n\n// ✅ 連續操作測試\n[Fact]\npublic void Increment_從0開始連續兩次_應回傳2()\n\n// ✅ 重設測試\n[Fact]\npublic void Reset_從任意值_應回傳0()\n```\n\n## 測試類別命名規範\n\n### 標準格式\n\n```text\n[被測試類別名稱]Tests\n```\n\n### 範例\n\n| 被測試類別        | 測試類別名稱           |\n| ----------------- | ---------------------- |\n| `Calculator`      | `CalculatorTests`      |\n| `OrderService`    | `OrderServiceTests`    |\n| `EmailHelper`     | `EmailHelperTests`     |\n| `PriceCalculator` | `PriceCalculatorTests` |\n\n### 類別結構範本\n\n```csharp\nnamespace MyProject.Tests;\n\n/// <summary>\n/// class CalculatorTests - Calculator 測試類別\n/// </summary>\npublic class CalculatorTests\n{\n    private readonly Calculator _calculator;\n\n    public CalculatorTests()\n    {\n        _calculator = new Calculator();\n    }\n\n    //---------------------------------------------------------------------------------------------\n    // Add 方法測試\n\n    [Fact]\n    public void Add_輸入1和2_應回傳3()\n    {\n        // ...\n    }\n\n    //---------------------------------------------------------------------------------------------\n    // Divide 方法測試\n\n    [Fact]\n    public void Divide_輸入10和2_應回傳5()\n    {\n        // ...\n    }\n}\n```\n\n## 參數化測試命名\n\n使用 `[Theory]` 時的命名規範：\n\n```csharp\n// ✅ 使用「各種」表示多組測試資料\n[Theory]\n[InlineData(1, 2, 3)]\n[InlineData(-1, 1, 0)]\n[InlineData(0, 0, 0)]\npublic void Add_輸入各種數值組合_應回傳正確結果(int a, int b, int expected)\n\n// ✅ 使用「有效」表示正向測試\n[Theory]\n[InlineData(\"test@example.com\")]\n[InlineData(\"user.name@domain.org\")]\npublic void IsValidEmail_輸入有效Email格式_應回傳True(string validEmail)\n\n// ✅ 使用「無效」表示負向測試\n[Theory]\n[InlineData(\"invalid-email\")]\n[InlineData(\"@example.com\")]\npublic void IsValidEmail_輸入無效Email格式_應回傳False(string invalidEmail)\n```\n\n## 常用情境詞彙\n\n### 輸入條件詞彙\n\n| 詞彙        | 使用情境             |\n| ----------- | -------------------- |\n| `輸入`      | 一般輸入參數         |\n| `給定`      | Given-When-Then 風格 |\n| `當`        | 事件觸發             |\n| `從...開始` | 初始狀態描述         |\n\n### 預期結果詞彙\n\n| 詞彙         | 使用情境 |\n| ------------ | -------- |\n| `應回傳`     | 有回傳值 |\n| `應拋出`     | 預期例外 |\n| `應為`       | 狀態驗證 |\n| `應包含`     | 集合驗證 |\n| `應正常處理` | 邊界條件 |\n\n## 命名檢查清單\n\n為測試方法命名時，請確認：\n\n- [ ] 使用三段式命名 `方法_情境_預期`\n- [ ] 情境描述清楚明確\n- [ ] 預期結果具體可驗證\n- [ ] 使用中文增加可讀性\n- [ ] 避免模糊詞彙如 `Test1`、`TestMethod`\n- [ ] 參數化測試使用「各種」、「有效」、「無效」等詞彙\n\n## 測試報告可讀性\n\n好的命名會讓測試報告更易讀：\n\n```text\nPASS CalculatorTests\n   PASS Add_輸入1和2_應回傳3\n   PASS Add_輸入負數和正數_應回傳正確結果\n   FAIL Divide_輸入10和0_應拋出DivideByZeroException\n\nPASS EmailHelperTests\n   PASS IsValidEmail_輸入有效Email_應回傳True\n   PASS IsValidEmail_輸入null值_應回傳False\n```\n\n## 輸出格式\n\n- 使用三段式命名法：`[方法名稱]_[測試情境]_[預期行為]`\n- 測試類別命名為 `{被測類別}Tests`\n- 情境描述使用中文以提升可讀性\n- 參數化測試使用「各種」、「有效」、「無效」等詞彙\n\n## 參考資源\n\n請參考同目錄下的範例檔案：\n\n- [templates/naming-convention-examples.cs](templates/naming-convention-examples.cs) - 命名規範完整範例\n\n### 原始文章\n\n本技能內容提煉自「老派軟體工程師的測試修練 - 30 天挑戰」系列文章：\n\n- **Day 01 - 老派工程師的測試啟蒙**\n  - 鐵人賽文章：https://ithelp.ithome.com.tw/articles/10373888\n  - 範例程式碼：https://github.com/kevintsengtw/30Days_in_Testing_Samples/tree/main/day01\n\n### 相關技能\n\n- `dotnet-testing-unit-test-fundamentals` - 單元測試基礎\n- `dotnet-testing-xunit-project-setup` - xUnit 專案設定","tags":["dotnet","testing","test","naming","conventions","agent","skills","kevintsengtw","agent-skills","ai-assisted-development","copilot-skills","csharp"],"capabilities":["skill","source-kevintsengtw","skill-dotnet-testing-test-naming-conventions","topic-agent-skills","topic-ai-assisted-development","topic-copilot-skills","topic-csharp","topic-dotnet","topic-dotnet-testing","topic-github-copilot","topic-integration-testing","topic-testing","topic-unit-testing","topic-xunit"],"categories":["dotnet-testing-agent-skills"],"synonyms":[],"warnings":[],"endpointUrl":"https://skills.sh/kevintsengtw/dotnet-testing-agent-skills/dotnet-testing-test-naming-conventions","protocol":"skill","transport":"skills-sh","auth":{"type":"none","details":{"cli":"npx skills add kevintsengtw/dotnet-testing-agent-skills","source_repo":"https://github.com/kevintsengtw/dotnet-testing-agent-skills","install_from":"skills.sh"}},"qualityScore":"0.461","qualityRationale":"deterministic score 0.46 from registry signals: · indexed on github topic:agent-skills · 23 github stars · SKILL.md body (5,598 chars)","verified":false,"liveness":"unknown","lastLivenessCheck":null,"agentReviews":{"count":0,"score_avg":null,"cost_usd_avg":null,"success_rate":null,"latency_p50_ms":null,"narrative_summary":null,"summary_updated_at":null},"enrichmentModel":"deterministic:skill-github:v1","enrichmentVersion":1,"enrichedAt":"2026-04-24T13:02:27.348Z","embedding":null,"createdAt":"2026-04-18T23:04:34.127Z","updatedAt":"2026-04-24T13:02:27.348Z","lastSeenAt":"2026-04-24T13:02:27.348Z","tsv":"'-1':325 '/articles/10373888':481 '/kevintsengtw/30days_in_testing_samples/tree/main/day01':485 '0':327,329,330,331 '01':476 '1':321,326 '2':322 '3':323 '30':472 'add':66,94,97,102,105,132,139,146,295,300,334,429,433 'ask':43 'b':340 'calcul':211,219,226,267,281,288,289,292,294 'calculatewithtax':233 'calculatortest':268,280,285,291,427 'class':279,284 'convent':6,36 'csharp':127,150,183,206,237,276,315 'day':475 'divid':303,308,437 'dotnet':2,488,495 'dotnet-testing-test-naming-convent':1 'dotnet-testing-unit-test-fundament':487 'dotnet-testing-xunit-project-setup':494 'email':365 'emailhelp':271 'emailhelpertest':272,441 'emailtest':109 'even':37 'example.com':367 'expect':342 'explicit':42 'fact':129,136,143,152,160,168,176,185,192,199,208,216,223,230,239,246,253,297,305 'fail':436 'fundament':492 'getordernumb':202 'github.com':484 'github.com/kevintsengtw/30days_in_testing_samples/tree/main/day01':483 'given':383 'given-when-then':382 'guidanc':46 'increment':242,249 'inlinedata':320,324,328,347,349,362,366 'int':337,339,341 'invalid':364 'invalid-email':363 'invalidemail':374 'isvalidemail':68,110,113,155,163,171,179,353,370,443,447 'ithelp.ithome.com.tw':480 'ithelp.ithome.com.tw/articles/10373888':479 'keyword':47 'make':14 'mention':23 'method':34 'myproject.tests':278 'name':5,25,28,35,45 'namespac':277 'net':49 'new':293 'null':159 'orderservic':269 'orderservicetest':270 'ordertest':117 'pass':426,428,432,440,442,446 'pricecalcul':273 'pricecalculatortest':274 'privat':286 'processord':67,118,121,188,195 'project':498 'public':130,137,144,153,161,169,177,186,193,200,209,217,224,231,240,247,254,283,290,298,306,332,351,368 'readabl':31 'readon':287 'reset':256 'setup':499 'shouldreturn3':99 'shouldreturncorrectresult':107 'shouldreturntru':115 'shouldthrowargumentnullexcept':123 'skill':19 'skill-dotnet-testing-test-naming-conventions' 'source-kevintsengtw' 'string':356,373 'sure':15 'templates/naming-convention-examples.cs':466,467 'test':3,4,24,29,30,33,48,263,457,489,491,496 'test1':101,416 'test@example.com':348 'testadd':93 'testmethod':417 'text':54,261,425 'theori':313,319,346,361 'topic-agent-skills' 'topic-ai-assisted-development' 'topic-copilot-skills' 'topic-csharp' 'topic-dotnet' 'topic-dotnet-testing' 'topic-github-copilot' 'topic-integration-testing' 'topic-testing' 'topic-unit-testing' 'topic-xunit' 'unit':490 'use':17 'user':22 'user.name@domain.org':350 'validemail':357 'void':131,138,145,154,162,170,178,187,194,201,210,218,225,232,241,248,255,299,307,333,352,369 'vs':83 'whenev':20 'whengiven1and2':98 'whengivennegativeandposit':106 'whennul':122 'whenvalidemail':114 'xunit':497,500 '一般輸入參數':380 '三段式命名可以使用中文或英文':85 '不好的命名':84,88 '中文命名':89 '中文命名建議':12 '事件觸發':388 '以下同時展示兩種風格':87 '使用':312,316,343,358 '使用三段式命名':408 '使用三段式命名法':451 '使用中文增加可讀性':414 '使用底線分隔的三段式命名法':53 '使用情境':378,394 '例外處理測試':191 '依團隊慣例選擇':86 '初始狀態描述':391 '初始狀態測試':238 '區段':61 '原因':92 '原始文章':469 '參數化測試使用':418,459 '參數化測試命名':311 '參考資源':464 '各段說明':60 '各種':317,419,460 '含稅計算':229 '命名檢查清單':405 '命名範例對照表':81 '命名規範完整範例':468 '單元測試基礎':493 '基本運算測試':126 '天挑戰':473 '好的命名':82 '好的命名會讓測試報告更易讀':424 '完整的三段式命名':116 '實際範例':125 '專案設定':501 '常用情境詞彙':375 '建立命名標準時使用':10 '從':389 '從0開始':243 '從0開始連續兩次':250 '從任意值':257 '情境':410 '情境描述使用中文以提升可讀性':458 '情境描述清楚明確':412 '應包含':401 '應回傳':395 '應回傳0':141,258 '應回傳1':244 '應回傳105元':235 '應回傳2':251 '應回傳3':78,96,134,302,431 '應回傳5':310 '應回傳90元':213 '應回傳fals':165,173,181,372,449 '應回傳true':80,112,157,355,445 '應回傳格式化訂單號碼':204 '應回傳正確結果':104,148,336,435 '應回傳處理後訂單':190 '應拋出':397 '應拋出argumentexcept':221 '應拋出argumentnullexcept':120,197 '應拋出dividebyzeroexcept':439 '應拋出except':79 '應正常處理':228,403 '應為':399 '推薦':90 '描述測試的前置條件或輸入':71 '描述預期的輸出或行為':77 '改進測試可讀性':9 '方法':409 '方法名稱':452 '方法測試':296,304 '明確的例外情境':124 '時的命名規範':314 '有回傳值':396 '有意義的描述':108 '有效':344,420,461 '有效輸入測試':151 '本技能內容提煉自':470 '格式化測試':198 '格式錯誤':175 '業務邏輯測試':182 '標準格式':52,260 '正在測試的方法名稱':65 '正常計算':207 '正常路徑測試':128 '涵蓋三段式命名法':11 '清楚說明測試情境與預期結果':100 '測試命名規範指南':50 '測試命名規範與最佳實踐的專門技能':7 '測試報告可讀性':423 '測試情境':56,69,453 '測試方法命名規範':51 '測試類別':282 '測試類別名稱':266 '測試類別命名為':455 '測試類別命名等':13 '測試類別命名規範':259 '為測試方法命名時':406 '無效':359,421,462 '無效輸入':158,166,174,214 '狀態變化測試':236 '狀態驗證':400 '當':387 '當需要為測試方法命名':8 '相關技能':486 '空字串':167 '等詞彙':422,463 '範例':63,264 '範例程式碼':482 '系列文章':474 '結果':59,76 '給定':381 '老派工程師的測試啟蒙':477 '老派軟體工程師的測試修練':471 '英文命名':91 '處理流程測試':184 '表示多組測試資料':318 '表示正向測試':345 '表示負向測試':360 '被測試方法名稱':55,64 '被測試類別':265 '被測試類別名稱':262 '被測類別':456 '計算邏輯測試':205 '詞彙':377,393 '說明':62 '請參考同目錄下的範例檔案':465 '請確認':407 '負數':215 '負數測試':142 '輸入':379 '輸入0元價格':227 '輸入0和0':140 '輸入100元和10percent折扣':212 '輸入100元和5percent稅率':234 '輸入10和0':438 '輸入10和2':309 '輸入1和2':72,95,133,301,430 '輸入null':73,119,196 '輸入null值':164,448 '輸入各種數值組合':335 '輸入有效email':111,156,444 '輸入有效email格式':354 '輸入有效訂單':74,189,203 '輸入條件':57,70 '輸入條件詞彙':376 '輸入無效email格式':180,371 '輸入空字串':172 '輸入負數價格':220 '輸入負數和正數':103,147,434 '輸出格式':450 '連續操作測試':245 '避免模糊詞彙如':415 '邊界值測試':222 '邊界條件':404 '邊界條件測試':135 '重設測試':252 '鐵人賽文章':478 '開始':390 '集合驗證':402 '預期':411 '預期例外':398 '預期結果具體可驗證':413 '預期結果詞彙':392 '預期行為':58,75,454 '類別結構範本':275 '風格':386 '驗證邏輯測試':149","prices":[{"id":"1449c19d-9215-42a7-a935-70749f94b111","listingId":"dd7469e6-7509-4a8e-98bb-7d6848159577","amountUsd":"0","unit":"free","nativeCurrency":null,"nativeAmount":null,"chain":null,"payTo":null,"paymentMethod":"skill-free","isPrimary":true,"details":{"org":"kevintsengtw","category":"dotnet-testing-agent-skills","install_from":"skills.sh"},"createdAt":"2026-04-18T23:04:34.127Z"}],"sources":[{"listingId":"dd7469e6-7509-4a8e-98bb-7d6848159577","source":"github","sourceId":"kevintsengtw/dotnet-testing-agent-skills/dotnet-testing-test-naming-conventions","sourceUrl":"https://github.com/kevintsengtw/dotnet-testing-agent-skills/tree/main/skills/dotnet-testing-test-naming-conventions","isPrimary":false,"firstSeenAt":"2026-04-18T23:04:34.127Z","lastSeenAt":"2026-04-24T13:02:27.348Z"}],"details":{"listingId":"dd7469e6-7509-4a8e-98bb-7d6848159577","quickStartSnippet":null,"exampleRequest":null,"exampleResponse":null,"schema":null,"openapiUrl":null,"agentsTxtUrl":null,"citations":[],"useCases":[],"bestFor":[],"notFor":[],"kindDetails":{"org":"kevintsengtw","slug":"dotnet-testing-test-naming-conventions","github":{"repo":"kevintsengtw/dotnet-testing-agent-skills","stars":23,"topics":["agent-skills","ai-assisted-development","copilot-skills","csharp","dotnet","dotnet-testing","github-copilot","integration-testing","testing","unit-testing","xunit"],"license":"mit","html_url":"https://github.com/kevintsengtw/dotnet-testing-agent-skills","pushed_at":"2026-03-31T07:28:56Z","description":"AI Agent Skills for .NET Testing - Based on 30-Day Testing Challenge (iThome Ironman 2025 Winner)","skill_md_sha":"ae230a01b7d0a6c3af2527b0b7ee58d902035c3b","skill_md_path":"skills/dotnet-testing-test-naming-conventions/SKILL.md","default_branch":"main","skill_tree_url":"https://github.com/kevintsengtw/dotnet-testing-agent-skills/tree/main/skills/dotnet-testing-test-naming-conventions"},"layout":"multi","source":"github","category":"dotnet-testing-agent-skills","frontmatter":{"name":"dotnet-testing-test-naming-conventions","description":"測試命名規範與最佳實踐的專門技能。當需要為測試方法命名、改進測試可讀性、建立命名標準時使用。涵蓋三段式命名法、中文命名建議、測試類別命名等。\nMake sure to use this skill whenever the user mentions test naming, how to name tests, test readability, or test method naming conventions, even if they don't explicitly ask for naming guidance.\nKeywords: test naming, 測試命名, naming conventions, 命名規範, 三段式命名, three-part naming, method_scenario_expected, 方法_情境_預期, 如何命名測試, 測試可讀性, test readability, 命名最佳實踐, 測試報告, test documentation"},"skills_sh_url":"https://skills.sh/kevintsengtw/dotnet-testing-agent-skills/dotnet-testing-test-naming-conventions"},"updatedAt":"2026-04-24T13:02:27.348Z"}}