Prompt file imported from rafsanulhasan/HypermediaEngine (
.github/prompts/write-tests.prompt.md). Copyright stays with the author.
Operating Methodology
You implement tests in four phases. This skill expects a confirmed test plan as input — test case design is handled by the design-test-cases skill. Do not redesign test strategy here; implement what the plan specifies.
Phase 0 — Context Load (silent, no user interaction)
Before writing any code:
- Read
CLAUDE.mdto internalize conventions. - Read the confirmed test plan in full — every TC specification is a work item.
- Locate the test project using Glob. Read several existing test files to internalize:
- Test framework (xUnit)
- Assertion library in use
- Test double approach (NSubstitute, hand-rolled, etc.)
- Naming convention
- Fixture and setup patterns (
IClassFixture, constructors,[ClassFixture])
- Add every TC from the plan as a tracked task before writing a single line of code.
Phase 1 — Test Implementation
Implement each TC from the confirmed plan in order. For every test file written:
Structure
Use Arrange / Act / Assert in every test method:
[Fact]
public async Task MethodName_StateUnderTest_ExpectedBehavior()
{
// Arrange
...
// Act
ResultType result = await sut.MethodNameAsync(input, ct);
// Assert
...
}
Naming
Three-part names that read as a specification: MethodName_StateUnderTest_ExpectedBehavior
Validate_WhenAuthHeaderIsMissing_ReturnsErrorResultDispatch_WhenHandlerSucceeds_ReturnsPopulatedDataProcess_WhenTokenIsCancelled_ThrowsOperationCanceledException
Convention checklist (apply to every test file)
- Explicit type declarations:
MyService sut = new(mockDep);notvar sut = ... -
await usingfor any disposable test fixtures - Assert both
dataanderrorfields for every{ data, error }result — never assert only one side - Each
[Fact]tests exactly one behavior from the TC specification - Use
[Theory]with[InlineData]or[MemberData]for parameterized edge cases listed in the plan - No
Thread.Sleepor arbitrary delays — useCancellationTokenproperly - Mock only the dependencies the TC exercises — minimal mock configuration
- Never mock the system under test itself
- No shared mutable state between test cases
Integration tests
For TCs marked as integration type in the plan:
- Use
WebApplicationFactory<T>or an in-memoryIHost - Register test doubles in the test host's DI — do not modify production registrations
- Each test must leave shared infrastructure in a clean state
Mark each TC task complete immediately after its test is written and compiling.
Phase 2 — Run and Verify
dotnet test
- All new tests must pass
- No previously passing test may fail — a test that breaks existing tests is itself a defect; report it to the software-engineer rather than modifying production code
- If a test fails because the implementation has a bug: stop, report the bug, do not modify production code yourself
- If a test fails because the test setup is wrong: fix the test setup only
Phase 3 — Mutation Testing
dotnet stryker
For each surviving mutant in code covered by the new tests:
- Map the mutant back to the TC that should have caught it
- Strengthen or add a test case that produces observably different output when the mutation is present
- Re-run
dotnet strykerto confirm the mutant is killed
Acceptable reasons to leave a mutant alive (add a comment in the test file):
- The mutant is in logging-only code with no observable output difference
- The code path is architecturally unreachable without breaking DI or middleware contracts
Do not mark work complete with unresolved surviving mutants unless each one is explicitly justified.
Quality Gate
Do not mark the test suite complete until:
- Every TC from the confirmed plan has a corresponding test method
- Every AC listed in the plan maps to at least one passing test
-
dotnet testexits with 0 failures -
dotnet strykerproduces no surviving mutants on new code paths (or each survivor is commented and justified) - Both
dataanderrorare asserted in every{ data, error }result test - No previously passing test was broken
- No production code was modified