-
Notifications
You must be signed in to change notification settings - Fork 0
Add E2E.Tests Aspire xUnit project #49
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,38 @@ | ||
| <Project Sdk="Microsoft.NET.Sdk"> | ||
|
|
||
| <PropertyGroup> | ||
| <TargetFramework>net10.0</TargetFramework> | ||
| <ImplicitUsings>enable</ImplicitUsings> | ||
| <Nullable>enable</Nullable> | ||
| <IsPackable>false</IsPackable> | ||
| <IsTestProject>true</IsTestProject> | ||
| <RootNamespace>MyBlog.E2E.Tests</RootNamespace> | ||
| </PropertyGroup> | ||
|
|
||
| <ItemGroup> | ||
| <PackageReference Include="Aspire.Hosting.Testing" Version="13.2.2" /> | ||
| <PackageReference Include="coverlet.collector" Version="10.0.0" /> | ||
| <PackageReference Include="FluentAssertions" Version="8.9.0" /> | ||
| <PackageReference Include="Microsoft.NET.Test.Sdk" Version="18.4.0" /> | ||
| <PackageReference Include="xunit" Version="2.9.3" /> | ||
| <PackageReference Include="xunit.runner.visualstudio" Version="3.1.5" /> | ||
| </ItemGroup> | ||
|
|
||
| <ItemGroup> | ||
| <Using Include="System.Net" /> | ||
| <Using Include="Aspire.Hosting.ApplicationModel" /> | ||
| <Using Include="Aspire.Hosting.Testing" /> | ||
| <Using Include="Xunit" /> | ||
| </ItemGroup> | ||
|
|
||
| <ItemGroup> | ||
| <ProjectReference Include="..\..\src\AppHost\AppHost.csproj" /> | ||
| </ItemGroup> | ||
|
|
||
| <ItemGroup> | ||
| <None Update="xunit.runner.json"> | ||
| <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> | ||
| </None> | ||
| </ItemGroup> | ||
|
|
||
| </Project> |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,13 @@ | ||
| //======================================================= | ||
| //Copyright (c) 2026. All rights reserved. | ||
| //File Name : GlobalUsings.cs | ||
| //Company : mpaulosky | ||
| //Author : Matthew Paulosky | ||
| //Solution Name : MyBlog | ||
| //Project Name : E2E.Tests | ||
| //======================================================= | ||
|
|
||
| global using FluentAssertions; | ||
| global using Aspire.Hosting.ApplicationModel; | ||
| global using Aspire.Hosting.Testing; | ||
| global using Xunit; |
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,44 @@ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| //======================================================= | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| //Copyright (c) 2026. All rights reserved. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| //File Name : WebAppTests.cs | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| //Company : mpaulosky | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| //Author : Matthew Paulosky | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| //Solution Name : MyBlog | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| //Project Name : E2E.Tests | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| //======================================================= | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| namespace MyBlog.E2E.Tests; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| public class WebAppTests | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| private static readonly TimeSpan DefaultTimeout = TimeSpan.FromSeconds(60); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| [Fact] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| public async Task GetWebResourceRootReturnsOkStatusCode() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Arrange | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| var cancellationToken = new CancellationTokenSource(DefaultTimeout).Token; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| var appHost = await DistributedApplicationTestingBuilder | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .CreateAsync<Projects.MyBlog_AppHost>(cancellationToken); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Check failure on line 23 in tests/E2E.Tests/WebAppTests.cs
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| appHost.Services.ConfigureHttpClientDefaults(clientBuilder => | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Check failure on line 25 in tests/E2E.Tests/WebAppTests.cs
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| clientBuilder.AddStandardResilienceHandler(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+25
to
+29
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| appHost.Services.ConfigureHttpClientDefaults(clientBuilder => | |
| { | |
| clientBuilder.AddStandardResilienceHandler(); | |
| }); |
Copilot
AI
Apr 19, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Timeout handling is currently duplicated: a 60s CancellationTokenSource governs the entire test, and then each step also adds a separate WaitAsync(DefaultTimeout, cancellationToken). This makes it harder to reason about total time budget and failure modes (cancellation vs timeout exceptions). Consider either (a) using the CTS token only (no WaitAsync(timeout)), or (b) using step-specific timeouts without a global 60s CTS (or a larger global CTS plus smaller per-step timeouts).
| await using var app = await appHost.BuildAsync(cancellationToken).WaitAsync(DefaultTimeout, cancellationToken); | |
| await app.StartAsync(cancellationToken).WaitAsync(DefaultTimeout, cancellationToken); | |
| // Act | |
| using var httpClient = app.CreateHttpClient("webfrontend"); | |
| await app.ResourceNotifications | |
| .WaitForResourceHealthyAsync("webfrontend", cancellationToken) | |
| .WaitAsync(DefaultTimeout, cancellationToken); | |
| await using var app = await appHost.BuildAsync(cancellationToken); | |
| await app.StartAsync(cancellationToken); | |
| // Act | |
| using var httpClient = app.CreateHttpClient("webfrontend"); | |
| await app.ResourceNotifications | |
| .WaitForResourceHealthyAsync("webfrontend", cancellationToken); |
Copilot
AI
Apr 19, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Timeout handling is currently duplicated: a 60s CancellationTokenSource governs the entire test, and then each step also adds a separate WaitAsync(DefaultTimeout, cancellationToken). This makes it harder to reason about total time budget and failure modes (cancellation vs timeout exceptions). Consider either (a) using the CTS token only (no WaitAsync(timeout)), or (b) using step-specific timeouts without a global 60s CTS (or a larger global CTS plus smaller per-step timeouts).
| await using var app = await appHost.BuildAsync(cancellationToken).WaitAsync(DefaultTimeout, cancellationToken); | |
| await app.StartAsync(cancellationToken).WaitAsync(DefaultTimeout, cancellationToken); | |
| // Act | |
| using var httpClient = app.CreateHttpClient("webfrontend"); | |
| await app.ResourceNotifications | |
| .WaitForResourceHealthyAsync("webfrontend", cancellationToken) | |
| .WaitAsync(DefaultTimeout, cancellationToken); | |
| await using var app = await appHost.BuildAsync(cancellationToken); | |
| await app.StartAsync(cancellationToken); | |
| // Act | |
| using var httpClient = app.CreateHttpClient("webfrontend"); | |
| await app.ResourceNotifications | |
| .WaitForResourceHealthyAsync("webfrontend", cancellationToken); |
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
| @@ -0,0 +1,7 @@ | ||||||
| { | ||||||
| "$schema": "https://xunit.net/schema/current/xunit.runner.schema.json", | ||||||
| "methodDisplay": "method", | ||||||
| "methodDisplayOptions": "all", | ||||||
| "parallelizeAssembly": false, | ||||||
| "parallelizeTestCollections": true | ||||||
|
||||||
| "parallelizeTestCollections": true | |
| "parallelizeTestCollections": false |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Timeout handling is currently duplicated: a 60s
CancellationTokenSourcegoverns the entire test, and then each step also adds a separateWaitAsync(DefaultTimeout, cancellationToken). This makes it harder to reason about total time budget and failure modes (cancellation vs timeout exceptions). Consider either (a) using the CTS token only (noWaitAsync(timeout)), or (b) using step-specific timeouts without a global 60s CTS (or a larger global CTS plus smaller per-step timeouts).