{"id":"9a998427-fb0a-4c17-a246-1950a91789d2","shortId":"b9DTWV","kind":"skill","title":"dotnet-testing-test-data-builder-pattern","tagline":"Test Data Builder Pattern 完整實作指南。當需要使用建構者模式建立可維護的測試資料或簡化複雜物件的測試準備時使用。涵蓋流暢介面、語意化方法、預設值設計與 Builder 組合模式。\nMake sure to use this skill whenever the user mentions test data builder, builder pattern, fluent interface, Object Mother, or test data preparation for complex objects, even if","description":"# Test Data Builder Pattern 測試資料建構器模式\n\n## 核心概念\n\n### 什麼是 Test Data Builder Pattern？\n\nTest Data Builder Pattern 是 Object Mother Pattern 的改良版，主要解決以下問題：\n\n1. **固定測試資料的問題**：Object Mother 提供固定的測試物件，難以針對特定測試情境調整\n2. **測試意圖不明確**：直接建立物件時，測試的關注點容易被大量屬性設定所掩蓋\n3. **重複程式碼**：相似的物件建立邏輯在多個測試中重複出現\n\n### 為何需要 Builder Pattern？\n\n```csharp\n// ❌ 問題：過多參數設定，測試意圖不明確\nvar user = new User\n{\n    Name = \"John Doe\", Email = \"john@example.com\", Age = 30,\n    Roles = new[] { \"User\" }, Settings = new UserSettings { Theme = \"Dark\", Language = \"zh-TW\" },\n    IsActive = true, CreatedAt = DateTime.Now, ModifiedAt = DateTime.Now\n};\n\n// ✅ 改善：意圖明確，只設定測試關注的屬性\nvar user = UserBuilder.AUser().WithName(\"John Doe\").WithValidEmail().Build();\n```\n\n## 實作指南\n\n### 基本 Builder 結構\n\n一個標準的 Test Data Builder 應包含：\n\n1. **預設值**：為所有必要屬性提供合理的預設值\n2. **流暢介面**：使用 `With*` 方法鏈來設定屬性\n3. **語意化方法**：提供有意義的預設建立者（如 `AnAdminUser()`、`ARegularUser()`）\n4. **Build 方法**：最終建立並回傳目標物件\n\n涵蓋完整 UserBuilder 實作（預設值、With* 流暢方法、語意化靜態工廠方法、Build 方法）、單一測試情境與配合 Theory 使用的範例。\n\n> 完整 Builder 實作與測試使用範例請參考 [references/builder-implementation.md](references/builder-implementation.md)\n\n---\n\n## 最佳實踐\n\n涵蓋五項實踐：提供合理的預設值、使用語意化命名（UserScenarios）、Builder 之間的組合（OrderBuilder 組合 UserBuilder + ProductBuilder）、避免過度複雜化、統一管理測試資料（TestData 靜態類別）。\n\n> 完整最佳實踐與進階模式請參考 [references/best-practices-and-patterns.md](references/best-practices-and-patterns.md)\n\n---\n\n## 與其他模式的比較\n\n### Test Data Builder vs. Object Mother\n\n| 特性     | Test Data Builder           | Object Mother         |\n| -------- | --------------------------- | --------------------- |\n| 彈性     | 高度彈性，可針對測試調整 | 固定的測試資料     |\n| 可讀性   | 流暢介面，意圖明確       | 需要查看方法實作 |\n| 維護性   | 集中管理，易於修改       | 變更影響所有測試   |\n| 使用場景 | 單元測試、情境測試          | 簡單的整合測試        |\n\n### Test Data Builder vs. AutoFixture\n\n| 特性       | Test Data Builder       | AutoFixture               |\n| ---------- | ----------------------- | ------------------------- |\n| 控制度     | 完全控制物件建立     | 自動產生，控制度較低 |\n| 設定複雜度 | 需手動建立 Builder | 幾乎零設定             |\n| 測試意圖   | 非常明確             | 需額外說明           |\n| 適用時機   | 需要精確控制的測試      | 大量資料產生、匿名測試    |\n\n> **建議**：Test Data Builder 和 AutoFixture 可以相輔相成。簡單情境使用 AutoFixture，複雜情境或需明確意圖時使用 Builder Pattern。\n\n## 實戰範例\n\n請參考 `templates/` 目錄下的完整實作範例：\n\n- `user-builder-example.cs` - 基本 User Builder 實作\n- `advanced-builder-scenarios.cs` - 進階 Builder 組合與使用情境\n- `builder-with-theory.cs` - Builder 配合 xUnit Theory 的實務範例\n\n## 輸出格式\n\n- 產生 Builder 類別檔案（如 `UserBuilder.cs`、`ProductBuilder.cs`），放置於測試專案的 `Builders/` 目錄\n- 每個 Builder 包含預設值、`With*` 流暢方法、語意化靜態工廠方法與 `Build()` 方法\n- 若需要跨測試共用，產生 `TestData.cs` 靜態類別集中管理常用測試資料\n- 產生對應的測試類別檔案（`*Tests.cs`），示範 Builder 的使用方式\n\n## 參考資源\n\n### 原始文章\n\n本技能內容提煉自「老派軟體工程師的測試修練 - 30 天挑戰」系列文章：\n\n- **Day 10 - AutoFixture 基礎：自動產生測試資料** (Builder Pattern 概念)\n  - 鐵人賽文章：https://ithelp.ithome.com.tw/articles/10375018\n  - 範例程式碼：https://github.com/kevintsengtw/30Days_in_Testing_Samples/tree/main/day10\n\n### 延伸閱讀\n\n- **Test Data Builder 原始文章**：[Test Data Builders: an alternative to the Object Mother pattern](http://www.natpryce.com/articles/000714.html) by Nat Pryce\n- **Builder Pattern vs Object Mother**：[Test Data Builders and Object Mother: another look](https://www.javacodegeeks.com/2014/06/test-data-builders-and-object-mother-another-look.html)\n\n### 相關技能\n\n- `autofixture-basics` - 使用 AutoFixture 自動產生測試資料\n- `xunit-project-setup` - xUnit 測試專案的基礎設定\n- `test-naming-conventions` - 測試命名規範\n\n## 總結\n\nTest Data Builder Pattern 是撰寫可維護測試的重要技巧：\n\n- **使用時機**：測試物件有多個屬性、需重複使用測試資料、希望表達清晰意圖\n- **核心優勢**：提升可讀性、降低維護成本、增強表達力\n- **注意事項**：保持 Builder 簡單、提供合理預設值、使用語意化方法名稱","tags":["dotnet","testing","test","data","builder","pattern","agent","skills","kevintsengtw","agent-skills","ai-assisted-development","copilot-skills"],"capabilities":["skill","source-kevintsengtw","skill-dotnet-testing-test-data-builder-pattern","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-data-builder-pattern","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 (3,509 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.258Z","embedding":null,"createdAt":"2026-04-18T23:04:33.343Z","updatedAt":"2026-04-24T13:02:27.258Z","lastSeenAt":"2026-04-24T13:02:27.258Z","tsv":"'/2014/06/test-data-builders-and-object-mother-another-look.html)':361 '/articles/000714.html)':342 '/articles/10375018':320 '/kevintsengtw/30days_in_testing_samples/tree/main/day10':324 '1':68,137 '10':310 '2':74,140 '3':78,145 '30':98,306 '4':151 'advanced-builder-scenarios.cs':265 'age':97 'altern':334 'anadminus':149 'anoth':357 'aregularus':150 'autofixtur':223,228,249,252,311,364,367 'autofixture-bas':363 'basic':365 'build':127,152,162,291 'builder':6,10,17,31,32,49,56,60,82,130,135,168,177,193,200,221,227,235,247,254,263,267,270,277,283,286,300,314,328,332,346,353,383,396 'builder-with-theory.cs':269 'complex':43 'convent':378 'createdat':113 'csharp':84 'dark':106 'data':5,9,30,40,48,55,59,134,192,199,220,226,246,327,331,352,382 'datetime.now':114,116 'day':309 'doe':94,125 'dotnet':2 'dotnet-testing-test-data-builder-pattern':1 'email':95 'even':45 'fluent':34 'github.com':323 'github.com/kevintsengtw/30days_in_testing_samples/tree/main/day10':322 'interfac':35 'isact':111 'ithelp.ithome.com.tw':319 'ithelp.ithome.com.tw/articles/10375018':318 'john':93,124 'john@example.com':96 'languag':107 'look':358 'make':19 'mention':28 'modifiedat':115 'mother':37,64,71,196,202,338,350,356 'name':92,377 'nat':344 'new':90,100,103 'object':36,44,63,70,195,201,337,349,355 'orderbuild':179 'pattern':7,11,33,50,57,61,65,83,255,315,339,347,384 'prepar':41 'productbuild':182 'productbuilder.cs':281 'project':371 'pryce':345 'references/best-practices-and-patterns.md':188,189 'references/builder-implementation.md':170,171 'role':99 'set':102 'setup':372 'skill':24 'skill-dotnet-testing-test-data-builder-pattern' 'source-kevintsengtw' 'sure':20 'templat':258 'test':3,4,8,29,39,47,54,58,133,191,198,219,225,245,326,330,351,376,381 'test-naming-convent':375 'testdata':185 'testdata.cs':295 'tests.cs':298 'theme':105 'theori':165,273 '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' 'true':112 'tw':110 'use':22 'user':27,89,91,101,121,262 'user-builder-example.cs':260 'userbuild':156,181 'userbuilder.auser':122 'userbuilder.cs':280 'userscenario':176 'userset':104 'var':88,120 'vs':194,222,348 'whenev':25 'withnam':123 'withvalidemail':126 'www.javacodegeeks.com':360 'www.javacodegeeks.com/2014/06/test-data-builders-and-object-mother-another-look.html)':359 'www.natpryce.com':341 'www.natpryce.com/articles/000714.html)':340 'xunit':272,370,373 'xunit-project-setup':369 'zh':109 'zh-tw':108 '一個標準的':132 '主要解決以下問題':67 '之間的組合':178 '什麼是':53 '使用':142,366 '使用場景':215 '使用時機':386 '使用的範例':166 '使用語意化命名':175 '使用語意化方法名稱':399 '保持':395 '包含預設值':287 '匿名測試':243 '原始文章':303,329 '參考資源':302 '只設定測試關注的屬性':119 '可以相輔相成':250 '可讀性':207 '可針對測試調整':205 '和':248 '問題':85 '單一測試情境與配合':164 '單元測試':216 '固定測試資料的問題':69 '固定的測試資料':206 '基本':129,261 '基礎':312 '增強表達力':393 '大量資料產生':242 '天挑戰':307 '如':148,279 '完全控制物件建立':230 '完整':167 '完整實作指南':12 '完整最佳實踐與進階模式請參考':187 '實作':157,264 '實作指南':128 '實作與測試使用範例請參考':169 '實戰範例':256 '希望表達清晰意圖':389 '幾乎零設定':236 '延伸閱讀':325 '建議':244 '彈性':203 '情境測試':217 '意圖明確':118,209 '應包含':136 '控制度':229 '控制度較低':232 '提供合理的預設值':174 '提供合理預設值':398 '提供固定的測試物件':72 '提供有意義的預設建立者':147 '提升可讀性':391 '改善':117 '放置於測試專案的':282 '方法':153,163,292 '方法鏈來設定屬性':144 '易於修改':213 '是':62 '是撰寫可維護測試的重要技巧':385 '最佳實踐':172 '最終建立並回傳目標物件':154 '本技能內容提煉自':304 '核心優勢':390 '核心概念':52 '概念':316 '每個':285 '注意事項':394 '流暢介面':141,208 '流暢方法':160,289 '涵蓋五項實踐':173 '涵蓋完整':155 '涵蓋流暢介面':14 '測試命名規範':379 '測試專案的基礎設定':374 '測試意圖':237 '測試意圖不明確':75,87 '測試物件有多個屬性':387 '測試的關注點容易被大量屬性設定所掩蓋':77 '測試資料建構器模式':51 '為何需要':81 '為所有必要屬性提供合理的預設值':139 '特性':197,224 '產生':276,294 '產生對應的測試類別檔案':297 '當需要使用建構者模式建立可維護的測試資料或簡化複雜物件的測試準備時使用':13 '的使用方式':301 '的實務範例':274 '的改良版':66 '目錄':284 '目錄下的完整實作範例':259 '直接建立物件時':76 '相似的物件建立邏輯在多個測試中重複出現':80 '相關技能':362 '示範':299 '範例程式碼':321 '簡單':397 '簡單情境使用':251 '簡單的整合測試':218 '系列文章':308 '組合':180 '組合模式':18 '組合與使用情境':268 '結構':131 '統一管理測試資料':184 '維護性':211 '總結':380 '老派軟體工程師的測試修練':305 '自動產生':231 '自動產生測試資料':313,368 '與其他模式的比較':190 '若需要跨測試共用':293 '複雜情境或需明確意圖時使用':253 '設定複雜度':233 '語意化方法':15,146 '語意化靜態工廠方法':161 '語意化靜態工廠方法與':290 '請參考':257 '變更影響所有測試':214 '輸出格式':275 '進階':266 '過多參數設定':86 '適用時機':240 '避免過度複雜化':183 '配合':271 '重複程式碼':79 '鐵人賽文章':317 '降低維護成本':392 '集中管理':212 '難以針對特定測試情境調整':73 '需手動建立':234 '需要查看方法實作':210 '需要精確控制的測試':241 '需重複使用測試資料':388 '需額外說明':239 '靜態類別':186 '靜態類別集中管理常用測試資料':296 '非常明確':238 '預設值':138,158 '預設值設計與':16 '類別檔案':278 '高度彈性':204","prices":[{"id":"fd4560d2-cf70-4d72-a06a-b9f7f5cc6cf7","listingId":"9a998427-fb0a-4c17-a246-1950a91789d2","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:33.343Z"}],"sources":[{"listingId":"9a998427-fb0a-4c17-a246-1950a91789d2","source":"github","sourceId":"kevintsengtw/dotnet-testing-agent-skills/dotnet-testing-test-data-builder-pattern","sourceUrl":"https://github.com/kevintsengtw/dotnet-testing-agent-skills/tree/main/skills/dotnet-testing-test-data-builder-pattern","isPrimary":false,"firstSeenAt":"2026-04-18T23:04:33.343Z","lastSeenAt":"2026-04-24T13:02:27.258Z"}],"details":{"listingId":"9a998427-fb0a-4c17-a246-1950a91789d2","quickStartSnippet":null,"exampleRequest":null,"exampleResponse":null,"schema":null,"openapiUrl":null,"agentsTxtUrl":null,"citations":[],"useCases":[],"bestFor":[],"notFor":[],"kindDetails":{"org":"kevintsengtw","slug":"dotnet-testing-test-data-builder-pattern","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":"41e48597068c48f9dd6f187902d9a27e448b20da","skill_md_path":"skills/dotnet-testing-test-data-builder-pattern/SKILL.md","default_branch":"main","skill_tree_url":"https://github.com/kevintsengtw/dotnet-testing-agent-skills/tree/main/skills/dotnet-testing-test-data-builder-pattern"},"layout":"multi","source":"github","category":"dotnet-testing-agent-skills","frontmatter":{"name":"dotnet-testing-test-data-builder-pattern","description":"Test Data Builder Pattern 完整實作指南。當需要使用建構者模式建立可維護的測試資料或簡化複雜物件的測試準備時使用。涵蓋流暢介面、語意化方法、預設值設計與 Builder 組合模式。\nMake sure to use this skill whenever the user mentions test data builder, builder pattern, fluent interface, Object Mother, or test data preparation for complex objects, even if they don't explicitly ask for the builder pattern.\nKeywords: test data builder, builder pattern test, 測試資料建構器, object mother, fluent interface, 流暢介面, UserBuilder, ProductBuilder, .With(), .Build(), AUser(), 測試資料準備, 複雜物件建立, 語意化測試"},"skills_sh_url":"https://skills.sh/kevintsengtw/dotnet-testing-agent-skills/dotnet-testing-test-data-builder-pattern"},"updatedAt":"2026-04-24T13:02:27.258Z"}}