{"id":"8f674f33-0053-4633-89be-c8a0528048c3","shortId":"AYVrQu","kind":"skill","title":"dotnet-testing-autodata-xunit-integration","tagline":"AutoFixture 與 xUnit 整合完整指南。當需要使用 AutoData 或 InlineAutoData 簡化 xUnit 參數化測試資料準備時使用。涵蓋自訂 Customization 與測試資料屬性，提升測試可讀性與維護性。\nMake sure to use this skill whenever the user mentions AutoData, InlineAutoData, MemberAutoData, AutoFixture xUnit integration, or parameterized test data attr","description":"# AutoData 屬性家族：xUnit 與 AutoFixture 的整合應用\n\n## 概述\n\nAutoData 屬性家族是 `AutoFixture.Xunit2` 套件提供的功能，將 AutoFixture 的資料產生能力與 xUnit 的參數化測試整合，讓測試參數自動注入，大幅減少測試準備程式碼。\n\n### 核心特色\n\n1. **AutoData**：自動產生所有測試參數\n2. **InlineAutoData**：混合固定值與自動產生\n3. **MemberAutoData**：結合外部資料來源\n4. **CompositeAutoData**：多重資料來源整合\n5. **CollectionSizeAttribute**：控制集合產生數量\n\n## 安裝套件\n\n```xml\n<PackageReference Include=\"AutoFixture\" Version=\"4.18.1\" />\n<PackageReference Include=\"AutoFixture.Xunit2\" Version=\"4.18.1\" />\n```\n\n```bash\ndotnet add package AutoFixture.Xunit2\n```\n\n## AutoData：完全自動產生參數\n\n`AutoData` 是最基礎的屬性，自動為測試方法的所有參數產生測試資料。\n\n### 基本使用\n\n```csharp\nusing AutoFixture.Xunit2;\n\npublic class Person\n{\n    public Guid Id { get; set; }\n\n    [StringLength(10)]\n    public string Name { get; set; } = string.Empty;\n\n    [Range(18, 80)]\n    public int Age { get; set; }\n\n    public string Email { get; set; } = string.Empty;\n    public DateTime CreateTime { get; set; }\n}\n\n[Theory]\n[AutoData]\npublic void AutoData_應能自動產生所有參數(Person person, string message, int count)\n{\n    // Arrange & Act - 參數已由 AutoData 自動產生\n\n    // Assert\n    person.Should().NotBeNull();\n    person.Id.Should().NotBe(Guid.Empty);\n    person.Name.Should().HaveLength(10);     // 遵循 StringLength 限制\n    person.Age.Should().BeInRange(18, 80);   // 遵循 Range 限制\n    message.Should().NotBeNullOrEmpty();\n    count.Should().NotBe(0);\n}\n```\n\n### 透過 DataAnnotation 約束參數\n\n```csharp\n[Theory]\n[AutoData]\npublic void AutoData_透過DataAnnotation約束參數(\n    [StringLength(5, MinimumLength = 3)] string shortName,\n    [Range(1, 100)] int percentage,\n    Person person)\n{\n    // Assert\n    shortName.Length.Should().BeInRange(3, 5);\n    percentage.Should().BeInRange(1, 100);\n    person.Should().NotBeNull();\n}\n```\n\n## InlineAutoData：混合固定值與自動產生\n\n`InlineAutoData` 結合了 `InlineData` 的固定值特性與 `AutoData` 的自動產生功能。\n\n### 基本語法\n\n```csharp\n[Theory]\n[InlineAutoData(\"VIP客戶\", 1000)]\n[InlineAutoData(\"一般客戶\", 500)]\n[InlineAutoData(\"新客戶\", 100)]\npublic void InlineAutoData_混合固定值與自動產生(\n    string customerType,    // 對應第 1 個固定值\n    decimal creditLimit,    // 對應第 2 個固定值\n    Person person)          // 由 AutoFixture 產生\n{\n    // Arrange\n    var customer = new Customer\n    {\n        Person = person,\n        Type = customerType,\n        CreditLimit = creditLimit\n    };\n\n    // Assert\n    customer.Type.Should().Be(customerType);\n    customer.CreditLimit.Should().BeOneOf(1000, 500, 100);\n    customer.Person.Should().NotBeNull();\n}\n```\n\n### 參數順序一致性\n\n固定值的順序必須與方法參數順序一致：\n\n```csharp\n[Theory]\n[InlineAutoData(\"產品A\", 100)]  // 依序對應 name, price\n[InlineAutoData(\"產品B\", 200)]\npublic void InlineAutoData_參數順序一致性(\n    string name,        // 對應第 1 個固定值\n    decimal price,      // 對應第 2 個固定值\n    string description, // 由 AutoFixture 產生\n    Product product)    // 由 AutoFixture 產生\n{\n    // Assert\n    name.Should().BeOneOf(\"產品A\", \"產品B\");\n    price.Should().BeOneOf(100, 200);\n    description.Should().NotBeNullOrEmpty();\n    product.Should().NotBeNull();\n}\n```\n\n### 重要限制：只能使用編譯時常數\n\n```csharp\n// 正確：使用常數\n[InlineAutoData(\"VIP\", 100000)]\n[InlineAutoData(\"Premium\", 50000)]\n\n// 錯誤：不能使用變數\nprivate const decimal VipCreditLimit = 100000m;\n[InlineAutoData(\"VIP\", VipCreditLimit)]  // 編譯錯誤\n\n// 錯誤：不能使用運算式\n[InlineAutoData(\"VIP\", 100 * 1000)]  // 編譯錯誤\n```\n\n需要使用複雜資料時，應使用 `MemberAutoData`。\n\n## MemberAutoData：結合外部資料來源\n\n`MemberAutoData` 允許從類別的方法、屬性或欄位中獲取測試資料。\n\n### 使用靜態方法\n\n```csharp\npublic class MemberAutoDataTests\n{\n    public static IEnumerable<object[]> GetProductCategories()\n    {\n        yield return new object[] { \"3C產品\", \"TECH\" };\n        yield return new object[] { \"服飾配件\", \"FASHION\" };\n        yield return new object[] { \"居家生活\", \"HOME\" };\n        yield return new object[] { \"運動健身\", \"SPORTS\" };\n    }\n\n    [Theory]\n    [MemberAutoData(nameof(GetProductCategories))]\n    public void MemberAutoData_使用靜態方法資料(\n        string categoryName,   // 來自 GetProductCategories\n        string categoryCode,   // 來自 GetProductCategories\n        Product product)       // 由 AutoFixture 產生\n    {\n        // Arrange\n        var categorizedProduct = new CategorizedProduct\n        {\n            Product = product,\n            CategoryName = categoryName,\n            CategoryCode = categoryCode\n        };\n\n        // Assert\n        categorizedProduct.CategoryName.Should().Be(categoryName);\n        categorizedProduct.CategoryCode.Should().Be(categoryCode);\n        categorizedProduct.Product.Should().NotBeNull();\n    }\n}\n```\n\n### 使用靜態屬性\n\n```csharp\npublic static IEnumerable<object[]> StatusTransitions => new[]\n{\n    new object[] { OrderStatus.Created, OrderStatus.Confirmed },\n    new object[] { OrderStatus.Confirmed, OrderStatus.Shipped },\n    new object[] { OrderStatus.Shipped, OrderStatus.Delivered },\n    new object[] { OrderStatus.Delivered, OrderStatus.Completed }\n};\n\n[Theory]\n[MemberAutoData(nameof(StatusTransitions))]\npublic void MemberAutoData_使用靜態屬性_訂單狀態轉換(\n    OrderStatus fromStatus,\n    OrderStatus toStatus,\n    Order order)\n{\n    // Arrange\n    order.Status = fromStatus;\n\n    // Act\n    order.TransitionTo(toStatus);\n\n    // Assert\n    order.Status.Should().Be(toStatus);\n}\n```\n\n## 自訂 AutoData 屬性\n\n建立專屬的 AutoData 配置：\n\n### DomainAutoDataAttribute\n\n```csharp\npublic class DomainAutoDataAttribute : AutoDataAttribute\n{\n    public DomainAutoDataAttribute() : base(() => CreateFixture())\n    {\n    }\n\n    private static IFixture CreateFixture()\n    {\n        var fixture = new Fixture();\n\n        // 設定 Person 的自訂規則\n        fixture.Customize<Person>(composer => composer\n            .With(p => p.Age, () => Random.Shared.Next(18, 65))\n            .With(p => p.Email, () => $\"user{Random.Shared.Next(1000)}@example.com\")\n            .With(p => p.Name, () => $\"測試用戶{Random.Shared.Next(100)}\"));\n\n        // 設定 Product 的自訂規則\n        fixture.Customize<Product>(composer => composer\n            .With(p => p.Price, () => Random.Shared.Next(100, 10000))\n            .With(p => p.IsAvailable, true)\n            .With(p => p.Name, () => $\"產品{Random.Shared.Next(1000)}\"));\n\n        return fixture;\n    }\n}\n```\n\n### BusinessAutoDataAttribute\n\n```csharp\npublic class BusinessAutoDataAttribute : AutoDataAttribute\n{\n    public BusinessAutoDataAttribute() : base(() => CreateFixture())\n    {\n    }\n\n    private static IFixture CreateFixture()\n    {\n        var fixture = new Fixture();\n\n        // 設定 Order 的業務規則\n        fixture.Customize<Order>(composer => composer\n            .With(o => o.Status, OrderStatus.Created)\n            .With(o => o.Amount, () => Random.Shared.Next(1000, 50000))\n            .With(o => o.OrderNumber, () => $\"ORD{DateTime.Now:yyyyMMdd}{Random.Shared.Next(1000):D4}\"));\n\n        return fixture;\n    }\n}\n```\n\n### 使用自訂 AutoData\n\n```csharp\n[Theory]\n[DomainAutoData]\npublic void 使用DomainAutoData(Person person, Product product)\n{\n    person.Age.Should().BeInRange(18, 64);\n    person.Email.Should().EndWith(\"@example.com\");\n    product.IsAvailable.Should().BeTrue();\n}\n\n[Theory]\n[BusinessAutoData]\npublic void 使用BusinessAutoData(Order order)\n{\n    order.Status.Should().Be(OrderStatus.Created);\n    order.Amount.Should().BeInRange(1000, 49999);\n    order.OrderNumber.Should().StartWith(\"ORD\");\n}\n```\n\n## CompositeAutoData：多重資料來源整合\n\n透過繼承 `AutoDataAttribute` 並以反射合併多個 Fixture 的 Customizations，組合多個自訂 AutoData 配置：\n\n```csharp\n// 使用方式 - 自動套用 DomainAutoData + BusinessAutoData 的所有設定\n[Theory]\n[CompositeAutoData(typeof(DomainAutoDataAttribute), typeof(BusinessAutoDataAttribute))]\npublic void CompositeAutoData_整合多重資料來源(\n    Person person, Product product, Order order)\n{\n    person.Age.Should().BeInRange(18, 64);       // DomainAutoData 的設定\n    product.IsAvailable.Should().BeTrue();        // DomainAutoData 的設定\n    order.Status.Should().Be(OrderStatus.Created); // BusinessAutoData 的設定\n}\n```\n\n## CollectionSizeAttribute：控制集合大小\n\nAutoData 預設的集合大小是 3，可透過自訂 `CollectionSizeAttribute` 控制產生的集合元素數量。完整實作與使用方式請參考 [CollectionSizeAttribute 完整指南](references/collection-size-attribute.md)。\n\n## 外部測試資料整合\n\n整合 CSV、JSON 等外部資料來源與 MemberAutoData，同時保留 AutoFixture 自動產生其餘參數的能力。完整指南請參考 [外部測試資料整合](references/external-data-integration.md)。\n\n## 資料來源設計模式\n\n階層式資料組織與可重用資料集的設計模式，建立 `BaseTestData` 基底類別統一管理測試資料路徑。完整範例請參考 [資料來源設計模式](references/data-source-patterns.md)。\n\n## 與 Awesome Assertions 協作\n\n```csharp\n[Theory]\n[InlineAutoData(\"VIP\", 100000)]\n[InlineAutoData(\"Premium\", 50000)]\n[InlineAutoData(\"Regular\", 20000)]\npublic void AutoData與AwesomeAssertions協作_客戶等級驗證(\n    string customerLevel,\n    decimal expectedCreditLimit,\n    [Range(1000, 15000)] decimal orderAmount,\n    Customer customer,\n    Order order)\n{\n    // Arrange\n    customer.Type = customerLevel;\n    customer.CreditLimit = expectedCreditLimit;\n    order.Amount = orderAmount;\n\n    // Act\n    var canPlaceOrder = customer.CanPlaceOrder(order.Amount);\n    var discountRate = CalculateDiscount(customer.Type, order.Amount);\n\n    // Assert - 使用 Awesome Assertions 語法\n    customer.Type.Should().Be(customerLevel);\n    customer.CreditLimit.Should().Be(expectedCreditLimit);\n    customer.CreditLimit.Should().BePositive();\n\n    order.Amount.Should().BeInRange(1000m, 15000m);\n    canPlaceOrder.Should().BeTrue();\n    discountRate.Should().BeInRange(0m, 0.3m);\n}\n\nprivate static decimal CalculateDiscount(string customerType, decimal orderAmount)\n{\n    var baseDiscount = customerType switch\n    {\n        \"VIP\" => 0.15m,\n        \"Premium\" => 0.10m,\n        \"Regular\" => 0.05m,\n        _ => 0m\n    };\n\n    var largeOrderBonus = orderAmount > 30000m ? 0.05m : 0m;\n    return Math.Min(baseDiscount + largeOrderBonus, 0.3m);\n}\n```\n\n## 最佳實踐\n\n### 應該做\n\n1. **善用 DataAnnotation**\n   - 在參數上使用 `[StringLength]`、`[Range]` 約束資料範圍\n   - 確保產生的資料符合業務規則\n\n2. **建立可重用的自訂 AutoData**\n   - 為不同領域建立專屬的 AutoData 屬性\n   - 集中管理測試資料的產生規則\n\n3. **使用 MemberAutoData 處理複雜資料**\n   - 當 InlineAutoData 無法滿足需求時使用\n   - 支援變數、運算式和外部資料來源\n\n4. **組織測試資料來源**\n   - 建立階層式的資料來源結構\n   - 將相關資料集中管理\n\n### 應該避免\n\n1. **在 InlineAutoData 使用非常數值**\n   - InlineAutoData 只接受編譯時常數\n   - 需要動態值時改用 MemberAutoData\n\n2. **過度複雜的 CompositeAutoData**\n   - 避免組合過多的 AutoData 來源\n   - 保持配置的可理解性\n\n3. **忽略參數順序**\n   - InlineAutoData 的固定值必須與參數順序一致\n   - 錯誤的順序會導致型別不符\n\n## 程式碼範本\n\n請參考 [templates](./templates) 資料夾中的範例檔案：\n\n- [autodata-attributes.cs](./templates/autodata-attributes.cs) - AutoData 屬性家族使用範例\n- [external-data-integration.cs](./templates/external-data-integration.cs) - CSV/JSON 外部資料整合\n- [advanced-patterns.cs](./templates/advanced-patterns.cs) - 進階模式與 CollectionSizeAttribute\n\n## 與其他技能的關係\n\n- **autofixture-basics**：本技能的前置知識\n- **autofixture-customization**：自訂化策略可用於 AutoData 屬性\n- **autofixture-nsubstitute-integration**：下一步學習目標\n- **awesome-assertions-guide**：搭配使用提升測試可讀性\n\n## 輸出格式\n\n- 產生使用 `[Theory]` 搭配 `[AutoData]` 或 `[InlineAutoData]` 的測試方法\n- 產生自訂 `AutoDataAttribute` 衍生類別檔案（`*AutoDataAttribute.cs`）\n- 測試參數透過屬性注入，減少 Arrange 區段程式碼\n- 固定值參數置於方法簽章前方，自動產生參數置於後方\n- 搭配 DataAnnotation 約束參數範圍\n\n## 參考資源\n\n### 原始文章\n\n本技能內容提煉自「老派軟體工程師的測試修練 - 30 天挑戰」系列文章：\n\n- **Day 12 - 結合 AutoData：xUnit 與 AutoFixture 的整合應用**\n  - 鐵人賽文章：https://ithelp.ithome.com.tw/articles/10375296\n  - 範例程式碼：https://github.com/kevintsengtw/30Days_in_Testing_Samples/tree/main/day12\n\n### 官方文件\n\n- [AutoFixture Cheat Sheet - AutoData Theories](https://github.com/AutoFixture/AutoFixture/wiki/Cheat-Sheet#autodata-theories)\n- [AutoDataAttribute API Reference](https://autofixture.io/api/AutoFixture.Xunit.AutoDataAttribute.html)\n- [InlineAutoDataAttribute API Reference](https://autofixture.io/api/AutoFixture.Xunit.InlineAutoDataAttribute.html)\n- [CsvHelper 官方文件](https://joshclose.github.io/CsvHelper/)","tags":["dotnet","testing","autodata","xunit","integration","agent","skills","kevintsengtw","agent-skills","ai-assisted-development","copilot-skills","csharp"],"capabilities":["skill","source-kevintsengtw","skill-dotnet-testing-autodata-xunit-integration","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-autodata-xunit-integration","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 (11,399 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:25.993Z","embedding":null,"createdAt":"2026-04-18T23:04:22.553Z","updatedAt":"2026-04-24T13:02:25.993Z","lastSeenAt":"2026-04-24T13:02:25.993Z","tsv":"'/api/autofixture.xunit.autodataattribute.html)':966 '/api/autofixture.xunit.inlineautodataattribute.html)':972 '/articles/10375296':947 '/autofixture/autofixture/wiki/cheat-sheet#autodata-theories)':960 '/csvhelper/)':977 '/kevintsengtw/30days_in_testing_samples/tree/main/day12':951 '/templates':873 '/templates/advanced-patterns.cs':884 '/templates/autodata-attributes.cs':876 '/templates/external-data-integration.cs':880 '0':168 '0.05':803,810 '0.10':800 '0.15':797 '0.3':782,817 '0m':781,805,812 '1':62,186,199,230,284,821,850 '10':102,153 '100':187,200,222,261,270,308,340,523,534 '1000':216,259,341,516,545,580,589,626,735 '10000':535 '100000':321,719 '100000m':331 '1000m':775 '12':937 '15000':736 '15000m':776 '18':110,159,509,607,666 '2':65,235,289,829,858 '200':276,309 '20000':725 '3':68,182,195,683,836,865 '30':933 '30000m':809 '3c產品':365 '4':71,845 '49999':627 '5':74,180,196 '500':219,260 '50000':324,581,722 '64':608,667 '65':510 '80':111,160 'act':141,468,750 'add':81 'advanced-patterns.cs':883 'age':114 'api':962,968 'arrang':140,242,406,465,743,922 'assert':145,192,253,301,417,471,713,760,763,905 'attr':42 'autodata':4,12,32,43,50,63,84,86,129,132,143,174,177,209,476,479,594,640,681,831,833,862,877,896,912,939,956 'autodata-attributes.cs':875 'autodataattribut':486,553,634,917,961 'autodataattribute.cs':919 'autodata與awesomeassertions協作':728 'autofixtur':7,35,47,55,240,294,299,404,698,889,893,899,942,953 'autofixture-bas':888 'autofixture-custom':892 'autofixture-nsubstitute-integr':898 'autofixture.io':965,971 'autofixture.io/api/autofixture.xunit.autodataattribute.html)':964 'autofixture.io/api/autofixture.xunit.inlineautodataattribute.html)':970 'autofixture.xunit2':52,83,92 'awesom':712,762,904 'awesome-assertions-guid':903 'base':489,556 'basediscount':793,815 'basetestdata':706 'bash':79 'basic':890 'beinrang':158,194,198,606,625,665,774,780 'beoneof':258,303,307 'beposit':772 'betru':613,671,778 'businessautodata':615,646,677 'businessautodataattribut':548,552,555,653 'calculatediscount':757,787 'canplaceord':752 'canplaceorder.should':777 'categorizedproduct':408,410 'categorizedproduct.categorycode.should':421 'categorizedproduct.categoryname.should':418 'categorizedproduct.product.should':424 'categorycod':398,415,416,423 'categorynam':394,413,414,420 'cheat':954 'class':94,354,484,551 'collectionsizeattribut':75,679,685,688,886 'compos':503,504,528,529,570,571 'compositeautodata':72,631,649,656,860 'const':328 'count':139 'count.should':166 'createfixtur':490,494,557,561 'createtim':125 'creditlimit':233,251,252 'csharp':90,172,212,266,316,352,427,482,549,595,642,715 'csv':693 'csv/json':881 'csvhelper':973 'custom':19,244,246,638,739,740,894 'customer.canplaceorder':753 'customer.creditlimit':746 'customer.creditlimit.should':257,768,771 'customer.person.should':262 'customer.type':744,758 'customer.type.should':254,765 'customerlevel':731,745,767 'customertyp':228,250,256,789,794 'd4':590 'data':41 'dataannot':170,823,927 'datetim':124 'datetime.now':586 'day':936 'decim':232,286,329,732,737,786,790 'descript':292 'description.should':310 'discountr':756 'discountrate.should':779 'domainautodata':597,645,668,672 'domainautodataattribut':481,485,488,651 'dotnet':2,80 'dotnet-testing-autodata-xunit-integr':1 'email':119 'endwith':610 'example.com':517,611 'expectedcreditlimit':733,747,770 'external-data-integration.cs':879 'fashion':372 'fixtur':496,498,547,563,565,592,636 'fixture.customize':502,527,569 'fromstatus':460,467 'get':99,106,115,120,126 'getproductcategori':360,388,396,400 'github.com':950,959 'github.com/autofixture/autofixture/wiki/cheat-sheet#autodata-theories)':958 'github.com/kevintsengtw/30days_in_testing_samples/tree/main/day12':949 'guid':97,906 'guid.empty':150 'havelength':152 'home':378 'id':98 'ienumer':358,430 'ifixtur':493,560 'inlineautodata':14,33,66,203,205,214,217,220,225,268,274,279,319,322,332,338,717,720,723,841,852,854,867,914 'inlineautodataattribut':967 'inlinedata':207 'int':113,138,188 'integr':6,37,901 'ithelp.ithome.com.tw':946 'ithelp.ithome.com.tw/articles/10375296':945 'joshclose.github.io':976 'joshclose.github.io/csvhelper/)':975 'json':694 'largeorderbonus':807,816 'm':783,798,801,804,811,818 'make':22 'math.min':814 'memberautodata':34,69,345,346,348,386,391,451,456,696,838,857 'memberautodatatest':355 'mention':31 'messag':137 'message.should':164 'minimumlength':181 'name':105,272,282 'name.should':302 'nameof':387,452 'new':245,363,369,375,381,409,433,434,438,442,446,497,564 'notb':149,167 'notbenul':147,202,263,313,425 'notbenullorempti':165,311 'nsubstitut':900 'o':573,577,583 'o.amount':578 'o.ordernumber':584 'o.status':574 'object':359,364,370,376,382,431,435,439,443,447 'ord':585,630 'order':463,464,567,619,620,662,663,741,742 'order.amount':748,754,759 'order.amount.should':624,773 'order.ordernumber.should':628 'order.status':466 'order.status.should':472,621,674 'order.transitionto':469 'orderamount':738,749,791,808 'orderstatus':459,461 'orderstatus.completed':449 'orderstatus.confirmed':437,440 'orderstatus.created':436,575,623,676 'orderstatus.delivered':445,448 'orderstatus.shipped':441,444 'p':506,512,519,531,537,541 'p.age':507 'p.email':513 'p.isavailable':538 'p.name':520,542 'p.price':532 'packag':82 'parameter':39 'percentag':189 'percentage.should':197 'person':95,134,135,190,191,237,238,247,248,500,601,602,658,659 'person.age.should':157,605,664 'person.email.should':609 'person.id.should':148 'person.name.should':151 'person.should':146,201 'premium':323,721,799 'price':273,287 'price.should':306 'privat':327,491,558,784 'product':296,297,401,402,411,412,525,603,604,660,661 'product.isavailable.should':612,670 'product.should':312 'public':93,96,103,112,117,123,130,175,223,277,353,356,389,428,454,483,487,550,554,598,616,654,726 'random.shared.next':508,515,522,533,544,579,588 'rang':109,162,185,734,826 'refer':963,969 'references/collection-size-attribute.md':690 'references/data-source-patterns.md':710 'references/external-data-integration.md':702 'regular':724,802 'return':362,368,374,380,546,591,813 'set':100,107,116,121,127 'sheet':955 'shortnam':184 'shortname.length.should':193 'skill':27 'skill-dotnet-testing-autodata-xunit-integration' 'source-kevintsengtw' 'sport':384 'startwith':629 'static':357,429,492,559,785 'statustransit':432,453 'string':104,118,136,183,227,281,291,393,397,730,788 'string.empty':108,122 'stringlength':101,155,179,825 'sure':23 'switch':795 'tech':366 'templat':872 'test':3,40 'theori':128,173,213,267,385,450,596,614,648,716,910,957 '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' 'tostatus':462,470,474 'true':539 'type':249 'typeof':650,652 'use':25,91 'user':30,514 'var':243,407,495,562,751,755,792,806 'vip':320,333,339,718,796 'vipcreditlimit':330,334 'vip客戶':215 'void':131,176,224,278,390,455,599,617,655,727 'whenev':28 'xml':78 'xunit':5,9,16,36,45,57,940 'yield':361,367,373,379 'yyyymmdd':587 '一般客戶':218 '下一步學習目標':902 '不能使用變數':326 '不能使用運算式':337 '並以反射合併多個':635 '使用':761,837 '使用businessautodata':618 '使用domainautodata':600 '使用常數':318 '使用方式':643 '使用自訂':593 '使用靜態屬性':426,457 '使用靜態方法':351 '使用靜態方法資料':392 '使用非常數值':853 '來源':863 '來自':395,399 '依序對應':271 '保持配置的可理解性':864 '個固定值':231,236,285,290 '允許從類別的方法':349 '區段程式碼':923 '協作':714 '原始文章':930 '參數化測試資料準備時使用':17 '參數已由':142 '參數順序一致性':264,280 '參考資源':929 '只接受編譯時常數':855 '只能使用編譯時常數':315 '可透過自訂':684 '同時保留':697 '善用':822 '固定值參數置於方法簽章前方':924 '固定值的順序必須與方法參數順序一致':265 '在':851 '在參數上使用':824 '基底類別統一管理測試資料路徑':707 '基本使用':89 '基本語法':211 '外部測試資料整合':691,701 '外部資料整合':882 '多重資料來源整合':73,632 '大幅減少測試準備程式碼':60 '天挑戰':934 '套件提供的功能':53 '安裝套件':77 '完全自動產生參數':85 '完整實作與使用方式請參考':687 '完整指南':689 '完整指南請參考':700 '完整範例請參考':708 '官方文件':952,974 '客戶等級驗證':729 '將':54 '將相關資料集中管理':848 '對應第':229,234,283,288 '居家生活':377 '屬性':477,834,897 '屬性家族':44 '屬性家族使用範例':878 '屬性家族是':51 '屬性或欄位中獲取測試資料':350 '建立':705 '建立可重用的自訂':830 '建立專屬的':478 '建立階層式的資料來源結構':847 '忽略參數順序':866 '應使用':344 '應能自動產生所有參數':133 '應該做':820 '應該避免':849 '或':13,913 '控制產生的集合元素數量':686 '控制集合大小':680 '控制集合產生數量':76 '提升測試可讀性與維護性':21 '搭配':911,926 '搭配使用提升測試可讀性':907 '支援變數':843 '整合':692 '整合多重資料來源':657 '整合完整指南':10 '新客戶':221 '是最基礎的屬性':87 '最佳實踐':819 '服飾配件':371 '本技能內容提煉自':931 '本技能的前置知識':891 '核心特色':61 '概述':49 '正確':317 '涵蓋自訂':18 '混合固定值與自動產生':67,204,226 '減少':921 '測試參數透過屬性注入':920 '測試用戶':521 '為不同領域建立專屬的':832 '無法滿足需求時使用':842 '產品':543 '產品a':269,304 '產品b':275,305 '產生':241,295,300,405 '產生使用':909 '產生自訂':916 '由':239,293,298,403 '當':840 '當需要使用':11 '的':637 '的參數化測試整合':58 '的固定值必須與參數順序一致':868 '的固定值特性與':208 '的所有設定':647 '的整合應用':48,943 '的業務規則':568 '的測試方法':915 '的自動產生功能':210 '的自訂規則':501,526 '的設定':669,673,678 '的資料產生能力與':56 '確保產生的資料符合業務規則':828 '程式碼範本':870 '等外部資料來源與':695 '範例程式碼':948 '簡化':15 '系列文章':935 '約束參數':171 '約束參數範圍':928 '約束資料範圍':827 '組合多個自訂':639 '組織測試資料來源':846 '結合':938 '結合了':206 '結合外部資料來源':70,347 '編譯錯誤':335,342 '老派軟體工程師的測試修練':932 '自動套用':644 '自動為測試方法的所有參數產生測試資料':88 '自動產生':144 '自動產生其餘參數的能力':699 '自動產生參數置於後方':925 '自動產生所有測試參數':64 '自訂':475 '自訂化策略可用於':895 '與':8,46,711,941 '與其他技能的關係':887 '與測試資料屬性':20 '處理複雜資料':839 '衍生類別檔案':918 '訂單狀態轉換':458 '設定':499,524,566 '語法':764 '請參考':871 '讓測試參數自動注入':59 '資料來源設計模式':703,709 '資料夾中的範例檔案':874 '輸出格式':908 '透過':169 '透過dataannotation約束參數':178 '透過繼承':633 '進階模式與':885 '運動健身':383 '運算式和外部資料來源':844 '過度複雜的':859 '遵循':154,161 '避免組合過多的':861 '配置':480,641 '重要限制':314 '錯誤':325,336 '錯誤的順序會導致型別不符':869 '鐵人賽文章':944 '限制':156,163 '階層式資料組織與可重用資料集的設計模式':704 '集中管理測試資料的產生規則':835 '需要使用複雜資料時':343 '需要動態值時改用':856 '預設的集合大小是':682","prices":[{"id":"06811f8c-fbc1-4dd3-ac58-5d9bad232740","listingId":"8f674f33-0053-4633-89be-c8a0528048c3","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:22.553Z"}],"sources":[{"listingId":"8f674f33-0053-4633-89be-c8a0528048c3","source":"github","sourceId":"kevintsengtw/dotnet-testing-agent-skills/dotnet-testing-autodata-xunit-integration","sourceUrl":"https://github.com/kevintsengtw/dotnet-testing-agent-skills/tree/main/skills/dotnet-testing-autodata-xunit-integration","isPrimary":false,"firstSeenAt":"2026-04-18T23:04:22.553Z","lastSeenAt":"2026-04-24T13:02:25.993Z"}],"details":{"listingId":"8f674f33-0053-4633-89be-c8a0528048c3","quickStartSnippet":null,"exampleRequest":null,"exampleResponse":null,"schema":null,"openapiUrl":null,"agentsTxtUrl":null,"citations":[],"useCases":[],"bestFor":[],"notFor":[],"kindDetails":{"org":"kevintsengtw","slug":"dotnet-testing-autodata-xunit-integration","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":"ca8f3ae8589d61574994e4575e8e98f59281bee8","skill_md_path":"skills/dotnet-testing-autodata-xunit-integration/SKILL.md","default_branch":"main","skill_tree_url":"https://github.com/kevintsengtw/dotnet-testing-agent-skills/tree/main/skills/dotnet-testing-autodata-xunit-integration"},"layout":"multi","source":"github","category":"dotnet-testing-agent-skills","frontmatter":{"name":"dotnet-testing-autodata-xunit-integration","description":"AutoFixture 與 xUnit 整合完整指南。當需要使用 AutoData 或 InlineAutoData 簡化 xUnit 參數化測試資料準備時使用。涵蓋自訂 Customization 與測試資料屬性，提升測試可讀性與維護性。\nMake sure to use this skill whenever the user mentions AutoData, InlineAutoData, MemberAutoData, AutoFixture xUnit integration, or parameterized test data attributes, even if they don't explicitly ask for AutoData guidance.\nKeywords: AutoData, InlineAutoData, AutoFixture xUnit, [AutoData], [InlineAutoData], AutoDataAttribute, ICustomization, DataAttribute, 參數化測試, Theory AutoData, MemberAutoData, 測試資料屬性, fixture.Customize"},"skills_sh_url":"https://skills.sh/kevintsengtw/dotnet-testing-agent-skills/dotnet-testing-autodata-xunit-integration"},"updatedAt":"2026-04-24T13:02:25.993Z"}}