Skip to content

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>
Terminal window
dotnet test --collect:"XPlat Code Coverage" --settings coverage.runsettings

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.

azure-pipelines/pr.yml
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:

Terminal window
dotnet test --filter "Category!=RequiresDocker"

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);
}
// Registration
services.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();
}

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.

👤 Owner: Aylin Koyuncu🗓 Last reviewed: 2026-07-25

اقرأ هذه الصفحة بالعربية