
Csharp Mstest
Write MSTest 3.x/4.x unit tests in a separate `[ProjectName].Tests` project with modern assertions and data-driven patterns.
Overview
csharp-mstest is an agent skill for the Ship phase that guides you through MSTest 3.x/4.x unit-test structure, naming, lifecycle, and modern assertion patterns for .NET projects.
Install
npx skills add https://github.com/github/awesome-copilot --skill csharp-mstestWhat is this skill?
- MSTest 3.x/4.x APIs with sealed `[TestClass]` and `MethodName_Scenario_ExpectedBehavior` naming
- Prefer constructors over `[TestInitialize]` for setup; `[TestCleanup]` when failure-safe teardown matters
- Arrange-Act-Assert examples plus guidance on `[TestMethod]` vs data-driven tests
- Separate test project naming and MSTest.Sdk / analyzer package setup
- Run and iterate with `dotnet test` from the repo root
Adoption & trust: 8.5k installs on skills.sh; 34.6k GitHub stars; 3/3 security scanners passed (skills.sh audits).
What problem does it solve?
You have C# production code but your MSTest projects use outdated attributes, unclear test names, or setup patterns that fight readonly fields and analyzer expectations.
Who is it for?
Solo builders maintaining .NET APIs, libraries, or internal tools who want agent-assisted MSTest tests that match current Microsoft guidance.
Skip if: Teams standardizing on xUnit or NUnit only, or workflows that need full integration/E2E harness design without unit-test focus.
When should I use this skill?
User asks for MSTest unit testing help, modern assertion APIs, data-driven tests, or .NET test project setup.
What do I get? / Deliverables
After running the skill, your agent produces sealed test classes, AAA-shaped methods, and MSTest 3.x-friendly setup so `dotnet test` gives reliable, readable coverage.
- MSTest test classes and methods following AAA and naming conventions
- Test project references and package guidance for MSTest 3.x+
Recommended Skills
Journey fit
Unit testing guidance belongs on the Ship shelf because solo builders apply it when hardening code before release, not during initial feature coding. Testing is the canonical subphase for MSTest structure, AAA layout, lifecycle hooks, and `dotnet test` workflows.
How it compares
Use instead of generic “write some tests” chat prompts when you want MSTest-specific conventions rather than framework-agnostic snippets.
Common Questions / FAQ
Who is csharp-mstest for?
Indie and solo .NET developers and agents pair-programming in Cursor, Claude Code, or Codex who need consistent MSTest 3.x/4.x unit tests in a dedicated test project.
When should I use csharp-mstest?
Use it in the Ship phase while adding or refactoring unit tests, before a release when you want AAA structure and modern assertions, or when onboarding an agent to your `[ProjectName].Tests` repo layout.
Is csharp-mstest safe to install?
It is documentation-style procedural guidance without bundled scripts; review the Security Audits panel on this Prism page and your org’s skill trust policy before enabling it in production agents.
SKILL.md
READMESKILL.md - Csharp Mstest
# MSTest Best Practices (MSTest 3.x/4.x) Your goal is to help me write effective unit tests with modern MSTest, using current APIs and best practices. ## Project Setup - Use a separate test project with naming convention `[ProjectName].Tests` - Reference MSTest 3.x+ NuGet packages (includes analyzers) - Consider using MSTest.Sdk for simplified project setup - Run tests with `dotnet test` ## Test Class Structure - Use `[TestClass]` attribute for test classes - **Seal test classes by default** for performance and design clarity - Use `[TestMethod]` for test methods (prefer over `[DataTestMethod]`) - Follow Arrange-Act-Assert (AAA) pattern - Name tests using pattern `MethodName_Scenario_ExpectedBehavior` ```csharp [TestClass] public sealed class CalculatorTests { [TestMethod] public void Add_TwoPositiveNumbers_ReturnsSum() { // Arrange var calculator = new Calculator(); // Act var result = calculator.Add(2, 3); // Assert Assert.AreEqual(5, result); } } ``` ## Test Lifecycle - **Prefer constructors over `[TestInitialize]`** - enables `readonly` fields and follows standard C# patterns - Use `[TestCleanup]` for cleanup that must run even if test fails - Combine constructor with async `[TestInitialize]` when async setup is needed ```csharp [TestClass] public sealed class ServiceTests { private readonly MyService _service; // readonly enabled by constructor public ServiceTests() { _service = new MyService(); } [TestInitialize] public async Task InitAsync() { // Use for async initialization only await _service.WarmupAsync(); } [TestCleanup] public void Cleanup() => _service.Reset(); } ``` ### Execution Order 1. **Assembly Initialization** - `[AssemblyInitialize]` (once per test assembly) 2. **Class Initialization** - `[ClassInitialize]` (once per test class) 3. **Test Initialization** (for every test method): 1. Constructor 2. Set `TestContext` property 3. `[TestInitialize]` 4. **Test Execution** - test method runs 5. **Test Cleanup** (for every test method): 1. `[TestCleanup]` 2. `DisposeAsync` (if implemented) 3. `Dispose` (if implemented) 6. **Class Cleanup** - `[ClassCleanup]` (once per test class) 7. **Assembly Cleanup** - `[AssemblyCleanup]` (once per test assembly) ## Modern Assertion APIs MSTest provides three assertion classes: `Assert`, `StringAssert`, and `CollectionAssert`. ### Assert Class - Core Assertions ```csharp // Equality Assert.AreEqual(expected, actual); Assert.AreNotEqual(notExpected, actual); Assert.AreSame(expectedObject, actualObject); // Reference equality Assert.AreNotSame(notExpectedObject, actualObject); // Null checks Assert.IsNull(value); Assert.IsNotNull(value); // Boolean Assert.IsTrue(condition); Assert.IsFalse(condition); // Fail/Inconclusive Assert.Fail("Test failed due to..."); Assert.Inconclusive("Test cannot be completed because..."); ``` ### Exception Testing (Prefer over `[ExpectedException]`) ```csharp // Assert.Throws - matches TException or derived types var ex = Assert.Throws<ArgumentException>(() => Method(null)); Assert.AreEqual("Value cannot be null.", ex.Message); // Assert.ThrowsExactly - matches exact type only var ex = Assert.ThrowsExactly<InvalidOperationException>(() => Method()); // Async versions var ex = await Assert.ThrowsAsync<HttpRequestException>(async () => await client.GetAsync(url)); var ex = await Assert.ThrowsExactlyAsync<InvalidOperationException>(async () => await Method()); ``` ### Collection Assertions (Assert class) ```csharp Assert.Contains(expectedItem, collection); Assert.DoesNotContain(unexpectedItem, collection); Assert.ContainsSingle(collection); // exactly one element Assert.HasCount(5, collection); Assert.IsEmpty(collection); Asser