Categories
Agent Tooling (71)
- .agents/skills/agent-browser/references/authentication.md
- .agents/skills/agent-browser/references/commands.md
- .agents/skills/agent-browser/references/profiling.md
- .agents/skills/agent-browser/references/proxy-support.md
- .agents/skills/agent-browser/references/session-management.md
- .agents/skills/agent-browser/references/snapshot-refs.md
- .agents/skills/agent-browser/references/video-recording.md
- .agents/skills/agent-browser/SKILL.md
- .agents/skills/aspire-deployment/references/aws.md
- .agents/skills/aspire-deployment/references/azure.md
- .agents/skills/aspire-deployment/references/cicd.md
- .agents/skills/aspire-deployment/references/docker-compose.md
- .agents/skills/aspire-deployment/references/javascript.md
- .agents/skills/aspire-deployment/references/kubernetes.md
- .agents/skills/aspire-deployment/references/preflight.md
- .agents/skills/aspire-deployment/SKILL.md
- .agents/skills/aspire-monitoring/references/diagnostics-bridge.md
- .agents/skills/aspire-monitoring/references/monitoring.md
- .agents/skills/aspire-monitoring/references/playwright-handoff.md
- .agents/skills/aspire-monitoring/SKILL.md
- .agents/skills/aspire-orchestration/references/agent-workflows.md
- .agents/skills/aspire-orchestration/references/app-commands.md
- .agents/skills/aspire-orchestration/references/detection.md
- .agents/skills/aspire-orchestration/references/resource-management.md
- .agents/skills/aspire-orchestration/references/safety-guardrails.md
- .agents/skills/aspire-orchestration/SKILL.md
- .agents/skills/aspire/references/aspire-13-3-breaking-changes.md
- .agents/skills/aspire/SKILL.md
- .agents/skills/aspireify/references/apphost-wiring.md
- .agents/skills/aspireify/references/csharp-authoring.md
- .agents/skills/aspireify/references/docker-compose.md
- .agents/skills/aspireify/references/full-solution-apphosts.md
- .agents/skills/aspireify/references/javascript-apps.md
- .agents/skills/aspireify/references/opentelemetry.md
- .agents/skills/aspireify/references/scan-and-propose.md
- .agents/skills/aspireify/references/service-defaults.md
- .agents/skills/aspireify/references/typescript-authoring.md
- .agents/skills/aspireify/references/validation.md
- .agents/skills/aspireify/SKILL.md
- .agents/skills/caveman-compress/README.md
- .agents/skills/caveman-compress/SECURITY.md
- .agents/skills/caveman-compress/SKILL.md
- .agents/skills/caveman-help/README.md
- .agents/skills/caveman-help/SKILL.md
- .agents/skills/caveman-stats/README.md
- .agents/skills/caveman-stats/SKILL.md
- .agents/skills/caveman/README.md
- .agents/skills/caveman/SKILL.md
- .agents/skills/csharp-developer/SKILL.md
- .agents/skills/dotnet-inspect/SKILL.md
- .agents/skills/efcore-data-layer/SKILL.md
- .agents/skills/git/SKILL.md
- .agents/skills/microsoft-code-reference/SKILL.md
- .agents/skills/microsoft-docs/SKILL.md
- .agents/skills/microsoft-skill-creator/references/skill-templates.md
- .agents/skills/microsoft-skill-creator/SKILL.md
- .agents/skills/skill-creator/references/output-patterns.md
- .agents/skills/skill-creator/references/workflows.md
- .agents/skills/skill-creator/SKILL.md
- .agents/skills/tunit-testing/references/aspire-integration.md
- .agents/skills/tunit-testing/references/aspnetcore-integration.md
- .agents/skills/tunit-testing/references/assertions.md
- .agents/skills/tunit-testing/references/data-driven.md
- .agents/skills/tunit-testing/references/infrastructure-and-troubleshooting.md
- .agents/skills/tunit-testing/references/lifecycle-hooks.md
- .agents/skills/tunit-testing/SKILL.md
- AGENTS.md
- backend/AGENTS.md
- backend/tests/AGENTS.md
- Front/AGENT.md
- opencode.jsonc
Aspire Integration
Use these patterns for distributed application testing with TUnit.Aspire.
When To Use TUnit.Aspire
Use TUnit.Aspire when tests need a real Aspire AppHost and its orchestrated resources:
- multiple services
- databases, caches, brokers, and containers
- real connection strings from the AppHost
- end-to-end HTTP flows across process boundaries
Prefer TUnit.AspNetCore when testing a single ASP.NET Core app in isolation.
Basic Fixture Pattern
The simplest setup uses AspireFixture<TAppHost> directly as shared class data.
[ClassDataSource<AspireFixture<Projects.MyAppHost>>(Shared = SharedType.PerTestSession)]
public class ApiTests(AspireFixture<Projects.MyAppHost> fixture)
{
[Test]
public async Task GetWeatherForecast_ReturnsOk()
{
var client = fixture.CreateHttpClient("apiservice");
var response = await client.GetAsync("/weatherforecast");
await Assert.That(response.StatusCode).IsEqualTo(HttpStatusCode.OK);
}
}This fixture handles:
- build
- start
- wait for resources
- stop
- disposal
Subclass For Customization
Create a dedicated fixture subclass when you need timeouts, builder customization, or custom waiting behavior.
public class AppFixture : AspireFixture<Projects.MyAppHost>
{
protected override TimeSpan ResourceTimeout => TimeSpan.FromMinutes(3);
protected override void ConfigureBuilder(IDistributedApplicationTestingBuilder builder)
{
builder.Services.ConfigureHttpClientDefaults(clientBuilder =>
{
clientBuilder.AddStandardResilienceHandler();
});
}
}Shared Session Pattern
Distributed applications are expensive to start. Prefer:
[ClassDataSource<AppFixture>(Shared = SharedType.PerTestSession)]
This starts the AppHost once per test process and shares it across tests.
Resource Waiting
Pick the lightest waiting strategy that still matches your test needs.
Defaults:
AllHealthyfor apps that expose useful health checks
Alternatives:
AllRunningwhen health checks are not configured or not neededNamedwhen tests depend on only a subset of resourcesNonewhen tests perform their own readiness logic
public class AppFixture : AspireFixture<Projects.MyAppHost>
{
protected override ResourceWaitBehavior WaitBehavior => ResourceWaitBehavior.Named;
protected override IEnumerable<string> ResourcesToWaitFor()
=> ["apiservice", "worker"];
}Remove Unneeded Resources
If the AppHost defines dashboards, admin tools, or optional developer-only resources, remove them from the test app instead of waiting for them.
public class AppFixture : AspireFixture<Projects.MyAppHost>
{
protected override IEnumerable<string> ResourcesToRemove()
=> ["pgadmin", "redisinsight", "seq"];
}This reduces startup time and CI flakiness.
Lifecycle Hooks In Fixtures
AspireFixture<TAppHost> already implements lifecycle management, but you can extend it safely.
Use InitializeAsync() for post-start actions such as:
- migrations
- seeding
- warming caches
public class AppFixture : AspireFixture<Projects.MyAppHost>
{
public override async Task InitializeAsync()
{
await base.InitializeAsync();
var connectionString = await GetConnectionStringAsync("postgresdb");
await RunMigrationsAsync(connectionString!);
}
}Fixture Chains
You can build higher-level fixtures on top of an Aspire fixture using property injection.
public class ApiClientFixture : IAsyncInitializer
{
[ClassDataSource<AppFixture>(Shared = SharedType.PerTestSession)]
public required AppFixture App { get; init; }
public HttpClient Client { get; private set; } = null!;
public Task InitializeAsync()
{
Client = App.CreateHttpClient("apiservice");
return Task.CompletedTask;
}
}This is useful for:
- preconfigured HTTP clients
- direct database connections
- cache clients
- message broker clients
Telemetry And Log Correlation
AspireFixture can correlate SUT logs and traces back to the test that triggered the request.
Guidance:
- prefer
fixture.CreateHttpClient(...)instead of constructing clients manually - leave telemetry collection enabled unless you have a specific reason to disable it
- use
WatchResourceLogs(resourceName)when debugging startup/resource failures
[Test]
public async Task Create_Order_Returns_201()
{
await using var _ = fixture.WatchResourceLogs("apiservice");
var client = fixture.CreateHttpClient("apiservice");
var response = await client.PostAsJsonAsync("/api/orders", new { Item = "Widget" });
await Assert.That(response.StatusCode).IsEqualTo(HttpStatusCode.Created);
}AppHost Arguments vs Builder Configuration
Use the right extension point for the right phase:
Argsfor values the AppHost reads during builder creationConfigureAppHost(...)for builder creation options and host settingsConfigureBuilder(...)for services and post-builder customization
If the AppHost reads a value during CreateBuilder(args), passing it later in ConfigureBuilder(...) is too late.
CI Guidance
Common CI requirements:
- Docker must be available
- use
SharedType.PerTestSession - increase
ResourceTimeoutfor slower runners - if HTTPS dev cert trust is an issue, set
ASPIRE_ALLOW_UNSECURED_TRANSPORT=true
Diagnostics
When startup or readiness fails:
- inspect recent resource logs in the thrown timeout/fail-fast diagnostics
- use
WatchResourceLogs(...)in focused tests - reduce the surface area by removing unneeded resources
- switch from
AllHealthytoAllRunningif health checks are the blocker and not required by the test
Decision Rule
Use:
TUnit.Aspirefor full distributed app tests around an Aspire AppHostTUnit.AspNetCorefor isolated in-process ASP.NET Core integration tests
They can coexist in the same solution when different test layers need different tradeoffs.