Conversation
Adds AspireFixture<TAppHost> that manages the full Aspire app lifecycle (build, start, wait-for-resources, stop, dispose), eliminating ~50 lines of boilerplate per test project. Supports direct use via ClassDataSource or subclassing with virtual configuration hooks. Closes #4768 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…nit.Aspire Update TUnit.Aspire.Test template to reference TUnit.Aspire instead of raw Aspire.Hosting.Testing boilerplate. Update CloudShop example's DistributedAppFixture to subclass AspireFixture<TAppHost>, demonstrating ConfigureBuilder, ResourceTimeout, and WaitForResourcesAsync overrides. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Code reviewNo issues found. Checked for bugs and CLAUDE.md compliance. This PR introduces a well-designed |
Code reviewNo issues found. Checked for bugs and CLAUDE.md compliance. This PR introduces a well-designed package that significantly reduces boilerplate for Aspire testing. The implementation follows TUnit's patterns correctly:
The refactoring of the CloudShop example validates the approach in a real-world scenario, reducing the fixture from 48 to 29 lines while maintaining all functionality. |
Two improvements to resource waiting: 1. Fail-fast: races each resource's ready-wait against a FailedToStart watcher. If a container crashes during startup, throws immediately with the resource name instead of hanging until timeout. 2. Timeout wrapping: catches OperationCanceledException from the timeout CTS and rethrows as TimeoutException listing all resource names, the wait behavior, and actionable suggestions (increase timeout, use WatchResourceLogs, check dashboard). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
When a resource enters FailedToStart, the error message now includes
the last 20 lines of that resource's logs (e.g., Docker pull failures,
config errors). On timeout, the message distinguishes ready vs. pending
resources and includes logs from each pending resource.
Example FailedToStart output:
Resource 'redis' failed to start.
--- redis logs ---
Error: no matching manifest for linux/amd64
Example timeout output:
Resources not ready: ['postgres']. Resources ready: ['redis']
--- postgres logs ---
waiting for server to start...
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…ate builds Template content projects reference TUnit.Aspire as a NuGet PackageReference, but the package hasn't been published yet. During solution builds (CI), this causes NU1101. The content Directory.Build.props (excluded from the template package) now swaps to a local ProjectReference and adds the implicit usings that would normally come from TUnit's NuGet props/targets. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Adding InternalsVisibleTo("TUnit.Aspire") to TUnit.Core changed the
assembly-level attributes, causing the Core_Library_Has_No_API_Changes
snapshot test to fail.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The CloudShop integration tests have been consistently timing out at the 10-minute job limit because pulling Docker images for PostgreSQL, Redis, and RabbitMQ from scratch on GitHub Actions runners takes too long. - Add a pre-pull step that pulls all 5 Docker images in parallel before the test run, giving visibility into pull times - Increase job timeout from 10 to 15 minutes - Increase fixture ResourceTimeout from 2 to 5 minutes Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Summary
TUnit.Aspirepackage withAspireFixture<TAppHost>that manages the full Aspire distributed app lifecycle (build, start, wait-for-resources, stop, dispose), eliminating ~50 lines of boilerplate per test project[ClassDataSource<AspireFixture<Projects.MyAppHost>>]or subclassing with virtual hooks (ConfigureBuilder,WaitBehavior,ResourceTimeout,ResourcesToWaitFor,WaitForResourcesAsync)WatchResourceLogs()for opt-in per-test resource log streamingTUnit.Aspire.Startertemplate to use the new package instead of rawAspire.Hosting.TestingboilerplateCloses #4768
Test plan
dotnet packproduces valid NuGet packagedotnet new tunit-aspire-starter🤖 Generated with Claude Code