[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M6ADEA0X8DPARRGZF73DJ88J":3,"skill-same:01M6ADEA0X8DPARRGZF73DJ88J":94},{"skillNo":4,"name":5,"nameZh":6,"description":7,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":16,"categories":17,"keywords":23,"publishedAt":37,"linkOnly":38,"markdownContent":39,"markdownBody":40,"frontMatter":41,"refName":42,"commitSha":43,"skillDirectory":44,"forksCount":45,"repositoryHtmlUrl":46,"repositoryHomepageUrl":47,"ownerHtmlUrl":48,"ownerBlogUrl":49,"ownerDescription":50,"updatedAt":51,"install":52,"resources":65},"01M6ADEA0X8DPARRGZF73DJ88J","csharp-mstest",null,"Get best practices for MSTest 3.x\u002F4.x unit testing, including modern assertion APIs and data-driven tests","github\u002Fawesome-copilot","github","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F9919?v=4","01M6AC83DS133TPXFSP1DHNCC6","GitHub","01M6AD3PBDYPK7NVFJNJ66Y8RS",41081,"MIT","https:\u002F\u002Fgithub.com\u002Fgithub\u002Fawesome-copilot\u002Fblob\u002Fmain\u002Fskills\u002Fcsharp-mstest\u002FSKILL.md",[18],{"categoryNo":19,"categoryName":20,"taxonomyType":21,"taxonomyTypeDesc":22},"01JBSEEDCAT000000000000008","测试与质量","SCENARIO","使用场景",[24,25,26,27,28,29,30,31,32,33,34,35,36],"mstest","csharp","csharp mstest","testing","best practices","data","unit testing","get","tests","driven","unit","for","data-driven","2026-11-10 10:12:30",false,"---\nname: csharp-mstest\ndescription: 'Get best practices for MSTest 3.x\u002F4.x unit testing, including modern assertion APIs and data-driven tests'\n---\n\n# MSTest Best Practices (MSTest 3.x\u002F4.x)\n\nYour goal is to help me write effective unit tests with modern MSTest, using current APIs and best practices.\n\n## Project Setup\n\n- Use a separate test project with naming convention `[ProjectName].Tests`\n- Reference MSTest 3.x+ NuGet packages (includes analyzers)\n- Consider using MSTest.Sdk for simplified project setup\n- Run tests with `dotnet test`\n\n## Test Class Structure\n\n- Use `[TestClass]` attribute for test classes\n- **Seal test classes by default** for performance and design clarity\n- Use `[TestMethod]` for test methods (prefer over `[DataTestMethod]`)\n- Follow Arrange-Act-Assert (AAA) pattern\n- Name tests using pattern `MethodName_Scenario_ExpectedBehavior`\n\n```csharp\n[TestClass]\npublic sealed class CalculatorTests\n{\n    [TestMethod]\n    public void Add_TwoPositiveNumbers_ReturnsSum()\n    {\n        \u002F\u002F Arrange\n        var calculator = new Calculator();\n\n        \u002F\u002F Act\n        var result = calculator.Add(2, 3);\n\n        \u002F\u002F Assert\n        Assert.AreEqual(5, result);\n    }\n}\n```\n\n## Test Lifecycle\n\n- **Prefer constructors over `[TestInitialize]`** - enables `readonly` fields and follows standard C# patterns\n- Use `[TestCleanup]` for cleanup that must run even if test fails\n- Combine constructor with async `[TestInitialize]` when async setup is needed\n\n```csharp\n[TestClass]\npublic sealed class ServiceTests\n{\n    private readonly MyService _service;  \u002F\u002F readonly enabled by constructor\n\n    public ServiceTests()\n    {\n        _service = new MyService();\n    }\n\n    [TestInitialize]\n    public async Task InitAsync()\n    {\n        \u002F\u002F Use for async initialization only\n        await _service.WarmupAsync();\n    }\n\n    [TestCleanup]\n    public void Cleanup() => _service.Reset();\n}\n```\n\n### Execution Order\n\n1. **Assembly Initialization** - `[AssemblyInitialize]` (once per test assembly)\n2. **Class Initialization** - `[ClassInitialize]` (once per test class)\n3. **Test Initialization** (for every test method):\n   1. Constructor\n   2. Set `TestContext` property\n   3. `[TestInitialize]`\n4. **Test Execution** - test method runs\n5. **Test Cleanup** (for every test method):\n   1. `[TestCleanup]`\n   2. `DisposeAsync` (if implemented)\n   3. `Dispose` (if implemented)\n6. **Class Cleanup** - `[ClassCleanup]` (once per test class)\n7. **Assembly Cleanup** - `[AssemblyCleanup]` (once per test assembly)\n\n## Modern Assertion APIs\n\nMSTest provides three assertion classes: `Assert`, `StringAssert`, and `CollectionAssert`.\n\n### Assert Class - Core Assertions\n\n```csharp\n\u002F\u002F Equality\nAssert.AreEqual(expected, actual);\nAssert.AreNotEqual(notExpected, actual);\nAssert.AreSame(expectedObject, actualObject);      \u002F\u002F Reference equality\nAssert.AreNotSame(notExpectedObject, actualObject);\n\n\u002F\u002F Null checks\nAssert.IsNull(value);\nAssert.IsNotNull(value);\n\n\u002F\u002F Boolean\nAssert.IsTrue(condition);\nAssert.IsFalse(condition);\n\n\u002F\u002F Fail\u002FInconclusive\nAssert.Fail(\"Test failed due to...\");\nAssert.Inconclusive(\"Test cannot be completed because...\");\n```\n\n### Exception Testing (Prefer over `[ExpectedException]`)\n\n```csharp\n\u002F\u002F Assert.Throws - matches TException or derived types\nvar ex = Assert.Throws\u003CArgumentException>(() => Method(null));\nAssert.AreEqual(\"Value cannot be null.\", ex.Message);\n\n\u002F\u002F Assert.ThrowsExactly - matches exact type only\nvar ex = Assert.ThrowsExactly\u003CInvalidOperationException>(() => Method());\n\n\u002F\u002F Async versions\nvar ex = await Assert.ThrowsAsync\u003CHttpRequestException>(async () => await client.GetAsync(url));\nvar ex = await Assert.ThrowsExactlyAsync\u003CInvalidOperationException>(async () => await Method());\n```\n\n### Collection Assertions (Assert class)\n\n```csharp\nAssert.Contains(expectedItem, collection);\nAssert.DoesNotContain(unexpectedItem, collection);\nAssert.ContainsSingle(collection);  \u002F\u002F exactly one element\nAssert.HasCount(5, collection);\nAssert.IsEmpty(collection);\nAssert.IsNotEmpty(collection);\n```\n\n### String Assertions (Assert class)\n\n```csharp\nAssert.Contains(\"expected\", actualString);\nAssert.StartsWith(\"prefix\", actualString);\nAssert.EndsWith(\"suffix\", actualString);\nAssert.DoesNotStartWith(\"prefix\", actualString);\nAssert.DoesNotEndWith(\"suffix\", actualString);\nAssert.MatchesRegex(@\"\\d{3}-\\d{4}\", phoneNumber);\nAssert.DoesNotMatchRegex(@\"\\d+\", textOnly);\n```\n\n### Comparison Assertions\n\n```csharp\nAssert.IsGreaterThan(lowerBound, actual);\nAssert.IsGreaterThanOrEqualTo(lowerBound, actual);\nAssert.IsLessThan(upperBound, actual);\nAssert.IsLessThanOrEqualTo(upperBound, actual);\nAssert.IsInRange(actual, low, high);\nAssert.IsPositive(number);\nAssert.IsNegative(number);\n```\n\n### Type Assertions\n\n```csharp\n\u002F\u002F MSTest 3.x - uses out parameter\nAssert.IsInstanceOfType\u003CMyClass>(obj, out var typed);\ntyped.DoSomething();\n\n\u002F\u002F MSTest 4.x - returns typed result directly\nvar typed = Assert.IsInstanceOfType\u003CMyClass>(obj);\ntyped.DoSomething();\n\nAssert.IsNotInstanceOfType\u003CWrongType>(obj);\n```\n\n### Assert.That (MSTest 4.0+)\n\n```csharp\nAssert.That(result.Count > 0);  \u002F\u002F Auto-captures expression in failure message\n```\n\n### StringAssert Class\n\n> **Note:** Prefer `Assert` class equivalents when available (e.g., `Assert.Contains(\"expected\", actual)` over `StringAssert.Contains(actual, \"expected\")`).\n\n```csharp\nStringAssert.Contains(actualString, \"expected\");\nStringAssert.StartsWith(actualString, \"prefix\");\nStringAssert.EndsWith(actualString, \"suffix\");\nStringAssert.Matches(actualString, new Regex(@\"\\d{3}-\\d{4}\"));\nStringAssert.DoesNotMatch(actualString, new Regex(@\"\\d+\"));\n```\n\n### CollectionAssert Class\n\n> **Note:** Prefer `Assert` class equivalents when available (e.g., `Assert.Contains`).\n\n```csharp\n\u002F\u002F Containment\nCollectionAssert.Contains(collection, expectedItem);\nCollectionAssert.DoesNotContain(collection, unexpectedItem);\n\n\u002F\u002F Equality (same elements, same order)\nCollectionAssert.AreEqual(expectedCollection, actualCollection);\nCollectionAssert.AreNotEqual(unexpectedCollection, actualCollection);\n\n\u002F\u002F Equivalence (same elements, any order)\nCollectionAssert.AreEquivalent(expectedCollection, actualCollection);\nCollectionAssert.AreNotEquivalent(unexpectedCollection, actualCollection);\n\n\u002F\u002F Subset checks\nCollectionAssert.IsSubsetOf(subset, superset);\nCollectionAssert.IsNotSubsetOf(notSubset, collection);\n\n\u002F\u002F Element validation\nCollectionAssert.AllItemsAreInstancesOfType(collection, typeof(MyClass));\nCollectionAssert.AllItemsAreNotNull(collection);\nCollectionAssert.AllItemsAreUnique(collection);\n```\n\n## Data-Driven Tests\n\n### DataRow\n\n```csharp\n[TestMethod]\n[DataRow(1, 2, 3)]\n[DataRow(0, 0, 0, DisplayName = \"Zeros\")]\n[DataRow(-1, 1, 0, IgnoreMessage = \"Known issue #123\")]  \u002F\u002F MSTest 3.8+\npublic void Add_ReturnsSum(int a, int b, int expected)\n{\n    Assert.AreEqual(expected, Calculator.Add(a, b));\n}\n```\n\n### DynamicData\n\nThe data source can return any of the following types:\n\n- `IEnumerable\u003C(T1, T2, ...)>` (ValueTuple) - **preferred**, provides type safety (MSTest 3.7+)\n- `IEnumerable\u003CTuple\u003CT1, T2, ...>>` - provides type safety\n- `IEnumerable\u003CTestDataRow>` - provides type safety plus control over test metadata (display name, categories)\n- `IEnumerable\u003Cobject[]>` - **least preferred**, no type safety\n\n> **Note:** When creating new test data methods, prefer `ValueTuple` or `TestDataRow` over `IEnumerable\u003Cobject[]>`. The `object[]` approach provides no compile-time type checking and can lead to runtime errors from type mismatches.\n\n```csharp\n[TestMethod]\n[DynamicData(nameof(TestData))]\npublic void DynamicTest(int a, int b, int expected)\n{\n    Assert.AreEqual(expected, Calculator.Add(a, b));\n}\n\n\u002F\u002F ValueTuple - preferred (MSTest 3.7+)\npublic static IEnumerable\u003C(int a, int b, int expected)> TestData =>\n[\n    (1, 2, 3),\n    (0, 0, 0),\n];\n\n\u002F\u002F TestDataRow - when you need custom display names or metadata\npublic static IEnumerable\u003CTestDataRow\u003C(int a, int b, int expected)>> TestDataWithMetadata =>\n[\n    new((1, 2, 3)) { DisplayName = \"Positive numbers\" },\n    new((0, 0, 0)) { DisplayName = \"Zeros\" },\n    new((-1, 1, 0)) { DisplayName = \"Mixed signs\", IgnoreMessage = \"Known issue #123\" },\n];\n\n\u002F\u002F IEnumerable\u003Cobject[]> - avoid for new code (no type safety)\npublic static IEnumerable\u003Cobject[]> LegacyTestData =>\n[\n    [1, 2, 3],\n    [0, 0, 0],\n];\n```\n\n## TestContext\n\nThe `TestContext` class provides test run information, cancellation support, and output methods.\nSee [TestContext documentation](https:\u002F\u002Flearn.microsoft.com\u002Fdotnet\u002Fcore\u002Ftesting\u002Funit-testing-mstest-writing-tests-testcontext) for complete reference.\n\n### Accessing TestContext\n\n```csharp\n\u002F\u002F Property (MSTest suppresses CS8618 - don't use nullable or = null!)\npublic TestContext TestContext { get; set; }\n\n\u002F\u002F Constructor injection (MSTest 3.6+) - preferred for immutability\n[TestClass]\npublic sealed class MyTests\n{\n    private readonly TestContext _testContext;\n\n    public MyTests(TestContext testContext)\n    {\n        _testContext = testContext;\n    }\n}\n\n\u002F\u002F Static methods receive it as parameter\n[ClassInitialize]\npublic static void ClassInit(TestContext context) { }\n\n\u002F\u002F Optional for cleanup methods (MSTest 3.6+)\n[ClassCleanup]\npublic static void ClassCleanup(TestContext context) { }\n\n[AssemblyCleanup]\npublic static void AssemblyCleanup(TestContext context) { }\n```\n\n### Cancellation Token\n\nAlways use `TestContext.CancellationToken` for cooperative cancellation with `[Timeout]`:\n\n```csharp\n[TestMethod]\n[Timeout(5000)]\npublic async Task LongRunningTest()\n{\n    await _httpClient.GetAsync(url, TestContext.CancellationToken);\n}\n```\n\n### Test Run Properties\n\n```csharp\nTestContext.TestName              \u002F\u002F Current test method name\nTestContext.TestDisplayName       \u002F\u002F Display name (3.7+)\nTestContext.CurrentTestOutcome    \u002F\u002F Pass\u002FFail\u002FInProgress\nTestContext.TestData              \u002F\u002F Parameterized test data (3.7+, in TestInitialize\u002FCleanup)\nTestContext.TestException         \u002F\u002F Exception if test failed (3.7+, in TestCleanup)\nTestContext.DeploymentDirectory   \u002F\u002F Directory with deployment items\n```\n\n### Output and Result Files\n\n```csharp\n\u002F\u002F Write to test output (useful for debugging)\nTestContext.WriteLine(\"Processing item {0}\", itemId);\n\n\u002F\u002F Attach files to test results (logs, screenshots)\nTestContext.AddResultFile(screenshotPath);\n\n\u002F\u002F Store\u002Fretrieve data across test methods\nTestContext.Properties[\"SharedKey\"] = computedValue;\n```\n\n## Advanced Features\n\n### Retry for Flaky Tests (MSTest 3.9+)\n\n```csharp\n[TestMethod]\n[Retry(3)]\npublic void FlakyTest() { }\n```\n\n### Conditional Execution (MSTest 3.10+)\n\nSkip or run tests based on OS or CI environment:\n\n```csharp\n\u002F\u002F OS-specific tests\n[TestMethod]\n[OSCondition(OperatingSystems.Windows)]\npublic void WindowsOnlyTest() { }\n\n[TestMethod]\n[OSCondition(OperatingSystems.Linux | OperatingSystems.MacOS)]\npublic void UnixOnlyTest() { }\n\n[TestMethod]\n[OSCondition(ConditionMode.Exclude, OperatingSystems.Windows)]\npublic void SkipOnWindowsTest() { }\n\n\u002F\u002F CI environment tests\n[TestMethod]\n[CICondition]  \u002F\u002F Runs only in CI (default: ConditionMode.Include)\npublic void CIOnlyTest() { }\n\n[TestMethod]\n[CICondition(ConditionMode.Exclude)]  \u002F\u002F Skips in CI, runs locally\npublic void LocalOnlyTest() { }\n```\n\n### Parallelization\n\n```csharp\n\u002F\u002F Assembly level\n[assembly: Parallelize(Workers = 4, Scope = ExecutionScope.MethodLevel)]\n\n\u002F\u002F Disable for specific class\n[TestClass]\n[DoNotParallelize]\npublic sealed class SequentialTests { }\n```\n\n### Work Item Traceability (MSTest 3.8+)\n\nLink tests to work items for traceability in test reports:\n\n```csharp\n\u002F\u002F Azure DevOps work items\n[TestMethod]\n[WorkItem(12345)]  \u002F\u002F Links to work item #12345\npublic void Feature_Scenario_ExpectedBehavior() { }\n\n\u002F\u002F Multiple work items\n[TestMethod]\n[WorkItem(12345)]\n[WorkItem(67890)]\npublic void Feature_CoversMultipleRequirements() { }\n\n\u002F\u002F GitHub issues (MSTest 3.8+)\n[TestMethod]\n[GitHubWorkItem(\"https:\u002F\u002Fgithub.com\u002Fowner\u002Frepo\u002Fissues\u002F42\")]\npublic void BugFix_Issue42_IsResolved() { }\n```\n\nWork item associations appear in test results and can be used for:\n- Tracing test coverage to requirements\n- Linking bug fixes to regression tests\n- Generating traceability reports in CI\u002FCD pipelines\n\n## Common Mistakes to Avoid\n\n```csharp\n\u002F\u002F ❌ Wrong argument order\nAssert.AreEqual(actual, expected);\n\u002F\u002F ✅ Correct\nAssert.AreEqual(expected, actual);\n\n\u002F\u002F ❌ Using ExpectedException (obsolete)\n[ExpectedException(typeof(ArgumentException))]\n\u002F\u002F ✅ Use Assert.Throws\nAssert.Throws\u003CArgumentException>(() => Method());\n\n\u002F\u002F ❌ Using LINQ Single() - unclear exception\nvar item = items.Single();\n\u002F\u002F ✅ Use ContainsSingle - better failure message\nvar item = Assert.ContainsSingle(items);\n\n\u002F\u002F ❌ Hard cast - unclear exception\nvar handler = (MyHandler)result;\n\u002F\u002F ✅ Type assertion - shows actual type on failure\nvar handler = Assert.IsInstanceOfType\u003CMyHandler>(result);\n\n\u002F\u002F ❌ Ignoring cancellation token\nawait client.GetAsync(url, CancellationToken.None);\n\u002F\u002F ✅ Flow test cancellation\nawait client.GetAsync(url, TestContext.CancellationToken);\n\n\u002F\u002F ❌ Making TestContext nullable - leads to unnecessary null checks\npublic TestContext? TestContext { get; set; }\n\u002F\u002F ❌ Using null! - MSTest already suppresses CS8618 for this property\npublic TestContext TestContext { get; set; } = null!;\n\u002F\u002F ✅ Declare without nullable or initializer - MSTest handles the warning\npublic TestContext TestContext { get; set; }\n```\n\n## Test Organization\n\n- Group tests by feature or component\n- Use `[TestCategory(\"Category\")]` for filtering\n- Use `[TestProperty(\"Name\", \"Value\")]` for custom metadata (e.g., `[TestProperty(\"Bug\", \"12345\")]`)\n- Use `[Priority(1)]` for critical tests\n- Enable relevant MSTest analyzers (MSTEST0020 for constructor preference)\n\n## Mocking and Isolation\n\n- Use Moq or NSubstitute for mocking dependencies\n- Use interfaces to facilitate mocking\n- Mock dependencies to isolate units under test\n","# MSTest Best Practices (MSTest 3.x\u002F4.x)\n\nYour goal is to help me write effective unit tests with modern MSTest, using current APIs and best practices.\n\n## Project Setup\n\n- Use a separate test project with naming convention `[ProjectName].Tests`\n- Reference MSTest 3.x+ NuGet packages (includes analyzers)\n- Consider using MSTest.Sdk for simplified project setup\n- Run tests with `dotnet test`\n\n## Test Class Structure\n\n- Use `[TestClass]` attribute for test classes\n- **Seal test classes by default** for performance and design clarity\n- Use `[TestMethod]` for test methods (prefer over `[DataTestMethod]`)\n- Follow Arrange-Act-Assert (AAA) pattern\n- Name tests using pattern `MethodName_Scenario_ExpectedBehavior`\n\n```csharp\n[TestClass]\npublic sealed class CalculatorTests\n{\n    [TestMethod]\n    public void Add_TwoPositiveNumbers_ReturnsSum()\n    {\n        \u002F\u002F Arrange\n        var calculator = new Calculator();\n\n        \u002F\u002F Act\n        var result = calculator.Add(2, 3);\n\n        \u002F\u002F Assert\n        Assert.AreEqual(5, result);\n    }\n}\n```\n\n## Test Lifecycle\n\n- **Prefer constructors over `[TestInitialize]`** - enables `readonly` fields and follows standard C# patterns\n- Use `[TestCleanup]` for cleanup that must run even if test fails\n- Combine constructor with async `[TestInitialize]` when async setup is needed\n\n```csharp\n[TestClass]\npublic sealed class ServiceTests\n{\n    private readonly MyService _service;  \u002F\u002F readonly enabled by constructor\n\n    public ServiceTests()\n    {\n        _service = new MyService();\n    }\n\n    [TestInitialize]\n    public async Task InitAsync()\n    {\n        \u002F\u002F Use for async initialization only\n        await _service.WarmupAsync();\n    }\n\n    [TestCleanup]\n    public void Cleanup() => _service.Reset();\n}\n```\n\n### Execution Order\n\n1. **Assembly Initialization** - `[AssemblyInitialize]` (once per test assembly)\n2. **Class Initialization** - `[ClassInitialize]` (once per test class)\n3. **Test Initialization** (for every test method):\n   1. Constructor\n   2. Set `TestContext` property\n   3. `[TestInitialize]`\n4. **Test Execution** - test method runs\n5. **Test Cleanup** (for every test method):\n   1. `[TestCleanup]`\n   2. `DisposeAsync` (if implemented)\n   3. `Dispose` (if implemented)\n6. **Class Cleanup** - `[ClassCleanup]` (once per test class)\n7. **Assembly Cleanup** - `[AssemblyCleanup]` (once per test assembly)\n\n## Modern Assertion APIs\n\nMSTest provides three assertion classes: `Assert`, `StringAssert`, and `CollectionAssert`.\n\n### Assert Class - Core Assertions\n\n```csharp\n\u002F\u002F Equality\nAssert.AreEqual(expected, actual);\nAssert.AreNotEqual(notExpected, actual);\nAssert.AreSame(expectedObject, actualObject);      \u002F\u002F Reference equality\nAssert.AreNotSame(notExpectedObject, actualObject);\n\n\u002F\u002F Null checks\nAssert.IsNull(value);\nAssert.IsNotNull(value);\n\n\u002F\u002F Boolean\nAssert.IsTrue(condition);\nAssert.IsFalse(condition);\n\n\u002F\u002F Fail\u002FInconclusive\nAssert.Fail(\"Test failed due to...\");\nAssert.Inconclusive(\"Test cannot be completed because...\");\n```\n\n### Exception Testing (Prefer over `[ExpectedException]`)\n\n```csharp\n\u002F\u002F Assert.Throws - matches TException or derived types\nvar ex = Assert.Throws\u003CArgumentException>(() => Method(null));\nAssert.AreEqual(\"Value cannot be null.\", ex.Message);\n\n\u002F\u002F Assert.ThrowsExactly - matches exact type only\nvar ex = Assert.ThrowsExactly\u003CInvalidOperationException>(() => Method());\n\n\u002F\u002F Async versions\nvar ex = await Assert.ThrowsAsync\u003CHttpRequestException>(async () => await client.GetAsync(url));\nvar ex = await Assert.ThrowsExactlyAsync\u003CInvalidOperationException>(async () => await Method());\n```\n\n### Collection Assertions (Assert class)\n\n```csharp\nAssert.Contains(expectedItem, collection);\nAssert.DoesNotContain(unexpectedItem, collection);\nAssert.ContainsSingle(collection);  \u002F\u002F exactly one element\nAssert.HasCount(5, collection);\nAssert.IsEmpty(collection);\nAssert.IsNotEmpty(collection);\n```\n\n### String Assertions (Assert class)\n\n```csharp\nAssert.Contains(\"expected\", actualString);\nAssert.StartsWith(\"prefix\", actualString);\nAssert.EndsWith(\"suffix\", actualString);\nAssert.DoesNotStartWith(\"prefix\", actualString);\nAssert.DoesNotEndWith(\"suffix\", actualString);\nAssert.MatchesRegex(@\"\\d{3}-\\d{4}\", phoneNumber);\nAssert.DoesNotMatchRegex(@\"\\d+\", textOnly);\n```\n\n### Comparison Assertions\n\n```csharp\nAssert.IsGreaterThan(lowerBound, actual);\nAssert.IsGreaterThanOrEqualTo(lowerBound, actual);\nAssert.IsLessThan(upperBound, actual);\nAssert.IsLessThanOrEqualTo(upperBound, actual);\nAssert.IsInRange(actual, low, high);\nAssert.IsPositive(number);\nAssert.IsNegative(number);\n```\n\n### Type Assertions\n\n```csharp\n\u002F\u002F MSTest 3.x - uses out parameter\nAssert.IsInstanceOfType\u003CMyClass>(obj, out var typed);\ntyped.DoSomething();\n\n\u002F\u002F MSTest 4.x - returns typed result directly\nvar typed = Assert.IsInstanceOfType\u003CMyClass>(obj);\ntyped.DoSomething();\n\nAssert.IsNotInstanceOfType\u003CWrongType>(obj);\n```\n\n### Assert.That (MSTest 4.0+)\n\n```csharp\nAssert.That(result.Count > 0);  \u002F\u002F Auto-captures expression in failure message\n```\n\n### StringAssert Class\n\n> **Note:** Prefer `Assert` class equivalents when available (e.g., `Assert.Contains(\"expected\", actual)` over `StringAssert.Contains(actual, \"expected\")`).\n\n```csharp\nStringAssert.Contains(actualString, \"expected\");\nStringAssert.StartsWith(actualString, \"prefix\");\nStringAssert.EndsWith(actualString, \"suffix\");\nStringAssert.Matches(actualString, new Regex(@\"\\d{3}-\\d{4}\"));\nStringAssert.DoesNotMatch(actualString, new Regex(@\"\\d+\"));\n```\n\n### CollectionAssert Class\n\n> **Note:** Prefer `Assert` class equivalents when available (e.g., `Assert.Contains`).\n\n```csharp\n\u002F\u002F Containment\nCollectionAssert.Contains(collection, expectedItem);\nCollectionAssert.DoesNotContain(collection, unexpectedItem);\n\n\u002F\u002F Equality (same elements, same order)\nCollectionAssert.AreEqual(expectedCollection, actualCollection);\nCollectionAssert.AreNotEqual(unexpectedCollection, actualCollection);\n\n\u002F\u002F Equivalence (same elements, any order)\nCollectionAssert.AreEquivalent(expectedCollection, actualCollection);\nCollectionAssert.AreNotEquivalent(unexpectedCollection, actualCollection);\n\n\u002F\u002F Subset checks\nCollectionAssert.IsSubsetOf(subset, superset);\nCollectionAssert.IsNotSubsetOf(notSubset, collection);\n\n\u002F\u002F Element validation\nCollectionAssert.AllItemsAreInstancesOfType(collection, typeof(MyClass));\nCollectionAssert.AllItemsAreNotNull(collection);\nCollectionAssert.AllItemsAreUnique(collection);\n```\n\n## Data-Driven Tests\n\n### DataRow\n\n```csharp\n[TestMethod]\n[DataRow(1, 2, 3)]\n[DataRow(0, 0, 0, DisplayName = \"Zeros\")]\n[DataRow(-1, 1, 0, IgnoreMessage = \"Known issue #123\")]  \u002F\u002F MSTest 3.8+\npublic void Add_ReturnsSum(int a, int b, int expected)\n{\n    Assert.AreEqual(expected, Calculator.Add(a, b));\n}\n```\n\n### DynamicData\n\nThe data source can return any of the following types:\n\n- `IEnumerable\u003C(T1, T2, ...)>` (ValueTuple) - **preferred**, provides type safety (MSTest 3.7+)\n- `IEnumerable\u003CTuple\u003CT1, T2, ...>>` - provides type safety\n- `IEnumerable\u003CTestDataRow>` - provides type safety plus control over test metadata (display name, categories)\n- `IEnumerable\u003Cobject[]>` - **least preferred**, no type safety\n\n> **Note:** When creating new test data methods, prefer `ValueTuple` or `TestDataRow` over `IEnumerable\u003Cobject[]>`. The `object[]` approach provides no compile-time type checking and can lead to runtime errors from type mismatches.\n\n```csharp\n[TestMethod]\n[DynamicData(nameof(TestData))]\npublic void DynamicTest(int a, int b, int expected)\n{\n    Assert.AreEqual(expected, Calculator.Add(a, b));\n}\n\n\u002F\u002F ValueTuple - preferred (MSTest 3.7+)\npublic static IEnumerable\u003C(int a, int b, int expected)> TestData =>\n[\n    (1, 2, 3),\n    (0, 0, 0),\n];\n\n\u002F\u002F TestDataRow - when you need custom display names or metadata\npublic static IEnumerable\u003CTestDataRow\u003C(int a, int b, int expected)>> TestDataWithMetadata =>\n[\n    new((1, 2, 3)) { DisplayName = \"Positive numbers\" },\n    new((0, 0, 0)) { DisplayName = \"Zeros\" },\n    new((-1, 1, 0)) { DisplayName = \"Mixed signs\", IgnoreMessage = \"Known issue #123\" },\n];\n\n\u002F\u002F IEnumerable\u003Cobject[]> - avoid for new code (no type safety)\npublic static IEnumerable\u003Cobject[]> LegacyTestData =>\n[\n    [1, 2, 3],\n    [0, 0, 0],\n];\n```\n\n## TestContext\n\nThe `TestContext` class provides test run information, cancellation support, and output methods.\nSee [TestContext documentation](https:\u002F\u002Flearn.microsoft.com\u002Fdotnet\u002Fcore\u002Ftesting\u002Funit-testing-mstest-writing-tests-testcontext) for complete reference.\n\n### Accessing TestContext\n\n```csharp\n\u002F\u002F Property (MSTest suppresses CS8618 - don't use nullable or = null!)\npublic TestContext TestContext { get; set; }\n\n\u002F\u002F Constructor injection (MSTest 3.6+) - preferred for immutability\n[TestClass]\npublic sealed class MyTests\n{\n    private readonly TestContext _testContext;\n\n    public MyTests(TestContext testContext)\n    {\n        _testContext = testContext;\n    }\n}\n\n\u002F\u002F Static methods receive it as parameter\n[ClassInitialize]\npublic static void ClassInit(TestContext context) { }\n\n\u002F\u002F Optional for cleanup methods (MSTest 3.6+)\n[ClassCleanup]\npublic static void ClassCleanup(TestContext context) { }\n\n[AssemblyCleanup]\npublic static void AssemblyCleanup(TestContext context) { }\n```\n\n### Cancellation Token\n\nAlways use `TestContext.CancellationToken` for cooperative cancellation with `[Timeout]`:\n\n```csharp\n[TestMethod]\n[Timeout(5000)]\npublic async Task LongRunningTest()\n{\n    await _httpClient.GetAsync(url, TestContext.CancellationToken);\n}\n```\n\n### Test Run Properties\n\n```csharp\nTestContext.TestName              \u002F\u002F Current test method name\nTestContext.TestDisplayName       \u002F\u002F Display name (3.7+)\nTestContext.CurrentTestOutcome    \u002F\u002F Pass\u002FFail\u002FInProgress\nTestContext.TestData              \u002F\u002F Parameterized test data (3.7+, in TestInitialize\u002FCleanup)\nTestContext.TestException         \u002F\u002F Exception if test failed (3.7+, in TestCleanup)\nTestContext.DeploymentDirectory   \u002F\u002F Directory with deployment items\n```\n\n### Output and Result Files\n\n```csharp\n\u002F\u002F Write to test output (useful for debugging)\nTestContext.WriteLine(\"Processing item {0}\", itemId);\n\n\u002F\u002F Attach files to test results (logs, screenshots)\nTestContext.AddResultFile(screenshotPath);\n\n\u002F\u002F Store\u002Fretrieve data across test methods\nTestContext.Properties[\"SharedKey\"] = computedValue;\n```\n\n## Advanced Features\n\n### Retry for Flaky Tests (MSTest 3.9+)\n\n```csharp\n[TestMethod]\n[Retry(3)]\npublic void FlakyTest() { }\n```\n\n### Conditional Execution (MSTest 3.10+)\n\nSkip or run tests based on OS or CI environment:\n\n```csharp\n\u002F\u002F OS-specific tests\n[TestMethod]\n[OSCondition(OperatingSystems.Windows)]\npublic void WindowsOnlyTest() { }\n\n[TestMethod]\n[OSCondition(OperatingSystems.Linux | OperatingSystems.MacOS)]\npublic void UnixOnlyTest() { }\n\n[TestMethod]\n[OSCondition(ConditionMode.Exclude, OperatingSystems.Windows)]\npublic void SkipOnWindowsTest() { }\n\n\u002F\u002F CI environment tests\n[TestMethod]\n[CICondition]  \u002F\u002F Runs only in CI (default: ConditionMode.Include)\npublic void CIOnlyTest() { }\n\n[TestMethod]\n[CICondition(ConditionMode.Exclude)]  \u002F\u002F Skips in CI, runs locally\npublic void LocalOnlyTest() { }\n```\n\n### Parallelization\n\n```csharp\n\u002F\u002F Assembly level\n[assembly: Parallelize(Workers = 4, Scope = ExecutionScope.MethodLevel)]\n\n\u002F\u002F Disable for specific class\n[TestClass]\n[DoNotParallelize]\npublic sealed class SequentialTests { }\n```\n\n### Work Item Traceability (MSTest 3.8+)\n\nLink tests to work items for traceability in test reports:\n\n```csharp\n\u002F\u002F Azure DevOps work items\n[TestMethod]\n[WorkItem(12345)]  \u002F\u002F Links to work item #12345\npublic void Feature_Scenario_ExpectedBehavior() { }\n\n\u002F\u002F Multiple work items\n[TestMethod]\n[WorkItem(12345)]\n[WorkItem(67890)]\npublic void Feature_CoversMultipleRequirements() { }\n\n\u002F\u002F GitHub issues (MSTest 3.8+)\n[TestMethod]\n[GitHubWorkItem(\"https:\u002F\u002Fgithub.com\u002Fowner\u002Frepo\u002Fissues\u002F42\")]\npublic void BugFix_Issue42_IsResolved() { }\n```\n\nWork item associations appear in test results and can be used for:\n- Tracing test coverage to requirements\n- Linking bug fixes to regression tests\n- Generating traceability reports in CI\u002FCD pipelines\n\n## Common Mistakes to Avoid\n\n```csharp\n\u002F\u002F ❌ Wrong argument order\nAssert.AreEqual(actual, expected);\n\u002F\u002F ✅ Correct\nAssert.AreEqual(expected, actual);\n\n\u002F\u002F ❌ Using ExpectedException (obsolete)\n[ExpectedException(typeof(ArgumentException))]\n\u002F\u002F ✅ Use Assert.Throws\nAssert.Throws\u003CArgumentException>(() => Method());\n\n\u002F\u002F ❌ Using LINQ Single() - unclear exception\nvar item = items.Single();\n\u002F\u002F ✅ Use ContainsSingle - better failure message\nvar item = Assert.ContainsSingle(items);\n\n\u002F\u002F ❌ Hard cast - unclear exception\nvar handler = (MyHandler)result;\n\u002F\u002F ✅ Type assertion - shows actual type on failure\nvar handler = Assert.IsInstanceOfType\u003CMyHandler>(result);\n\n\u002F\u002F ❌ Ignoring cancellation token\nawait client.GetAsync(url, CancellationToken.None);\n\u002F\u002F ✅ Flow test cancellation\nawait client.GetAsync(url, TestContext.CancellationToken);\n\n\u002F\u002F ❌ Making TestContext nullable - leads to unnecessary null checks\npublic TestContext? TestContext { get; set; }\n\u002F\u002F ❌ Using null! - MSTest already suppresses CS8618 for this property\npublic TestContext TestContext { get; set; } = null!;\n\u002F\u002F ✅ Declare without nullable or initializer - MSTest handles the warning\npublic TestContext TestContext { get; set; }\n```\n\n## Test Organization\n\n- Group tests by feature or component\n- Use `[TestCategory(\"Category\")]` for filtering\n- Use `[TestProperty(\"Name\", \"Value\")]` for custom metadata (e.g., `[TestProperty(\"Bug\", \"12345\")]`)\n- Use `[Priority(1)]` for critical tests\n- Enable relevant MSTest analyzers (MSTEST0020 for constructor preference)\n\n## Mocking and Isolation\n\n- Use Moq or NSubstitute for mocking dependencies\n- Use interfaces to facilitate mocking\n- Mock dependencies to isolate units under test\n",{"name":5,"description":7},"main","5269f7ea2d6c3a9bfda5ed878b6726cf509121fd","skills\u002Fcsharp-mstest",5344,"https:\u002F\u002Fgithub.com\u002Fgithub\u002Fawesome-copilot","https:\u002F\u002Fawesome-copilot.github.com\u002F","https:\u002F\u002Fgithub.com\u002Fgithub","https:\u002F\u002Fgithub.com\u002Fabout","How people build software.","2026-11-13 02:05:36",{"source":8,"skillName":5,"commands":53,"prompt":63,"zipAvailable":64},[54,57,60],{"tool":55,"command":56},"npx","npx skills add github\u002Fawesome-copilot --skill csharp-mstest",{"tool":58,"command":59},"bunx","bunx skills add github\u002Fawesome-copilot --skill csharp-mstest",{"tool":61,"command":62},"pnpm","pnpm dlx skills add github\u002Fawesome-copilot --skill csharp-mstest","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002Fgithub\u002Fawesome-copilot\u002Fblob\u002Fmain\u002Fskills\u002Fcsharp-mstest\u002FSKILL.md",true,[66,72,76,80,86,90],{"path":67,"resourceType":68,"resourceTypeDesc":69,"sizeBytes":70,"sourceHtmlUrl":71},"references\u002Fllm_integration_guide.md","REFERENCE","参考文档",1421,"https:\u002F\u002Fgithub.com\u002Fdavila7\u002Fclaude-code-templates\u002Fblob\u002Fmain\u002Fcli-tool\u002Fcomponents\u002Fskills\u002Fdevelopment\u002Fsenior-ml-engineer\u002Freferences\u002Fllm_integration_guide.md",{"path":73,"resourceType":68,"resourceTypeDesc":69,"sizeBytes":74,"sourceHtmlUrl":75},"references\u002Fmlops_production_patterns.md",1429,"https:\u002F\u002Fgithub.com\u002Fdavila7\u002Fclaude-code-templates\u002Fblob\u002Fmain\u002Fcli-tool\u002Fcomponents\u002Fskills\u002Fdevelopment\u002Fsenior-ml-engineer\u002Freferences\u002Fmlops_production_patterns.md",{"path":77,"resourceType":68,"resourceTypeDesc":69,"sizeBytes":78,"sourceHtmlUrl":79},"references\u002Frag_system_architecture.md",1425,"https:\u002F\u002Fgithub.com\u002Fdavila7\u002Fclaude-code-templates\u002Fblob\u002Fmain\u002Fcli-tool\u002Fcomponents\u002Fskills\u002Fdevelopment\u002Fsenior-ml-engineer\u002Freferences\u002Frag_system_architecture.md",{"path":81,"resourceType":82,"resourceTypeDesc":83,"sizeBytes":84,"sourceHtmlUrl":85},"scripts\u002Fml_monitoring_suite.py","SCRIPT","脚本",2782,"https:\u002F\u002Fgithub.com\u002Fdavila7\u002Fclaude-code-templates\u002Fblob\u002Fmain\u002Fcli-tool\u002Fcomponents\u002Fskills\u002Fdevelopment\u002Fsenior-ml-engineer\u002Fscripts\u002Fml_monitoring_suite.py",{"path":87,"resourceType":82,"resourceTypeDesc":83,"sizeBytes":88,"sourceHtmlUrl":89},"scripts\u002Fmodel_deployment_pipeline.py",2812,"https:\u002F\u002Fgithub.com\u002Fdavila7\u002Fclaude-code-templates\u002Fblob\u002Fmain\u002Fcli-tool\u002Fcomponents\u002Fskills\u002Fdevelopment\u002Fsenior-ml-engineer\u002Fscripts\u002Fmodel_deployment_pipeline.py",{"path":91,"resourceType":82,"resourceTypeDesc":83,"sizeBytes":92,"sourceHtmlUrl":93},"scripts\u002Frag_system_builder.py",2777,"https:\u002F\u002Fgithub.com\u002Fdavila7\u002Fclaude-code-templates\u002Fblob\u002Fmain\u002Fcli-tool\u002Fcomponents\u002Fskills\u002Fdevelopment\u002Fsenior-ml-engineer\u002Fscripts\u002Frag_system_builder.py",[95,125,152,182,216,233],{"skillNo":96,"name":97,"nameZh":6,"description":98,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":99,"categories":100,"keywords":105,"publishedAt":37},"01M70KXZNX9ES38N2A8M58ZZMZ","supabase-rls-policies","Write, review, and test Supabase Row Level Security (RLS) policies so that one user cannot read or change another user's rows. Use when creating or changing tables, policies, views, or security definer functions in a Supabase project, when reviewing a migration that touches RLS, or when asked to prove user isolation with pgTAP tests that sign in as two users.","https:\u002F\u002Fgithub.com\u002Fgithub\u002Fawesome-copilot\u002Fblob\u002Fmain\u002Fskills\u002Fsupabase-rls-policies\u002FSKILL.md",[101,102],{"categoryNo":19,"categoryName":20,"taxonomyType":21,"taxonomyTypeDesc":22},{"categoryNo":103,"categoryName":104,"taxonomyType":21,"taxonomyTypeDesc":22},"01JBSEEDCAT000000000000023","Skill与智能体开发",[106,107,108,109,110,111,112,113,114,115,116,117,118,119,32,120,121,122,123,124],"supabase","rls","supabase rls","supabase rls policies","project","when","review","change","read","write","security","isolation","tables","as","prove","use","users","functions","with",{"skillNo":126,"name":127,"nameZh":6,"description":128,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":129,"categories":130,"keywords":132,"publishedAt":37},"01M70KWA5YWXDV6V8DZ19E3T2Y","skill-distribution-audit","Audit a skill collection before release or investigate installer omissions, archived\u002Ftemplate leakage, duplicate identities, and manifest drift. Reconcile the intended public source set, distribution manifest, and actual discovery output for a specified consumer version. Includes a deterministic set-comparison helper.","https:\u002F\u002Fgithub.com\u002Fgithub\u002Fawesome-copilot\u002Fblob\u002Fmain\u002Fskills\u002Fskill-distribution-audit\u002FSKILL.md",[131],{"categoryNo":103,"categoryName":104,"taxonomyType":21,"taxonomyTypeDesc":22},[133,134,135,136,137,138,35,139,140,141,142,143,144,145,146,147,148,149,150,151],"distribution","skill distribution audit","audit","SET","deterministic","installer","discovery","comparison","helper","manifest","version","collection","drift","output","investigate","duplicate","template","release","reconcile",{"skillNo":153,"name":154,"nameZh":6,"description":155,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":156,"sourceHtmlUrl":157,"categories":158,"keywords":164,"publishedAt":37},"01M70KCJPFVW7PPQ49CC5R8JGK","logicapps-custom-code-net10-migration","Migrate Azure Logic Apps Standard local-function custom-code projects from .NET 8 to .NET 10. Use for legacy Logic Apps custom-code workspace upgrades, project\u002Fpackage configuration, custom-worker settings, publication, and integrated VS Code debugging. Not for ordinary .NET applications, standalone Azure Functions, Consumption workflows, or cloud deployment.","https:\u002F\u002Fgithub.com\u002Fgithub\u002Fawesome-copilot\u002Fblob\u002Fmain\u002Fskills\u002Flogicapps-custom-code-net10-migration\u002FLICENSE","https:\u002F\u002Fgithub.com\u002Fgithub\u002Fawesome-copilot\u002Fblob\u002Fmain\u002Fskills\u002Flogicapps-custom-code-net10-migration\u002FSKILL.md",[159],{"categoryNo":160,"categoryName":161,"taxonomyType":162,"taxonomyTypeDesc":163},"01JBSEEDCAT000000000000030","开发工程师","PROFESSION","适用职业",[165,166,167,168,169,170,35,110,171,172,173,174,175,176,177,121,178,179,180,181],"custom","code","logicapps custom code net10 migration","migration","projects","standalone","deployment","applications","local","azure","worker","upgrades","package","apps","Legacy","debugging","workflows",{"skillNo":183,"name":184,"nameZh":6,"description":185,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":186,"sourceHtmlUrl":187,"categories":188,"keywords":193,"publishedAt":37},"01M6AEBN37RQMXJ3298PEY7PG1","winmd-api-search","Find and explore Windows desktop APIs. Use when building features that need platform capabilities — camera, file access, notifications, UI controls, AI\u002FML, sensors, networking, etc. Discovers the right API for a task and retrieves full type details (methods, properties, events, enumeration values).","https:\u002F\u002Fgithub.com\u002Fgithub\u002Fawesome-copilot\u002Fblob\u002Fmain\u002Fskills\u002Fwinmd-api-search\u002FLICENSE.txt","https:\u002F\u002Fgithub.com\u002Fgithub\u002Fawesome-copilot\u002Fblob\u002Fmain\u002Fskills\u002Fwinmd-api-search\u002FSKILL.md",[189,192],{"categoryNo":190,"categoryName":191,"taxonomyType":21,"taxonomyTypeDesc":22},"01JBSEEDCAT000000000000010","后端与接口",{"categoryNo":160,"categoryName":161,"taxonomyType":162,"taxonomyTypeDesc":163},[194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,111,209,210,211,212,213,35,214,215],"winmd api search","search","api","windows","desktop","file access","enumeration","ui","ml","file","networking","capabilities","notifications","explore","access","features","full","camera","events","platform","methods","controls",{"skillNo":217,"name":218,"nameZh":6,"description":219,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":220,"licenseFileUrl":221,"sourceHtmlUrl":222,"categories":223,"keywords":229,"publishedAt":37},"01M6AE571R3SC1ZGE202B3NB5S","resemble-detect","Deepfake detection and media safety — detect AI-generated audio, images, video, and text, trace synthesis sources, apply watermarks, verify speaker identity, and analyze media intelligence using Resemble AI","Apache-2.0","https:\u002F\u002Fgithub.com\u002Fgithub\u002Fawesome-copilot\u002Fblob\u002Fmain\u002Fskills\u002Fresemble-detect\u002FLICENSE","https:\u002F\u002Fgithub.com\u002Fgithub\u002Fawesome-copilot\u002Fblob\u002Fmain\u002Fskills\u002Fresemble-detect\u002FSKILL.md",[224,225,228],{"categoryNo":190,"categoryName":191,"taxonomyType":21,"taxonomyTypeDesc":22},{"categoryNo":226,"categoryName":227,"taxonomyType":21,"taxonomyTypeDesc":22},"01JBSEEDCAT000000000000016","图像与多媒体",{"categoryNo":103,"categoryName":104,"taxonomyType":21,"taxonomyTypeDesc":22},[230,136,203,231,232],"resemble detect","https","identity",{"skillNo":234,"name":235,"nameZh":6,"description":236,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":220,"licenseFileUrl":237,"sourceHtmlUrl":238,"categories":239,"keywords":244,"publishedAt":37},"01M6AE30BSK2HCY4TQQ22Z8JRD","quality-playbook","Run a complete quality engineering audit on any codebase. Derives behavioral requirements from the code, generates spec-traced functional tests, runs a three-pass code review with regression tests, executes a multi-model spec audit (Council of Three), and produces a consolidated bug report with TDD-verified patches. Finds the 35% of real defects that structural code review alone cannot catch. Works with any language. Trigger on 'quality playbook', 'spec audit', 'Council of Three', 'fitness-to-purpose', or 'coverage theater'.","https:\u002F\u002Fgithub.com\u002Fgithub\u002Fawesome-copilot\u002Fblob\u002Fmain\u002Fskills\u002Fquality-playbook\u002FLICENSE.txt","https:\u002F\u002Fgithub.com\u002Fgithub\u002Fawesome-copilot\u002Fblob\u002Fmain\u002Fskills\u002Fquality-playbook\u002FSKILL.md",[240,243],{"categoryNo":241,"categoryName":242,"taxonomyType":21,"taxonomyTypeDesc":22},"01JBSEEDCAT000000000000007","代码审查",{"categoryNo":103,"categoryName":104,"taxonomyType":21,"taxonomyTypeDesc":22},[245,246,247,248,166,112,9,135,249,250,231,251,252,253,254,255,256,257,258,259,260,261,32,262,263,264,265],"playbook","quality playbook","quality","code review","tdd","run","report","spec","bug report","council","engineering","functional","spec audit","bug","verified","multi-model","three","coverage","model","regression","structural"]