Testing Examples
Illustrative only. The Testing Strategy page states the policy; this page shows the four mechanisms behind it.
1. How “business logic only” is actually expressed
Section titled “1. How “business logic only” is actually expressed”The coverage claim on the main page is only real because of this file. Without it, “coverage on business logic” is a sentence, not a gate.
<!-- coverage.runsettings --><RunSettings> <DataCollectionRunSettings> <DataCollectors> <DataCollector friendlyName="XPlat code coverage"> <Configuration> <Format>cobertura</Format> <Exclude>[*]*.Migrations.*,[*]*.Contracts.*,[*]Program</Exclude> <ExcludeByAttribute> ExcludeFromCodeCoverage,GeneratedCodeAttribute,CompilerGeneratedAttribute </ExcludeByAttribute> </Configuration> </DataCollector> </DataCollectors> </DataCollectionRunSettings></RunSettings>dotnet test --collect:"XPlat Code Coverage" --settings coverage.runsettings2. The PR lanes
Section titled “2. The PR lanes”Two things matter here and both are easy to get wrong: no path filter on the test steps, and full history so the diff can be compared against the merge base.
steps: # A shallow clone makes the diff-coverage comparison silently pass. - checkout: self fetchDepth: 0
- task: DotNetCoreCLI@2 displayName: 'Fast lane — unit + no-Docker subset' inputs: command: test arguments: > --filter "Category!=RequiresDocker" --collect:"XPlat Code Coverage" --settings coverage.runsettings
- task: DotNetCoreCLI@2 displayName: 'Integration lane — real database' inputs: command: test arguments: '--filter "Category=RequiresDocker"'
- script: npm ci && npm test -- --coverage displayName: 'Frontend unit' workingDirectory: src/web
- script: | diff-cover coverage.cobertura.xml \ --compare-branch=origin/$(System.PullRequest.TargetBranch) \ --fail-under=80 displayName: 'Diff coverage — 80% of changed lines'Note there is no condition: on the test steps. A path filter that skips tests when “only the backend changed” is how a suite quietly stops running.
3. An integration test against a real host
Section titled “3. An integration test against a real host”[Trait("Category", "RequiresDocker")]public sealed class GetBranchesEndpointTests(ApiFactory factory) : IClassFixture<ApiFactory>{ [Fact] public async Task Returns_only_branches_the_supervisor_owns() { // xUnit v3: the framework's token, threaded into every async call. // This is what makes the "pass CancellationToken" rule testable. var ct = TestContext.Current.CancellationToken;
var client = factory.CreateClient(); await factory.SeedAsync(new Supervisor("s-1", branches: ["b-1", "b-2"]), ct);
var response = await client.GetAsync("/v1/branches?supervisorId=s-1", ct);
response.StatusCode.ShouldBe(HttpStatusCode.OK); var branches = await response.Content.ReadFromJsonAsync<BranchDto[]>(ct); branches.ShouldNotBeNull().Length.ShouldBe(2); }}The trait is what lets a developer without Docker still run a green suite:
dotnet test --filter "Category!=RequiresDocker"4. Deterministic time
Section titled “4. Deterministic time”The most common source of flakiness, and the cheapest to remove.
// Before — untestable without sleeping, and the assertion depends on the clock.public sealed class ManagerSessionStore{ public bool IsExpired(ManagerSession s) => DateTimeOffset.UtcNow > s.StartedAt.AddMinutes(30);}
// After — the clock is a dependency.public sealed class ManagerSessionStore(TimeProvider time){ public bool IsExpired(ManagerSession s) => time.GetUtcNow() > s.StartedAt.AddMinutes(30);}// Registrationservices.AddSingleton(TimeProvider.System);[Fact]public void Session_expires_after_thirty_minutes(){ var clock = new FakeTimeProvider(new DateTimeOffset(2026, 1, 1, 9, 0, 0, TimeSpan.Zero)); var store = new ManagerSessionStore(clock); var session = new ManagerSession(startedAt: clock.GetUtcNow());
store.IsExpired(session).ShouldBeFalse();
clock.Advance(TimeSpan.FromMinutes(31)); // no sleep, no wall clock
store.IsExpired(session).ShouldBeTrue();}Quarantining a flake
Section titled “Quarantining a flake”Two one-liners, and the work item is what makes it temporary rather than permanent:
[Fact(Skip = "Flaky — AB#12345")]test.fixme('checkout survives a slow payment callback', async ({ page }) => { /* … */ });Back to Testing Strategy.