diff --git a/.github/actions/setup-runtimes-caching/action.yml b/.github/actions/setup-runtimes-caching/action.yml
index 27c4edbf9..5b7644b87 100644
--- a/.github/actions/setup-runtimes-caching/action.yml
+++ b/.github/actions/setup-runtimes-caching/action.yml
@@ -123,3 +123,4 @@ runs:
if: ${{ inputs.name == 'Full' || contains(inputs.name, 'Hosting.Ollama') }}
with:
version: 0.11.8
+
diff --git a/.github/workflows/tests.yaml b/.github/workflows/tests.yaml
index c511bb0d0..ea8569957 100644
--- a/.github/workflows/tests.yaml
+++ b/.github/workflows/tests.yaml
@@ -101,18 +101,19 @@ jobs:
- name: Run tests
run: >-
- dotnet test ${{ github.workspace }}/${{ env.TEST_PROJECT_PATH }}
+ dotnet run
+ --project "${{ github.workspace }}/${{ env.TEST_PROJECT_PATH }}"
+ --no-build
--configuration ${{ env.DOTNET_CONFIGURATION }}
- --logger "console;verbosity=normal"
- --logger "trx"
- --logger "GitHubActions;summary.includePassedTests=true;summary.includeSkippedTests=true"
- --blame
- --blame-hang-timeout 7m
- --blame-crash
- --results-directory testresults
- --collect "XPlat Code Coverage"
- --no-restore
- --no-build -- RunConfiguration.CollectSourceInformation=true
+ --crashdump
+ --hangdump
+ --hangdump-timeout 7m
+ --results-directory "${{ github.workspace }}/testresults"
+ --filter-not-trait "category=failing"
+ --report-trx
+ --report-trx-filename "${{ matrix.name }}-${{ matrix.os }}.trx"
+ --coverage
+ --report-github
env:
CUSTOM_CONTAINER_REGISTRY: ${{ secrets.CUSTOM_CONTAINER_REGISTRY }}
diff --git a/.gitignore b/.gitignore
index d997c9787..959f23f3f 100644
--- a/.gitignore
+++ b/.gitignore
@@ -7,7 +7,7 @@ obj
appsettings.*.json
*.orig
test-results
-TestResults
+[Tt]est[Rr]esults
nuget
.pnpm-store
.DS_Store
diff --git a/.vscode/tasks.json b/.vscode/tasks.json
index c4fa0024b..4658de2bd 100644
--- a/.vscode/tasks.json
+++ b/.vscode/tasks.json
@@ -2,36 +2,49 @@
"version": "2.0.0",
"tasks": [
{
- "label": "build",
- "command": "dotnet",
- "type": "process",
- "args": [
- "build",
- "/property:GenerateFullPaths=true",
- "/consoleloggerparameters:NoSummary;ForceNoAlign"
- ],
- "problemMatcher": "$msCompile"
+ "label": "build",
+ "command": "dotnet",
+ "type": "process",
+ "args": [
+ "build",
+ "/property:GenerateFullPaths=true",
+ "/consoleloggerparameters:NoSummary;ForceNoAlign"
+ ],
+ "problemMatcher": "$msCompile"
},
{
- "label": "publish",
- "command": "dotnet",
- "type": "process",
- "args": [
- "publish",
- "/property:GenerateFullPaths=true",
- "/consoleloggerparameters:NoSummary;ForceNoAlign"
- ],
- "problemMatcher": "$msCompile"
+ "label": "publish",
+ "command": "dotnet",
+ "type": "process",
+ "args": [
+ "publish",
+ "/property:GenerateFullPaths=true",
+ "/consoleloggerparameters:NoSummary;ForceNoAlign"
+ ],
+ "problemMatcher": "$msCompile"
},
{
- "label": "watch",
- "command": "dotnet",
- "type": "process",
- "args": [
- "watch",
- "run"
- ],
- "problemMatcher": "$msCompile"
+ "label": "watch",
+ "command": "dotnet",
+ "type": "process",
+ "args": [
+ "watch",
+ "run"
+ ],
+ "problemMatcher": "$msCompile"
+ },
+ {
+ "label": "cleanup",
+ "type": "shell",
+ "command": "./eng/clean-bin-obj.sh",
+ "problemMatcher": [],
+ "linux": {
+ "options": {
+ "shell": {
+ "executable": "bash"
+ }
+ }
+ }
}
],
"inputs": [
diff --git a/Directory.Packages.props b/Directory.Packages.props
index 815f85b89..9f5e837d1 100644
--- a/Directory.Packages.props
+++ b/Directory.Packages.props
@@ -103,13 +103,18 @@
-
+
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
diff --git a/eng/clean-bin-obj.sh b/eng/clean-bin-obj.sh
new file mode 100755
index 000000000..f9b69649a
--- /dev/null
+++ b/eng/clean-bin-obj.sh
@@ -0,0 +1,85 @@
+#!/usr/bin/env bash
+# Recursively delete all `bin` and `obj` folders from the repository.
+# Usage: ./eng/clean-bin-obj.sh
+# Optional flags:
+# --dry-run Show what would be removed without deleting.
+# --quiet Suppress per-folder output; only show summary.
+# --help Display help.
+#
+# The script resolves the repo root based on its own location so it can be
+# invoked from any working directory.
+
+set -euo pipefail
+
+print_help() {
+ cat <<'EOF'
+Clean bin/obj folders
+
+Deletes ALL directories named `bin` or `obj` under the repository root.
+
+Flags:
+ --dry-run List directories that would be deleted.
+ --quiet Only print summary information.
+ --help Show this help text.
+
+Examples:
+ ./eng/clean-bin-obj.sh
+ ./eng/clean-bin-obj.sh --dry-run
+ ./eng/clean-bin-obj.sh --quiet
+EOF
+}
+
+DRY_RUN=0
+QUIET=0
+for arg in "$@"; do
+ case "$arg" in
+ --dry-run) DRY_RUN=1 ;;
+ --quiet) QUIET=1 ;;
+ --help|-h) print_help; exit 0 ;;
+ *) echo "Unknown argument: $arg" >&2; exit 1 ;;
+ esac
+done
+
+# Determine repo root (parent of this script's directory)
+SCRIPT_DIR=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)
+REPO_ROOT=$(cd "${SCRIPT_DIR}/.." && pwd)
+
+cd "$REPO_ROOT"
+
+# Collect bin/obj directories excluding anything under .git to be safe.
+# Use -prune to avoid descending into matched directories after they are found.
+mapfile -t TARGETS < <(find . -type d \( -name bin -o -name obj \) -not -path '*/.git/*' -prune -print)
+
+COUNT=${#TARGETS[@]}
+if [[ $COUNT -eq 0 ]]; then
+ [[ $QUIET -eq 0 ]] && echo "No bin/obj directories found under $REPO_ROOT." || true
+ exit 0
+fi
+
+if [[ $DRY_RUN -eq 1 ]]; then
+ [[ $QUIET -eq 0 ]] && printf '%s\n' "Dry run: the following $COUNT directories would be deleted:" || true
+ printf '%s\n' "${TARGETS[@]}"
+ exit 0
+fi
+
+# Delete directories.
+DELETED=0
+for dir in "${TARGETS[@]}"; do
+ if [[ $QUIET -eq 0 ]]; then
+ echo "Removing: $dir"
+ fi
+ rm -rf "$dir" || {
+ echo "Failed to remove: $dir" >&2
+ continue
+ }
+ # Increment without triggering set -e early exit (arithmetic exit status is 1 when result is 0 for post-increment)
+ ((DELETED++)) || true
+done
+
+if [[ $QUIET -eq 0 ]]; then
+ echo "Removed $DELETED bin/obj directories under $REPO_ROOT."
+else
+ echo "Removed $DELETED directories." # Always show a minimal summary in quiet mode.
+fi
+
+exit 0
diff --git a/examples/powershell/CommunityToolkit.Aspire.PowerShell.AppHost/Program.cs b/examples/powershell/CommunityToolkit.Aspire.PowerShell.AppHost/Program.cs
index 57f4bb348..dc33823bf 100644
--- a/examples/powershell/CommunityToolkit.Aspire.PowerShell.AppHost/Program.cs
+++ b/examples/powershell/CommunityToolkit.Aspire.PowerShell.AppHost/Program.cs
@@ -2,7 +2,13 @@
var builder = DistributedApplication.CreateBuilder(args);
-var storage = builder.AddAzureStorage("storage").RunAsEmulator();
+var storage = builder.AddAzureStorage("storage")
+ // see: https://github.com/dotnet/aspire/issues/13811
+ .RunAsEmulator(azurite =>
+ {
+ azurite.WithArgs("--disableProductStyleUrl");
+ });
+
var blob = storage.AddBlobs("myblob");
var ps = builder.AddPowerShell("ps")
@@ -14,6 +20,7 @@
param($name)
write-information "Hello, $name"
+ write-information $pwd
# uncommenting this will hang the script if you don't attach the pwsh debugger
# wait-debugger
@@ -22,15 +29,19 @@
# only run this if Azure CLI is installed
if ((gcm az -ErrorAction SilentlyContinue) -ne $null) {
+ # When in the tests the PWD is wrong so we should test for it and fix it
+ if ($pwd -like "*CommunityToolkit.Aspire.Hosting.PowerShell.Tests*") {
+ write-information "Fixing PWD from $pwd"
+ Set-Location (Join-Path $pwd "../../../../../examples/powershell/CommunityToolkit.Aspire.PowerShell.AppHost")
+ write-information "New PWD is $pwd"
+ }
az storage container create --connection-string $myblob -n demo
- az storage blob upload --connection-string $myblob -c demo --file ./scripts/script.ps1
+ az storage blob upload --connection-string $myblob -c demo --file ./Scripts/script.ps1
write-information "Blob uploaded"
} else {
-
write-warning "Azure CLI not found, skipping blob upload"
-
}
write-information $pwd
@@ -39,10 +50,19 @@ az storage blob upload --connection-string $myblob -c demo --file ./scripts/scri
// outputs "the sum of 2 and 3 is 5"
var script2 = ps.AddScript("script2", """
- & ./scripts/script.ps1 @args
+ write-information 'Getting there...'
+ if ($pwd -like "*CommunityToolkit.Aspire.Hosting.PowerShell.Tests*") {
+ write-information "Fixing PWD from $pwd"
+ Set-Location (Join-Path $pwd "../../../../../examples/powershell/CommunityToolkit.Aspire.PowerShell.AppHost")
+ write-information "New PWD is $pwd"
+ }
+ write-information $PWD
+
+ & ./Scripts/script.ps1 @args
""")
.WithArgs(2, 3)
.WaitForCompletion(script1);
+
builder.Build().Run();
diff --git a/examples/powershell/CommunityToolkit.Aspire.PowerShell.AppHost/Properties/launchSettings.json b/examples/powershell/CommunityToolkit.Aspire.PowerShell.AppHost/Properties/launchSettings.json
index 80e6457ea..64093b07a 100644
--- a/examples/powershell/CommunityToolkit.Aspire.PowerShell.AppHost/Properties/launchSettings.json
+++ b/examples/powershell/CommunityToolkit.Aspire.PowerShell.AppHost/Properties/launchSettings.json
@@ -7,6 +7,7 @@
"launchBrowser": true,
"applicationUrl": "https://localhost:17118;http://localhost:15215",
"environmentVariables": {
+ "DCP_DIAGNOSTICS_LOG_LEVEL": "debug",
"ASPNETCORE_ENVIRONMENT": "Development",
"DOTNET_ENVIRONMENT": "Development",
"DOTNET_DASHBOARD_OTLP_ENDPOINT_URL": "https://localhost:21165",
diff --git a/nuget.config b/nuget.config
index ea10cc391..3e815a248 100644
--- a/nuget.config
+++ b/nuget.config
@@ -10,7 +10,7 @@
-
+
diff --git a/src/CommunityToolkit.Aspire.Hosting.PowerShell/DistributedApplicationBuilderExtensions.cs b/src/CommunityToolkit.Aspire.Hosting.PowerShell/DistributedApplicationBuilderExtensions.cs
index baf5ce2b1..f2a3970a2 100644
--- a/src/CommunityToolkit.Aspire.Hosting.PowerShell/DistributedApplicationBuilderExtensions.cs
+++ b/src/CommunityToolkit.Aspire.Hosting.PowerShell/DistributedApplicationBuilderExtensions.cs
@@ -1,6 +1,7 @@
using Aspire.Hosting;
using Aspire.Hosting.ApplicationModel;
using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.Hosting;
using System.Diagnostics;
using System.Management.Automation;
using System.Management.Automation.Runspaces;
@@ -34,23 +35,34 @@ public static IResourceBuilder AddPowerShell(
var pool = new PowerShellRunspacePoolResource(name, languageMode, minRunspaces, maxRunspaces);
+ var poolBuilder = builder.AddResource(pool)
+ .WithInitialState(new()
+ {
+ ResourceType = "PowerShellRunspacePool",
+ State = KnownResourceStates.NotStarted,
+ Properties = [
- builder.Eventing.Subscribe(pool, async (e, ct) =>
- {
- var poolResource = e.Resource as PowerShellRunspacePoolResource;
-
- Debug.Assert(poolResource is not null);
+ new ("LanguageMode", pool.LanguageMode.ToString()),
+ new ("MinRunspaces", pool.MinRunspaces.ToString()),
+ new ("MaxRunspaces", pool.MaxRunspaces.ToString())
+ ]
+ })
+ .ExcludeFromManifest();
+ poolBuilder.OnInitializeResource(async (res, e, ct) =>
+ {
var loggerService = e.Services.GetRequiredService();
var notificationService = e.Services.GetRequiredService();
+ var hostLifetime = e.Services.GetRequiredService();
var sessionState = InitialSessionState.CreateDefault();
+ sessionState.UseFullLanguageModeInDebugger = true;
// This will block until explicit and implied WaitFor calls are completed
await builder.Eventing.PublishAsync(
- new BeforeResourceStartedEvent(poolResource, e.Services), ct);
+ new BeforeResourceStartedEvent(res, e.Services), ct);
- foreach (var annotation in poolResource.Annotations.OfType>())
+ foreach (var annotation in res.Annotations.OfType>())
{
if (annotation is { } reference)
{
@@ -62,24 +74,12 @@ await builder.Eventing.PublishAsync(
}
}
- var poolName = poolResource.Name;
+ var poolName = res.Name;
var poolLogger = loggerService.GetLogger(poolName);
- _ = poolResource.StartAsync(sessionState, notificationService, poolLogger, ct);
+ _ = res.StartAsync(sessionState, notificationService, poolLogger, hostLifetime, ct);
});
- return builder.AddResource(pool)
- .WithInitialState(new()
- {
- ResourceType = "PowerShellRunspacePool",
- State = KnownResourceStates.NotStarted,
- Properties = [
-
- new ("LanguageMode", pool.LanguageMode.ToString()),
- new ("MinRunspaces", pool.MinRunspaces.ToString()),
- new ("MaxRunspaces", pool.MaxRunspaces.ToString())
- ]
- })
- .ExcludeFromManifest();
+ return poolBuilder;
}
}
\ No newline at end of file
diff --git a/src/CommunityToolkit.Aspire.Hosting.PowerShell/PowerShellRunspacePoolResource.cs b/src/CommunityToolkit.Aspire.Hosting.PowerShell/PowerShellRunspacePoolResource.cs
index a0a90156d..96831fe61 100644
--- a/src/CommunityToolkit.Aspire.Hosting.PowerShell/PowerShellRunspacePoolResource.cs
+++ b/src/CommunityToolkit.Aspire.Hosting.PowerShell/PowerShellRunspacePoolResource.cs
@@ -1,4 +1,5 @@
using Aspire.Hosting.ApplicationModel;
+using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using System.Globalization;
using System.Management.Automation;
@@ -37,7 +38,7 @@ public class PowerShellRunspacePoolResource(
///
public RunspacePool? Pool { get; private set; }
- internal Task StartAsync(InitialSessionState sessionState, ResourceNotificationService notificationService, ILogger logger, CancellationToken token = default)
+ internal Task StartAsync(InitialSessionState sessionState, ResourceNotificationService notificationService, ILogger logger, IHostApplicationLifetime hostLifetime, CancellationToken token = default)
{
logger.LogInformation(
"Starting PowerShell runspace pool '{PoolName}' with {MinRunspaces} to {MaxRunspaces} runspaces",
@@ -48,6 +49,13 @@ internal Task StartAsync(InitialSessionState sessionState, ResourceNotificationS
Pool = RunspaceFactory.CreateRunspacePool(MinRunspaces, MaxRunspaces, sessionState, new AspirePSHost(logger));
ConfigureStateChangeNotifications(notificationService, logger);
+
+ hostLifetime.ApplicationStopping.Register(() =>
+ {
+ // if we don't do this, xunit 3 will hang on exit because of open runspaces (foreground threads)
+ logger.LogInformation("Closing PowerShell runspace pool '{PoolName}'", Name);
+ Pool?.Close();
+ });
return Task.Factory.FromAsync(Pool.BeginOpen, Pool.EndOpen, null);
}
diff --git a/src/CommunityToolkit.Aspire.Hosting.PowerShell/PowerShellRunspacePoolResourceBuilderExtensions.cs b/src/CommunityToolkit.Aspire.Hosting.PowerShell/PowerShellRunspacePoolResourceBuilderExtensions.cs
index 5ab6437b6..695a8ce97 100644
--- a/src/CommunityToolkit.Aspire.Hosting.PowerShell/PowerShellRunspacePoolResourceBuilderExtensions.cs
+++ b/src/CommunityToolkit.Aspire.Hosting.PowerShell/PowerShellRunspacePoolResourceBuilderExtensions.cs
@@ -32,31 +32,7 @@ public static IResourceBuilder AddScript(
var scriptResource = new PowerShellScriptResource(name, scriptBlock, builder.Resource);
- builder.ApplicationBuilder.Eventing.Subscribe(scriptResource, async (e, ct) =>
- {
- var loggerService = e.Services.GetRequiredService();
- var notificationService = e.Services.GetRequiredService();
-
- var scriptName = scriptResource.Name;
- var scriptLogger = loggerService.GetLogger(scriptName);
-
- try
- {
- // this will block until the runspace pool is started, which is implied by the WaitFor call
- await builder.ApplicationBuilder.Eventing.PublishAsync(
- new BeforeResourceStartedEvent(scriptResource, e.Services), ct);
-
- scriptLogger.LogInformation("Starting script '{ScriptName}'", scriptName);
-
- _ = scriptResource.StartAsync(scriptLogger, notificationService, ct);
- }
- catch (Exception ex)
- {
- scriptLogger.LogError(ex, "Failed to start script '{ScriptName}'", scriptName);
- }
- });
-
- return builder.ApplicationBuilder
+ var scriptBuilder = builder.ApplicationBuilder
.AddResource(scriptResource)
.WithParentRelationship(builder.Resource)
.WaitFor(builder)
@@ -88,6 +64,32 @@ await builder.ApplicationBuilder.Eventing.PublishAsync(
ResourceCommandState.Disabled :
ResourceCommandState.Enabled
});
+
+ scriptBuilder.OnInitializeResource(async (res, e, ct) =>
+ {
+ var loggerService = e.Services.GetRequiredService();
+ var notificationService = e.Services.GetRequiredService();
+
+ var scriptName = res.Name;
+ var scriptLogger = loggerService.GetLogger(scriptName);
+
+ try
+ {
+ // this will block until the runspace pool is started, which is implied by the WaitFor call
+ await builder.ApplicationBuilder.Eventing.PublishAsync(
+ new BeforeResourceStartedEvent(res, e.Services), ct);
+
+ scriptLogger.LogInformation("Starting script '{ScriptName}'", scriptName);
+
+ _ = res.StartAsync(scriptLogger, notificationService, ct);
+ }
+ catch (Exception ex)
+ {
+ scriptLogger.LogError(ex, "Failed to start script '{ScriptName}'", scriptName);
+ }
+ });
+
+ return scriptBuilder;
}
///
diff --git a/tests/.runsettings b/tests/.runsettings
deleted file mode 100644
index 1ce761b64..000000000
--- a/tests/.runsettings
+++ /dev/null
@@ -1,7 +0,0 @@
-
-
-
-
- category!=unsupported-platform
-
-
\ No newline at end of file
diff --git a/tests/CommunityToolkit.Aspire.GoFeatureFlag.Tests/AspireGoFeatureFlagClientExtensionsTest.cs b/tests/CommunityToolkit.Aspire.GoFeatureFlag.Tests/AspireGoFeatureFlagClientExtensionsTest.cs
index 4d07a5cf9..a7e134ba2 100644
--- a/tests/CommunityToolkit.Aspire.GoFeatureFlag.Tests/AspireGoFeatureFlagClientExtensionsTest.cs
+++ b/tests/CommunityToolkit.Aspire.GoFeatureFlag.Tests/AspireGoFeatureFlagClientExtensionsTest.cs
@@ -2,6 +2,7 @@
// The .NET Foundation licenses this file to you under the MIT license.
using Aspire.Components.Common.Tests;
+using CommunityToolkit.Aspire.Testing;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Diagnostics.HealthChecks;
using Microsoft.Extensions.Hosting;
diff --git a/tests/CommunityToolkit.Aspire.GoFeatureFlag.Tests/ConformanceTests.cs b/tests/CommunityToolkit.Aspire.GoFeatureFlag.Tests/ConformanceTests.cs
index e5942de1a..65c5ae4ff 100644
--- a/tests/CommunityToolkit.Aspire.GoFeatureFlag.Tests/ConformanceTests.cs
+++ b/tests/CommunityToolkit.Aspire.GoFeatureFlag.Tests/ConformanceTests.cs
@@ -3,6 +3,7 @@
using Aspire.Components.Common.Tests;
using Aspire.Components.ConformanceTests;
+using CommunityToolkit.Aspire.Testing;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Hosting;
using OpenFeature.Contrib.Providers.GOFeatureFlag;
diff --git a/tests/CommunityToolkit.Aspire.GoFeatureFlag.Tests/GoFeatureFlagContainerFixture.cs b/tests/CommunityToolkit.Aspire.GoFeatureFlag.Tests/GoFeatureFlagContainerFixture.cs
index 591ece83c..5c5db3936 100644
--- a/tests/CommunityToolkit.Aspire.GoFeatureFlag.Tests/GoFeatureFlagContainerFixture.cs
+++ b/tests/CommunityToolkit.Aspire.GoFeatureFlag.Tests/GoFeatureFlagContainerFixture.cs
@@ -6,6 +6,7 @@
using Aspire.Hosting;
using DotNet.Testcontainers.Builders;
using DotNet.Testcontainers.Containers;
+using CommunityToolkit.Aspire.Testing;
namespace CommunityToolkit.Aspire.GoFeatureFlag.Tests;
@@ -22,7 +23,7 @@ public string GetConnectionString()
return $"Endpoint={endpoint}";
}
- public async Task InitializeAsync()
+ public async ValueTask InitializeAsync()
{
if (RequiresDockerAttribute.IsSupported)
{
@@ -38,7 +39,7 @@ public async Task InitializeAsync()
}
}
- public async Task DisposeAsync()
+ public async ValueTask DisposeAsync()
{
if (Container is not null)
{
diff --git a/tests/CommunityToolkit.Aspire.Hosting.GoFeatureFlag.Tests/GoFeatureFlagFunctionalTests.cs b/tests/CommunityToolkit.Aspire.Hosting.GoFeatureFlag.Tests/GoFeatureFlagFunctionalTests.cs
index 0eb202a15..e6a044049 100644
--- a/tests/CommunityToolkit.Aspire.Hosting.GoFeatureFlag.Tests/GoFeatureFlagFunctionalTests.cs
+++ b/tests/CommunityToolkit.Aspire.Hosting.GoFeatureFlag.Tests/GoFeatureFlagFunctionalTests.cs
@@ -1,14 +1,13 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
-using Aspire.Components.Common.Tests;
using Aspire.Hosting;
using Microsoft.Extensions.Diagnostics.HealthChecks;
using Microsoft.Extensions.Hosting;
-using Xunit.Abstractions;
using Aspire.Hosting.Utils;
using OpenFeature.Contrib.Providers.GOFeatureFlag;
using OpenFeature.Model;
+using CommunityToolkit.Aspire.Testing;
namespace CommunityToolkit.Aspire.Hosting.GoFeatureFlag.Tests;
diff --git a/tests/CommunityToolkit.Aspire.Hosting.KurrentDB.Tests/KurrentDBFunctionalTests.cs b/tests/CommunityToolkit.Aspire.Hosting.KurrentDB.Tests/KurrentDBFunctionalTests.cs
index 3b1b431f8..b4653823e 100644
--- a/tests/CommunityToolkit.Aspire.Hosting.KurrentDB.Tests/KurrentDBFunctionalTests.cs
+++ b/tests/CommunityToolkit.Aspire.Hosting.KurrentDB.Tests/KurrentDBFunctionalTests.cs
@@ -1,12 +1,12 @@
using Aspire.Components.Common.Tests;
using Aspire.Hosting;
using Aspire.Hosting.Utils;
+using CommunityToolkit.Aspire.Testing;
using KurrentDB.Client;
using Microsoft.Extensions.Diagnostics.HealthChecks;
using Microsoft.Extensions.Hosting;
using System.Text;
using System.Text.Json;
-using Xunit.Abstractions;
namespace CommunityToolkit.Aspire.Hosting.KurrentDB.Tests;
diff --git a/tests/CommunityToolkit.Aspire.Hosting.McpInspector.Tests/AppHostTests.cs b/tests/CommunityToolkit.Aspire.Hosting.McpInspector.Tests/AppHostTests.cs
index 3fdb35c32..372cc547a 100644
--- a/tests/CommunityToolkit.Aspire.Hosting.McpInspector.Tests/AppHostTests.cs
+++ b/tests/CommunityToolkit.Aspire.Hosting.McpInspector.Tests/AppHostTests.cs
@@ -2,8 +2,6 @@
namespace CommunityToolkit.Aspire.Hosting.McpInspector.Tests;
-// Forcing linux only due to: https://github.com/modelcontextprotocol/inspector/issues/893
-[RequiresLinux]
public class AppHostTests(AspireIntegrationTestFixture fixture) : IClassFixture>
{
[Fact]
diff --git a/tests/CommunityToolkit.Aspire.Hosting.Meilisearch.Tests/MeilisearchFunctionalTests.cs b/tests/CommunityToolkit.Aspire.Hosting.Meilisearch.Tests/MeilisearchFunctionalTests.cs
index 01d4e1d4a..e409ce007 100644
--- a/tests/CommunityToolkit.Aspire.Hosting.Meilisearch.Tests/MeilisearchFunctionalTests.cs
+++ b/tests/CommunityToolkit.Aspire.Hosting.Meilisearch.Tests/MeilisearchFunctionalTests.cs
@@ -6,7 +6,6 @@
using Microsoft.Extensions.Diagnostics.HealthChecks;
using Microsoft.Extensions.Hosting;
using Polly;
-using Xunit.Abstractions;
using Meilisearch;
using Aspire.Hosting.Utils;
using CommunityToolkit.Aspire.Testing;
diff --git a/tests/CommunityToolkit.Aspire.Hosting.Minio.Tests/MinioFunctionalTests.cs b/tests/CommunityToolkit.Aspire.Hosting.Minio.Tests/MinioFunctionalTests.cs
index 1ccdc8641..3a164b54f 100644
--- a/tests/CommunityToolkit.Aspire.Hosting.Minio.Tests/MinioFunctionalTests.cs
+++ b/tests/CommunityToolkit.Aspire.Hosting.Minio.Tests/MinioFunctionalTests.cs
@@ -1,10 +1,10 @@
using Aspire.Components.Common.Tests;
using Aspire.Hosting;
using Aspire.Hosting.Utils;
+using CommunityToolkit.Aspire.Testing;
using Microsoft.Extensions.Hosting;
using Minio;
using Minio.DataModel.Args;
-using Xunit.Abstractions;
namespace CommunityToolkit.Aspire.Hosting.Minio.Tests;
diff --git a/tests/CommunityToolkit.Aspire.Hosting.OpenTelemetryCollector.Tests/ResourceCreationTests.cs b/tests/CommunityToolkit.Aspire.Hosting.OpenTelemetryCollector.Tests/ResourceCreationTests.cs
index b259b6448..5ea684801 100644
--- a/tests/CommunityToolkit.Aspire.Hosting.OpenTelemetryCollector.Tests/ResourceCreationTests.cs
+++ b/tests/CommunityToolkit.Aspire.Hosting.OpenTelemetryCollector.Tests/ResourceCreationTests.cs
@@ -1,7 +1,7 @@
using Aspire.Components.Common.Tests;
using Aspire.Hosting;
using Aspire.Hosting.Utils;
-using Xunit.Abstractions;
+using CommunityToolkit.Aspire.Testing;
namespace CommunityToolkit.Aspire.Hosting.OpenTelemetryCollector.Tests;
diff --git a/tests/CommunityToolkit.Aspire.Hosting.PowerShell.Tests/AppHostTests.cs b/tests/CommunityToolkit.Aspire.Hosting.PowerShell.Tests/AppHostTests.cs
index 284d5c7bd..6472b383b 100644
--- a/tests/CommunityToolkit.Aspire.Hosting.PowerShell.Tests/AppHostTests.cs
+++ b/tests/CommunityToolkit.Aspire.Hosting.PowerShell.Tests/AppHostTests.cs
@@ -1,4 +1,3 @@
-using Aspire.Components.Common.Tests;
using CommunityToolkit.Aspire.Testing;
namespace CommunityToolkit.Aspire.Hosting.PowerShell.Tests;
@@ -14,7 +13,7 @@ public async Task PowerShellResourceStarts()
await fixture.ResourceNotificationService
.WaitForResourceAsync(resourceName, KnownResourceStates.Running)
.WaitAsync(TimeSpan.FromSeconds(60));
-
+
Assert.True(true);
}
diff --git a/tests/CommunityToolkit.Aspire.Hosting.Redis.Extensions.Tests/ResourceCreationTests.cs b/tests/CommunityToolkit.Aspire.Hosting.Redis.Extensions.Tests/ResourceCreationTests.cs
index c02a12420..5a5c27842 100644
--- a/tests/CommunityToolkit.Aspire.Hosting.Redis.Extensions.Tests/ResourceCreationTests.cs
+++ b/tests/CommunityToolkit.Aspire.Hosting.Redis.Extensions.Tests/ResourceCreationTests.cs
@@ -45,7 +45,7 @@ public async Task WithDbGateAddsAnnotations()
{
var redisUrl = redisResource.PasswordParameter is not null ?
$"redis://:{await redisResource.PasswordParameter.GetValueAsync(default)}@{redisResource.Name}:{redisResource.PrimaryEndpoint.TargetPort}" : $"redis://{redisResource.Name}:{redisResource.PrimaryEndpoint.TargetPort}";
- Assert.Equal("URL_redis1", item.Key);
+ Assert.Equal("URL_redis", item.Key);
Assert.Equal(redisUrl, item.Value);
},
item =>
diff --git a/tests/CommunityToolkit.Aspire.Hosting.Sftp.Tests/AppHostTests.cs b/tests/CommunityToolkit.Aspire.Hosting.Sftp.Tests/AppHostTests.cs
index 7d9f08f99..04f529ca3 100644
--- a/tests/CommunityToolkit.Aspire.Hosting.Sftp.Tests/AppHostTests.cs
+++ b/tests/CommunityToolkit.Aspire.Hosting.Sftp.Tests/AppHostTests.cs
@@ -3,7 +3,6 @@
using Polly;
using Projects;
using Renci.SshNet;
-using Xunit.Abstractions;
namespace CommunityToolkit.Aspire.Hosting.Sftp.Tests;
diff --git a/tests/CommunityToolkit.Aspire.Hosting.Sftp.Tests/SftpFunctionalTests.cs b/tests/CommunityToolkit.Aspire.Hosting.Sftp.Tests/SftpFunctionalTests.cs
index c9aa4fc1b..d29503c55 100644
--- a/tests/CommunityToolkit.Aspire.Hosting.Sftp.Tests/SftpFunctionalTests.cs
+++ b/tests/CommunityToolkit.Aspire.Hosting.Sftp.Tests/SftpFunctionalTests.cs
@@ -1,12 +1,12 @@
using Aspire.Components.Common.Tests;
using Aspire.Hosting;
using Aspire.Hosting.Utils;
+using CommunityToolkit.Aspire.Testing;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using Polly;
using Renci.SshNet;
using Renci.SshNet.Common;
-using Xunit.Abstractions;
namespace CommunityToolkit.Aspire.Hosting.Sftp.Tests;
diff --git a/tests/CommunityToolkit.Aspire.Hosting.SqlDatabaseProjects.Tests/FunctionalTests.cs b/tests/CommunityToolkit.Aspire.Hosting.SqlDatabaseProjects.Tests/FunctionalTests.cs
index ca481bfe2..9409da302 100644
--- a/tests/CommunityToolkit.Aspire.Hosting.SqlDatabaseProjects.Tests/FunctionalTests.cs
+++ b/tests/CommunityToolkit.Aspire.Hosting.SqlDatabaseProjects.Tests/FunctionalTests.cs
@@ -1,9 +1,8 @@
-using Aspire.Components.Common.Tests;
-using Aspire.Hosting;
+using Aspire.Hosting;
using Aspire.Hosting.Utils;
+using CommunityToolkit.Aspire.Testing;
using Microsoft.Data.SqlClient;
using Microsoft.Extensions.Diagnostics.HealthChecks;
-using Xunit.Abstractions;
namespace CommunityToolkit.Aspire.Hosting.SqlDatabaseProjects.Tests;
diff --git a/tests/CommunityToolkit.Aspire.Hosting.SqlDatabaseProjects.Tests/SqlServerContainerFixture.cs b/tests/CommunityToolkit.Aspire.Hosting.SqlDatabaseProjects.Tests/SqlServerContainerFixture.cs
index aa7cce6da..9890da7d7 100644
--- a/tests/CommunityToolkit.Aspire.Hosting.SqlDatabaseProjects.Tests/SqlServerContainerFixture.cs
+++ b/tests/CommunityToolkit.Aspire.Hosting.SqlDatabaseProjects.Tests/SqlServerContainerFixture.cs
@@ -15,9 +15,9 @@ public sealed class SqlServerContainerFixture : IAsyncLifetime
public string GetConnectionString() => Container?.GetConnectionString() ??
throw new InvalidOperationException("The test container was not initialized.");
- public async Task InitializeAsync() => Container = await CreateContainerAsync();
+ public async ValueTask InitializeAsync() => Container = await CreateContainerAsync();
- public async Task DisposeAsync()
+ public async ValueTask DisposeAsync()
{
if (Container is not null)
await Container.DisposeAsync();
diff --git a/tests/CommunityToolkit.Aspire.Hosting.SqlServer.Extensions.Tests/ResourceCreationTests.cs b/tests/CommunityToolkit.Aspire.Hosting.SqlServer.Extensions.Tests/ResourceCreationTests.cs
index 6fcd43bfa..fd885a83f 100644
--- a/tests/CommunityToolkit.Aspire.Hosting.SqlServer.Extensions.Tests/ResourceCreationTests.cs
+++ b/tests/CommunityToolkit.Aspire.Hosting.SqlServer.Extensions.Tests/ResourceCreationTests.cs
@@ -53,7 +53,7 @@ public async Task WithDbGateAddsAnnotations()
},
async item =>
{
- Assert.Equal("PASSWORD_sqlserver1", item.Key);
+ Assert.Equal("PASSWORD_sqlserver", item.Key);
Assert.Equal(await sqlserverResource.PasswordParameter.GetValueAsync(default), item.Value);
},
item =>
diff --git a/tests/CommunityToolkit.Aspire.Hosting.Stripe.Tests/AppHostTests.cs b/tests/CommunityToolkit.Aspire.Hosting.Stripe.Tests/AppHostTests.cs
index 83901481a..17c8f84ea 100644
--- a/tests/CommunityToolkit.Aspire.Hosting.Stripe.Tests/AppHostTests.cs
+++ b/tests/CommunityToolkit.Aspire.Hosting.Stripe.Tests/AppHostTests.cs
@@ -1,4 +1,3 @@
-using Aspire.Components.Common.Tests;
using CommunityToolkit.Aspire.Testing;
namespace CommunityToolkit.Aspire.Hosting.Stripe.Tests;
diff --git a/tests/CommunityToolkit.Aspire.Hosting.SurrealDb.Tests/SurrealDbFunctionalTests.cs b/tests/CommunityToolkit.Aspire.Hosting.SurrealDb.Tests/SurrealDbFunctionalTests.cs
index 2c3afd26b..4f92c4573 100644
--- a/tests/CommunityToolkit.Aspire.Hosting.SurrealDb.Tests/SurrealDbFunctionalTests.cs
+++ b/tests/CommunityToolkit.Aspire.Hosting.SurrealDb.Tests/SurrealDbFunctionalTests.cs
@@ -13,7 +13,6 @@
using SurrealDb.Net;
using SurrealDb.Net.Exceptions;
using System.Data;
-using Xunit.Abstractions;
using SurrealRecord = SurrealDb.Net.Models.Record;
namespace CommunityToolkit.Aspire.Hosting.SurrealDb.Tests;
diff --git a/tests/CommunityToolkit.Aspire.KurrentDB.Tests/AspireKurrentDBClientExtensionsTest.cs b/tests/CommunityToolkit.Aspire.KurrentDB.Tests/AspireKurrentDBClientExtensionsTest.cs
index 56509b7d7..94ef94b04 100644
--- a/tests/CommunityToolkit.Aspire.KurrentDB.Tests/AspireKurrentDBClientExtensionsTest.cs
+++ b/tests/CommunityToolkit.Aspire.KurrentDB.Tests/AspireKurrentDBClientExtensionsTest.cs
@@ -2,6 +2,7 @@
// The .NET Foundation licenses this file to you under the MIT license.
using Aspire.Components.Common.Tests;
+using CommunityToolkit.Aspire.Testing;
using KurrentDB.Client;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Diagnostics.HealthChecks;
diff --git a/tests/CommunityToolkit.Aspire.KurrentDB.Tests/ConformanceTests.cs b/tests/CommunityToolkit.Aspire.KurrentDB.Tests/ConformanceTests.cs
index db9b5d412..144f2940b 100644
--- a/tests/CommunityToolkit.Aspire.KurrentDB.Tests/ConformanceTests.cs
+++ b/tests/CommunityToolkit.Aspire.KurrentDB.Tests/ConformanceTests.cs
@@ -3,6 +3,7 @@
using Aspire.Components.Common.Tests;
using Aspire.Components.ConformanceTests;
+using CommunityToolkit.Aspire.Testing;
using KurrentDB.Client;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Hosting;
diff --git a/tests/CommunityToolkit.Aspire.KurrentDB.Tests/KurrentDBContainerFixture.cs b/tests/CommunityToolkit.Aspire.KurrentDB.Tests/KurrentDBContainerFixture.cs
index 9dfa41495..8bba0a4b5 100644
--- a/tests/CommunityToolkit.Aspire.KurrentDB.Tests/KurrentDBContainerFixture.cs
+++ b/tests/CommunityToolkit.Aspire.KurrentDB.Tests/KurrentDBContainerFixture.cs
@@ -3,6 +3,7 @@
using Aspire.Components.Common.Tests;
using CommunityToolkit.Aspire.Hosting.KurrentDB;
+using CommunityToolkit.Aspire.Testing;
using DotNet.Testcontainers.Builders;
using DotNet.Testcontainers.Containers;
@@ -22,7 +23,7 @@ public string GetConnectionString()
return $"{endpoint}?tls=false";
}
- public async Task InitializeAsync()
+ public async ValueTask InitializeAsync()
{
if (RequiresDockerAttribute.IsSupported)
{
@@ -39,7 +40,7 @@ public async Task InitializeAsync()
}
}
- public async Task DisposeAsync()
+ public async ValueTask DisposeAsync()
{
if (Container is not null)
{
diff --git a/tests/CommunityToolkit.Aspire.Meilisearch.Tests/AspireMeilisearchClientExtensionsTest.cs b/tests/CommunityToolkit.Aspire.Meilisearch.Tests/AspireMeilisearchClientExtensionsTest.cs
index 7048a0e42..add49d2e9 100644
--- a/tests/CommunityToolkit.Aspire.Meilisearch.Tests/AspireMeilisearchClientExtensionsTest.cs
+++ b/tests/CommunityToolkit.Aspire.Meilisearch.Tests/AspireMeilisearchClientExtensionsTest.cs
@@ -2,6 +2,7 @@
// The .NET Foundation licenses this file to you under the MIT license.
using Aspire.Components.Common.Tests;
+using CommunityToolkit.Aspire.Testing;
using Meilisearch;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
diff --git a/tests/CommunityToolkit.Aspire.Meilisearch.Tests/ConformanceTests.cs b/tests/CommunityToolkit.Aspire.Meilisearch.Tests/ConformanceTests.cs
index 684d5e764..b25d5cc9b 100644
--- a/tests/CommunityToolkit.Aspire.Meilisearch.Tests/ConformanceTests.cs
+++ b/tests/CommunityToolkit.Aspire.Meilisearch.Tests/ConformanceTests.cs
@@ -3,6 +3,7 @@
using Aspire.Components.Common.Tests;
using Aspire.Components.ConformanceTests;
+using CommunityToolkit.Aspire.Testing;
using Meilisearch;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
diff --git a/tests/CommunityToolkit.Aspire.Meilisearch.Tests/MeilisearchContainerFixture.cs b/tests/CommunityToolkit.Aspire.Meilisearch.Tests/MeilisearchContainerFixture.cs
index e263b9c52..4d7d13ef9 100644
--- a/tests/CommunityToolkit.Aspire.Meilisearch.Tests/MeilisearchContainerFixture.cs
+++ b/tests/CommunityToolkit.Aspire.Meilisearch.Tests/MeilisearchContainerFixture.cs
@@ -8,6 +8,7 @@
using DotNet.Testcontainers.Containers;
using Xunit;
using System.Linq.Expressions;
+using CommunityToolkit.Aspire.Testing;
namespace CommunityToolkit.Aspire.Meilisearch.Tests;
@@ -25,7 +26,7 @@ public string GetConnectionString()
return $"Endpoint={endpoint};MasterKey={_masterKey}";
}
- public async Task InitializeAsync()
+ public async ValueTask InitializeAsync()
{
if (RequiresDockerAttribute.IsSupported)
{
@@ -55,7 +56,7 @@ public async Task InitializeAsync()
}
}
- public async Task DisposeAsync()
+ public async ValueTask DisposeAsync()
{
if (Container is not null)
{
diff --git a/tests/CommunityToolkit.Aspire.Minio.Client.Tests/ConformanceTests.cs b/tests/CommunityToolkit.Aspire.Minio.Client.Tests/ConformanceTests.cs
index 5012126fb..442732cf8 100644
--- a/tests/CommunityToolkit.Aspire.Minio.Client.Tests/ConformanceTests.cs
+++ b/tests/CommunityToolkit.Aspire.Minio.Client.Tests/ConformanceTests.cs
@@ -1,5 +1,6 @@
using Aspire.Components.Common.Tests;
using Aspire.Components.ConformanceTests;
+using CommunityToolkit.Aspire.Testing;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Hosting;
using Minio;
diff --git a/tests/CommunityToolkit.Aspire.Minio.Client.Tests/MinioContainerFeature.cs b/tests/CommunityToolkit.Aspire.Minio.Client.Tests/MinioContainerFeature.cs
index 3feee2c66..01c92b12a 100644
--- a/tests/CommunityToolkit.Aspire.Minio.Client.Tests/MinioContainerFeature.cs
+++ b/tests/CommunityToolkit.Aspire.Minio.Client.Tests/MinioContainerFeature.cs
@@ -1,5 +1,6 @@
using Aspire.Components.Common.Tests;
using CommunityToolkit.Aspire.Hosting.Minio;
+using CommunityToolkit.Aspire.Testing;
using DotNet.Testcontainers.Builders;
using DotNet.Testcontainers.Containers;
@@ -19,7 +20,7 @@ public string GetContainerEndpoint()
return endpoint;
}
- public async Task InitializeAsync()
+ public async ValueTask InitializeAsync()
{
if (RequiresDockerAttribute.IsSupported)
{
@@ -39,7 +40,7 @@ public async Task InitializeAsync()
}
}
- public async Task DisposeAsync()
+ public async ValueTask DisposeAsync()
{
if (Container is not null)
{
diff --git a/tests/CommunityToolkit.Aspire.OllamaSharp.Tests/ConformanceTests.cs b/tests/CommunityToolkit.Aspire.OllamaSharp.Tests/ConformanceTests.cs
index f6d784e0c..42229f208 100644
--- a/tests/CommunityToolkit.Aspire.OllamaSharp.Tests/ConformanceTests.cs
+++ b/tests/CommunityToolkit.Aspire.OllamaSharp.Tests/ConformanceTests.cs
@@ -1,5 +1,6 @@
using Aspire.Components.Common.Tests;
using Aspire.Components.ConformanceTests;
+using CommunityToolkit.Aspire.Testing;
using Microsoft.Extensions.AI;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Hosting;
diff --git a/tests/CommunityToolkit.Aspire.OllamaSharp.Tests/OllamaContainerFeature.cs b/tests/CommunityToolkit.Aspire.OllamaSharp.Tests/OllamaContainerFeature.cs
index 2df093fad..93fe77692 100644
--- a/tests/CommunityToolkit.Aspire.OllamaSharp.Tests/OllamaContainerFeature.cs
+++ b/tests/CommunityToolkit.Aspire.OllamaSharp.Tests/OllamaContainerFeature.cs
@@ -1,5 +1,6 @@
using Aspire.Components.Common.Tests;
using CommunityToolkit.Aspire.Hosting.Ollama;
+using CommunityToolkit.Aspire.Testing;
using DotNet.Testcontainers.Builders;
using DotNet.Testcontainers.Containers;
@@ -18,7 +19,7 @@ public string GetContainerEndpoint()
return endpoint;
}
- public async Task InitializeAsync()
+ public async ValueTask InitializeAsync()
{
if (RequiresDockerAttribute.IsSupported)
{
@@ -32,7 +33,7 @@ public async Task InitializeAsync()
}
}
- public async Task DisposeAsync()
+ public async ValueTask DisposeAsync()
{
if (Container is not null)
{
diff --git a/tests/CommunityToolkit.Aspire.RavenDB.Client.Tests/CommunityToolkit.Aspire.RavenDB.Client.Tests.csproj b/tests/CommunityToolkit.Aspire.RavenDB.Client.Tests/CommunityToolkit.Aspire.RavenDB.Client.Tests.csproj
index b4528f844..55c1a5d46 100644
--- a/tests/CommunityToolkit.Aspire.RavenDB.Client.Tests/CommunityToolkit.Aspire.RavenDB.Client.Tests.csproj
+++ b/tests/CommunityToolkit.Aspire.RavenDB.Client.Tests/CommunityToolkit.Aspire.RavenDB.Client.Tests.csproj
@@ -2,8 +2,6 @@
Exe
- enable
- enable
diff --git a/tests/CommunityToolkit.Aspire.RavenDB.Client.Tests/RavenDbServerFixture.cs b/tests/CommunityToolkit.Aspire.RavenDB.Client.Tests/RavenDbServerFixture.cs
index 2df45c921..0e9dda06d 100644
--- a/tests/CommunityToolkit.Aspire.RavenDB.Client.Tests/RavenDbServerFixture.cs
+++ b/tests/CommunityToolkit.Aspire.RavenDB.Client.Tests/RavenDbServerFixture.cs
@@ -9,7 +9,7 @@ public sealed class RavenDbServerFixture : IAsyncLifetime, IDisposable
public IDocumentStore? Store { get; private set; }
public string? ConnectionString { get; private set; }
- public async Task InitializeAsync()
+ public async ValueTask InitializeAsync()
{
Server.StartServer();
@@ -28,10 +28,10 @@ public void CreateDatabase(DatabaseOptions options)
Store = Server.GetDocumentStore(options);
}
- public Task DisposeAsync()
+ public ValueTask DisposeAsync()
{
Dispose();
- return Task.CompletedTask;
+ return ValueTask.CompletedTask;
}
public void Dispose()
diff --git a/tests/CommunityToolkit.Aspire.SurrealDb.Tests/AspireSurrealClientExtensionsTest.cs b/tests/CommunityToolkit.Aspire.SurrealDb.Tests/AspireSurrealClientExtensionsTest.cs
index 20ab869b0..bbb8c6e2c 100644
--- a/tests/CommunityToolkit.Aspire.SurrealDb.Tests/AspireSurrealClientExtensionsTest.cs
+++ b/tests/CommunityToolkit.Aspire.SurrealDb.Tests/AspireSurrealClientExtensionsTest.cs
@@ -2,6 +2,7 @@
// The .NET Foundation licenses this file to you under the MIT license.
using Aspire.Components.Common.Tests;
+using CommunityToolkit.Aspire.Testing;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Diagnostics.HealthChecks;
using Microsoft.Extensions.Hosting;
diff --git a/tests/CommunityToolkit.Aspire.SurrealDb.Tests/ConformanceTests.cs b/tests/CommunityToolkit.Aspire.SurrealDb.Tests/ConformanceTests.cs
index 276b7359b..08debf7b6 100644
--- a/tests/CommunityToolkit.Aspire.SurrealDb.Tests/ConformanceTests.cs
+++ b/tests/CommunityToolkit.Aspire.SurrealDb.Tests/ConformanceTests.cs
@@ -3,6 +3,7 @@
using Aspire.Components.Common.Tests;
using Aspire.Components.ConformanceTests;
+using CommunityToolkit.Aspire.Testing;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Hosting;
using SurrealDb.Net;
@@ -103,6 +104,6 @@ protected override void TriggerActivity(SurrealDbClient service)
{
using var source = new CancellationTokenSource(100);
- service.Version(source.Token).Wait();
+ Task.Run(() => service.Connect());
}
}
\ No newline at end of file
diff --git a/tests/CommunityToolkit.Aspire.SurrealDb.Tests/SurrealDbContainerFixture.cs b/tests/CommunityToolkit.Aspire.SurrealDb.Tests/SurrealDbContainerFixture.cs
index 560d17e75..9be69e084 100644
--- a/tests/CommunityToolkit.Aspire.SurrealDb.Tests/SurrealDbContainerFixture.cs
+++ b/tests/CommunityToolkit.Aspire.SurrealDb.Tests/SurrealDbContainerFixture.cs
@@ -4,6 +4,7 @@
using Aspire.Components.Common.Tests;
using Aspire.Hosting;
using Aspire.Hosting.Utils;
+using CommunityToolkit.Aspire.Testing;
using DotNet.Testcontainers.Builders;
using DotNet.Testcontainers.Containers;
@@ -28,7 +29,7 @@ public string GetConnectionString()
return $"Endpoint={endpoint};Username={_username};Password={_password}";
}
- public async Task InitializeAsync()
+ public async ValueTask InitializeAsync()
{
if (RequiresDockerAttribute.IsSupported)
{
@@ -60,7 +61,7 @@ public async Task InitializeAsync()
}
}
- public async Task DisposeAsync()
+ public async ValueTask DisposeAsync()
{
if (Container is not null)
{
diff --git a/tests/CommunityToolkit.Aspire.Testing/AspireIntegrationTest.cs b/tests/CommunityToolkit.Aspire.Testing/AspireIntegrationTest.cs
index 823ab73c0..29f3ab61b 100644
--- a/tests/CommunityToolkit.Aspire.Testing/AspireIntegrationTest.cs
+++ b/tests/CommunityToolkit.Aspire.Testing/AspireIntegrationTest.cs
@@ -71,7 +71,5 @@ public async override ValueTask DisposeAsync()
}
}
- public Task InitializeAsync() => StartAsync().WaitAsync(TimeSpan.FromMinutes(10));
-
- async Task IAsyncLifetime.DisposeAsync() => await DisposeAsync();
+ public async ValueTask InitializeAsync() => await StartAsync().WaitAsync(TimeSpan.FromMinutes(10));
}
\ No newline at end of file
diff --git a/tests/CommunityToolkit.Aspire.Testing/CommunityToolkit.Aspire.Testing.csproj b/tests/CommunityToolkit.Aspire.Testing/CommunityToolkit.Aspire.Testing.csproj
index 50850bb44..21c6798e5 100644
--- a/tests/CommunityToolkit.Aspire.Testing/CommunityToolkit.Aspire.Testing.csproj
+++ b/tests/CommunityToolkit.Aspire.Testing/CommunityToolkit.Aspire.Testing.csproj
@@ -13,11 +13,12 @@
See https://xunit.github.io/docs/nuget-packages and the special note in https://xunit.github.io/releases/2.3.
-->
-
-
+
+
+
diff --git a/tests/CommunityToolkit.Aspire.Testing/ConformanceTests.cs b/tests/CommunityToolkit.Aspire.Testing/ConformanceTests.cs
index fb5f9e35d..13e8441a8 100644
--- a/tests/CommunityToolkit.Aspire.Testing/ConformanceTests.cs
+++ b/tests/CommunityToolkit.Aspire.Testing/ConformanceTests.cs
@@ -3,9 +3,7 @@
using System.Diagnostics;
using System.Text.Json.Nodes;
-using Microsoft.DotNet.XUnitExtensions;
using Microsoft.Extensions.Configuration;
-using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Diagnostics.HealthChecks;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
@@ -13,6 +11,8 @@
using OpenTelemetry.Metrics;
using OpenTelemetry.Trace;
using Xunit;
+using Aspire.Components.Common.Tests;
+using Microsoft.DotNet.XUnitExtensions;
namespace Aspire.Components.ConformanceTests;
@@ -45,6 +45,8 @@ public abstract class ConformanceTests
protected virtual bool SupportsKeyedRegistrations => false;
+ protected virtual bool IsComponentBuiltBeforeHost => false;
+
protected bool MetricsAreSupported => CheckIfImplemented(SetMetrics);
// every Component has to support health checks, this property is a temporary workaround
@@ -54,6 +56,8 @@ protected virtual void DisableRetries(TOptions options) { }
protected bool TracingIsSupported => CheckIfImplemented(SetTracing);
+ protected virtual bool CheckOptionClassSealed => true;
+
///
/// Calls the actual Component
///
@@ -85,18 +89,23 @@ protected virtual void DisableRetries(TOptions options) { }
///
protected abstract void SetMetrics(TOptions options, bool enabled);
- [ConditionalFact]
+ [Fact]
public void OptionsTypeIsSealed()
{
if (typeof(TOptions) == typeof(object))
{
- throw new SkipTestException("Not implemented yet");
+ Assert.Skip("Not implemented yet");
+ }
+
+ if (!CheckOptionClassSealed)
+ {
+ Assert.Skip("Opt-out of test");
}
Assert.True(typeof(TOptions).IsSealed);
}
- [ConditionalTheory]
+ [Theory]
[InlineData(true)]
[InlineData(false)]
public void HealthChecksRegistersHealthCheckService(bool enabled)
@@ -110,7 +119,7 @@ public void HealthChecksRegistersHealthCheckService(bool enabled)
Assert.Equal(enabled, healthCheckService is not null);
}
- [ConditionalFact]
+ [Fact]
public async Task EachKeyedComponentRegistersItsOwnHealthCheck()
{
SkipIfHealthChecksAreNotSupported();
@@ -124,16 +133,18 @@ public async Task EachKeyedComponentRegistersItsOwnHealthCheck()
List registeredNames = new();
await healthCheckService.CheckHealthAsync(healthCheckRegistration =>
+#pragma warning disable xUnit1030 // Do not call ConfigureAwait(false) in test method
{
registeredNames.Add(healthCheckRegistration.Name);
return false;
}).ConfigureAwait(false);
+#pragma warning restore xUnit1030 // Do not call ConfigureAwait(false) in test method
Assert.Equal(2, registeredNames.Count);
Assert.All(registeredNames, name => Assert.True(name.Contains(key1) || name.Contains(key2), $"{name} did not contain the key."));
}
- [ConditionalTheory]
+ [Theory]
[InlineData(true)]
[InlineData(false)]
public void TracingRegistersTraceProvider(bool enabled)
@@ -148,7 +159,7 @@ public void TracingRegistersTraceProvider(bool enabled)
Assert.Equal(enabled, tracer is not null);
}
- [ConditionalTheory]
+ [Theory]
[InlineData(true)]
[InlineData(false)]
public void MetricsRegistersMeterProvider(bool enabled)
@@ -162,7 +173,7 @@ public void MetricsRegistersMeterProvider(bool enabled)
Assert.Equal(enabled, meter is not null);
}
- [ConditionalTheory]
+ [Theory]
[InlineData(true)]
[InlineData(false)]
public void ServiceLifetimeIsAsExpected(bool useKey)
@@ -213,7 +224,7 @@ public void ServiceLifetimeIsAsExpected(bool useKey)
: serviceProvider.GetKeyedService(key);
}
- [ConditionalFact]
+ [Fact]
public void CanRegisterMultipleInstancesUsingDifferentKeys()
{
SkipIfKeyedRegistrationIsNotSupported();
@@ -229,7 +240,7 @@ public void CanRegisterMultipleInstancesUsingDifferentKeys()
Assert.NotSame(serviceForKey1, serviceForKey2);
}
- [ConditionalFact]
+ [Fact]
public void WhenKeyedRegistrationIsUsedThenItsImpossibleToResolveWithoutKey()
{
SkipIfKeyedRegistrationIsNotSupported();
@@ -249,7 +260,7 @@ public void WhenKeyedRegistrationIsUsedThenItsImpossibleToResolveWithoutKey()
Assert.Throws(host.Services.GetRequiredService);
}
- [ConditionalTheory]
+ [Theory]
[InlineData(true, true)]
[InlineData(true, false)]
[InlineData(false, true)]
@@ -259,11 +270,6 @@ public void LoggerFactoryIsUsedByRegisteredClient(bool registerAfterLoggerFactor
SkipIfRequiredServerConnectionCanNotBeEstablished();
SkipIfKeyedRegistrationIsNotSupported(useKey);
- if (RequiredLogCategories.Length == 0 && NotAcceptableLogCategories.Length == 0)
- {
- throw new SkipTestException("No log categories specified to test against.");
- }
-
string? key = useKey ? "key" : null;
HostApplicationBuilder builder = CreateHostBuilder(key: key);
@@ -303,21 +309,21 @@ public void LoggerFactoryIsUsedByRegisteredClient(bool registerAfterLoggerFactor
}
}
- [ConditionalTheory]
+ [Theory]
[InlineData(null)]
[InlineData("key")]
- public async Task HealthCheckReportsExpectedStatus(string? key)
+ public virtual async Task HealthCheckReportsExpectedStatus(string? key)
{
SkipIfHealthChecksAreNotSupported();
// DisableRetries so the test doesn't take so long retrying when the server isn't available.
using IHost host = CreateHostWithComponent(configureComponent: DisableRetries, key: key);
- HealthCheckService healthCheckService = host.Services.GetRequiredService();
+ var healthCheckService = host.Services.GetRequiredService();
- HealthReport healthReport = await healthCheckService.CheckHealthAsync().ConfigureAwait(false);
+ var healthReport = await healthCheckService.CheckHealthAsync();
- HealthStatus expected = CanConnectToServer ? HealthStatus.Healthy : HealthStatus.Unhealthy;
+ var expected = CanConnectToServer ? HealthStatus.Healthy : HealthStatus.Unhealthy;
Assert.Equal(expected, healthReport.Status);
Assert.NotEmpty(healthReport.Entries);
@@ -355,13 +361,14 @@ public void ConfigurationSchemaInvalidJsonConfigTest()
/// Ensures that when the connection information is missing, an exception isn't thrown before the host
/// is built, so any exception can be logged with ILogger.
///
- [ConditionalTheory]
+ [Theory]
[InlineData(true)]
[InlineData(false)]
public void ConnectionInformationIsDelayValidated(bool useKey)
{
+ SkipIfComponentIsBuiltBeforeHost();
+
SetupConnectionInformationIsDelayValidated();
- SkipIfKeyedRegistrationIsNotSupported(useKey);
var builder = Host.CreateEmptyApplicationBuilder(null);
@@ -376,7 +383,7 @@ key is null
: host.Services.GetRequiredKeyedService(key));
}
- [ConditionalFact]
+ [Fact]
public void FavorsNamedConfigurationOverTopLevelConfigurationWhenBothProvided_DisableTracing()
{
SkipIfNamedConfigNotSupported();
@@ -398,7 +405,7 @@ public void FavorsNamedConfigurationOverTopLevelConfigurationWhenBothProvided_Di
Assert.Null(host.Services.GetService());
}
- [ConditionalFact]
+ [Fact]
public void FavorsNamedConfigurationOverTopLevelConfigurationWhenBothProvided_DisableHealthChecks()
{
SkipIfNamedConfigNotSupported();
@@ -486,7 +493,7 @@ protected void SkipIfHealthChecksAreNotSupported()
{
if (!HealthChecksAreSupported)
{
- throw new SkipTestException("Health checks aren't supported.");
+ Assert.Skip("Health checks aren't supported.");
}
}
@@ -494,7 +501,7 @@ protected void SkipIfKeyedRegistrationIsNotSupported(bool useKey = true)
{
if (useKey && !SupportsKeyedRegistrations)
{
- throw new SkipTestException("Does not support Keyed Services");
+ Assert.Skip("Does not support Keyed Services");
}
}
@@ -502,7 +509,7 @@ protected void SkipIfTracingIsNotSupported()
{
if (!TracingIsSupported)
{
- throw new SkipTestException("Tracing is not supported.");
+ Assert.Skip("Tracing is not supported.");
}
}
@@ -510,7 +517,7 @@ protected void SkipIfMetricsAreNotSupported()
{
if (!MetricsAreSupported)
{
- throw new SkipTestException("Metrics are not supported.");
+ Assert.Skip("Metrics are not supported.");
}
}
@@ -518,7 +525,7 @@ protected void SkipIfRequiredServerConnectionCanNotBeEstablished()
{
if (!CanCreateClientWithoutConnectingToServer && !CanConnectToServer)
{
- throw new SkipTestException("Unable to connect to the server.");
+ Assert.Skip("Unable to connect to the server.");
}
}
@@ -526,7 +533,7 @@ protected void SkipIfCanNotConnectToServer()
{
if (!CanConnectToServer)
{
- throw new SkipTestException("Unable to connect to the server.");
+ Assert.Skip("Unable to connect to the server.");
}
}
@@ -534,13 +541,21 @@ protected void SkipIfNamedConfigNotSupported()
{
if (!SupportsNamedConfig || ConfigurationSectionName is null)
{
- throw new SkipTestException("Named configuration is not supported.");
+ Assert.Skip("Named configuration is not supported.");
}
}
public static string CreateConfigKey(string prefix, string? key, string suffix)
=> string.IsNullOrEmpty(key) ? $"{prefix}:{suffix}" : $"{prefix}:{key}:{suffix}";
+ protected void SkipIfComponentIsBuiltBeforeHost()
+ {
+ if (IsComponentBuiltBeforeHost)
+ {
+ Assert.Skip("Component is built before host.");
+ }
+ }
+
protected HostApplicationBuilder CreateHostBuilder(HostApplicationBuilderSettings? hostSettings = null, string? key = null)
{
HostApplicationBuilder builder = Host.CreateEmptyApplicationBuilder(hostSettings);
diff --git a/tests/CommunityToolkit.Aspire.Testing/DistributedApplicationTestingBuilderExtensions.cs b/tests/CommunityToolkit.Aspire.Testing/DistributedApplicationTestingBuilderExtensions.cs
index 1b7d0bb5c..c7d12af9d 100644
--- a/tests/CommunityToolkit.Aspire.Testing/DistributedApplicationTestingBuilderExtensions.cs
+++ b/tests/CommunityToolkit.Aspire.Testing/DistributedApplicationTestingBuilderExtensions.cs
@@ -5,7 +5,6 @@
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Xunit;
-using Xunit.Abstractions;
namespace Aspire.Hosting.Utils;
diff --git a/tests/CommunityToolkit.Aspire.Testing/PlatformDetection.cs b/tests/CommunityToolkit.Aspire.Testing/PlatformDetection.cs
index 9f29acb39..b342739ec 100644
--- a/tests/CommunityToolkit.Aspire.Testing/PlatformDetection.cs
+++ b/tests/CommunityToolkit.Aspire.Testing/PlatformDetection.cs
@@ -2,5 +2,10 @@ namespace Aspire.Components.Common.Tests;
public static class PlatformDetection
{
- public static bool IsRunningOnCI => Environment.GetEnvironmentVariable("CI") is not null;
-}
\ No newline at end of file
+ public static bool IsRunningOnGithubActions => Environment.GetEnvironmentVariable("GITHUB_JOB") is not null;
+ public static bool IsRunningOnCI => IsRunningOnGithubActions || Environment.GetEnvironmentVariable("CI") is not null;
+
+ public static bool IsWindows => OperatingSystem.IsWindows();
+ public static bool IsLinux => OperatingSystem.IsLinux();
+ public static bool IsMacOS => OperatingSystem.IsMacOS();
+}
diff --git a/tests/CommunityToolkit.Aspire.Testing/RequiresAuthenticatedToolAttribute.cs b/tests/CommunityToolkit.Aspire.Testing/RequiresAuthenticatedToolAttribute.cs
index 2a343d15e..0b53638b3 100644
--- a/tests/CommunityToolkit.Aspire.Testing/RequiresAuthenticatedToolAttribute.cs
+++ b/tests/CommunityToolkit.Aspire.Testing/RequiresAuthenticatedToolAttribute.cs
@@ -1,5 +1,6 @@
using Aspire.Components.Common.Tests;
-using Xunit.Sdk;
+using Microsoft.DotNet.XUnitExtensions;
+using Xunit.v3;
namespace CommunityToolkit.Aspire.Testing;
@@ -7,7 +8,6 @@ namespace CommunityToolkit.Aspire.Testing;
/// Marks a test or test class as requiring an authenticated external tool.
/// Adds a trait to propagate the required tool name to the xUnit pipeline.
///
-[TraitDiscoverer("CommunityToolkit.Aspire.Testing.RequiresAuthenticatedToolDiscoverer", "CommunityToolkit.Aspire.Testing")]
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = true)]
public sealed class RequiresAuthenticatedToolAttribute : Attribute, ITraitAttribute
{
@@ -34,4 +34,16 @@ public RequiresAuthenticatedToolAttribute(string toolName, string? reason = null
/// Gets a value indicating whether authenticated tools are supported in the current environment.
public static bool IsSupported => !PlatformDetection.IsRunningOnCI;
+
+ public IReadOnlyCollection> GetTraits()
+ {
+ IReadOnlyCollection> traits = [new("RequiresTools", ToolName)];
+
+ if (!IsSupported)
+ {
+ traits = [.. traits, new KeyValuePair(XunitConstants.Category, "failing")];
+ }
+
+ return traits;
+ }
}
diff --git a/tests/CommunityToolkit.Aspire.Testing/RequiresAuthenticatedToolDiscoverer.cs b/tests/CommunityToolkit.Aspire.Testing/RequiresAuthenticatedToolDiscoverer.cs
deleted file mode 100644
index 9acb5b20b..000000000
--- a/tests/CommunityToolkit.Aspire.Testing/RequiresAuthenticatedToolDiscoverer.cs
+++ /dev/null
@@ -1,36 +0,0 @@
-using Xunit.Abstractions;
-using Xunit.Sdk;
-
-namespace CommunityToolkit.Aspire.Testing;
-
-///
-/// Discovers traits for .
-/// Adds a RequiresTools trait with the tool name and
-/// categorizes tests as unsupported-platform when authenticated tools are not supported.
-///
-public sealed class RequiresAuthenticatedToolDiscoverer : ITraitDiscoverer
-{
- ///
- public IEnumerable> GetTraits(IAttributeInfo traitAttribute)
- {
- string? toolName = null;
- foreach (object? argument in traitAttribute.GetConstructorArguments().Where(a => a is string))
- {
- if (argument is string value)
- {
- toolName = value;
- break;
- }
- }
-
- if (!string.IsNullOrWhiteSpace(toolName))
- {
- yield return new KeyValuePair("RequiresTools", toolName);
- }
-
- if (!RequiresAuthenticatedToolAttribute.IsSupported)
- {
- yield return new KeyValuePair("category", "unsupported-platform");
- }
- }
-}
diff --git a/tests/CommunityToolkit.Aspire.Testing/RequiresDockerAttribute.cs b/tests/CommunityToolkit.Aspire.Testing/RequiresDockerAttribute.cs
index f604b16a5..fbecc0bd1 100644
--- a/tests/CommunityToolkit.Aspire.Testing/RequiresDockerAttribute.cs
+++ b/tests/CommunityToolkit.Aspire.Testing/RequiresDockerAttribute.cs
@@ -1,13 +1,12 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
-// Copied from: https://github.com/dotnet/aspire/blob/d31331d6132aeb22940dcd8834344956ba811373/tests/Aspire.Components.Common.Tests/RequiresDockerAttribute.cs
+using Aspire.Components.Common.Tests;
+using Microsoft.DotNet.XUnitExtensions;
+using Xunit.v3;
-using Xunit.Sdk;
+namespace CommunityToolkit.Aspire.Testing;
-namespace Aspire.Components.Common.Tests;
-
-[TraitDiscoverer("Aspire.Components.Common.Tests.RequiresDockerDiscoverer", "CommunityToolkit.Aspire.Testing")]
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false)]
public class RequiresDockerAttribute : Attribute, ITraitAttribute
{
@@ -23,12 +22,21 @@ public class RequiresDockerAttribute : Attribute, ITraitAttribute
// - https://github.com/dotnet/aspire/issues/4291
// - Linux - Local, or CI: always assume that docker is installed
public static bool IsSupported =>
- OperatingSystem.IsLinux() ||
- !PlatformDetection.IsRunningOnCI;
+ OperatingSystem.IsLinux() || !PlatformDetection.IsRunningOnCI; // non-linux on CI does not support docker
public string? Reason { get; init; }
public RequiresDockerAttribute(string? reason = null)
{
Reason = reason;
}
-}
+
+ public IReadOnlyCollection> GetTraits()
+ {
+ if (!IsSupported)
+ {
+ return [new KeyValuePair(XunitConstants.Category, "failing")];
+ }
+
+ return [];
+ }
+}
\ No newline at end of file
diff --git a/tests/CommunityToolkit.Aspire.Testing/RequiresDockerDiscoverer.cs b/tests/CommunityToolkit.Aspire.Testing/RequiresDockerDiscoverer.cs
deleted file mode 100644
index 64ef21d97..000000000
--- a/tests/CommunityToolkit.Aspire.Testing/RequiresDockerDiscoverer.cs
+++ /dev/null
@@ -1,20 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-
-// Copied from: https://github.com/dotnet/aspire/blob/d31331d6132aeb22940dcd8834344956ba811373/tests/Aspire.Components.Common.Tests/RequiresDockerDiscoverer.cs
-
-using Xunit.Abstractions;
-using Xunit.Sdk;
-
-namespace Aspire.Components.Common.Tests;
-
-public class RequiresDockerDiscoverer : ITraitDiscoverer
-{
- public IEnumerable> GetTraits(IAttributeInfo traitAttribute)
- {
- if (!RequiresDockerAttribute.IsSupported)
- {
- yield return new KeyValuePair("category", "unsupported-platform");
- }
- }
-}
\ No newline at end of file
diff --git a/tests/CommunityToolkit.Aspire.Testing/RequiresLinuxAttribute.cs b/tests/CommunityToolkit.Aspire.Testing/RequiresLinuxAttribute.cs
index a8c53fdc9..1fca3a5d6 100644
--- a/tests/CommunityToolkit.Aspire.Testing/RequiresLinuxAttribute.cs
+++ b/tests/CommunityToolkit.Aspire.Testing/RequiresLinuxAttribute.cs
@@ -1,4 +1,5 @@
-using Xunit.Sdk;
+using Microsoft.DotNet.XUnitExtensions;
+using Xunit.v3;
namespace CommunityToolkit.Aspire.Testing;
@@ -6,7 +7,6 @@ namespace CommunityToolkit.Aspire.Testing;
/// Marks a test or test class as requiring a Linux operating system.
/// Adds a trait so tests can be skipped or filtered when not running on Linux.
///
-[TraitDiscoverer("CommunityToolkit.Aspire.Testing.RequiresLinuxDiscoverer", "CommunityToolkit.Aspire.Testing")]
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false)]
public class RequiresLinuxAttribute(string? reason = null) : Attribute, ITraitAttribute
{
@@ -15,4 +15,14 @@ public class RequiresLinuxAttribute(string? reason = null) : Attribute, ITraitAt
/// Gets a value indicating whether the current OS is Linux.
public static bool IsSupported => OperatingSystem.IsLinux();
+
+ public IReadOnlyCollection> GetTraits()
+ {
+ if (!IsSupported)
+ {
+ return [new KeyValuePair(XunitConstants.Category, "failing")];
+ }
+
+ return [];
+ }
}
diff --git a/tests/CommunityToolkit.Aspire.Testing/RequiresLinuxDiscoverer.cs b/tests/CommunityToolkit.Aspire.Testing/RequiresLinuxDiscoverer.cs
deleted file mode 100644
index a252d5776..000000000
--- a/tests/CommunityToolkit.Aspire.Testing/RequiresLinuxDiscoverer.cs
+++ /dev/null
@@ -1,20 +0,0 @@
-using Xunit.Abstractions;
-using Xunit.Sdk;
-
-namespace CommunityToolkit.Aspire.Testing;
-
-///
-/// Discovers traits for .
-/// Adds a category trait of unsupported-platform when not running on Linux.
-///
-public class RequiresLinuxDiscoverer : ITraitDiscoverer
-{
- ///
- public IEnumerable> GetTraits(IAttributeInfo traitAttribute)
- {
- if (!RequiresLinuxAttribute.IsSupported)
- {
- yield return new KeyValuePair("category", "unsupported-platform");
- }
- }
-}
diff --git a/tests/CommunityToolkit.Aspire.Testing/RequiresWindowsAttribute.cs b/tests/CommunityToolkit.Aspire.Testing/RequiresWindowsAttribute.cs
index 16414031c..860299cc9 100644
--- a/tests/CommunityToolkit.Aspire.Testing/RequiresWindowsAttribute.cs
+++ b/tests/CommunityToolkit.Aspire.Testing/RequiresWindowsAttribute.cs
@@ -1,12 +1,28 @@
-using Xunit.Sdk;
+using Microsoft.DotNet.XUnitExtensions;
+using Xunit.v3;
namespace CommunityToolkit.Aspire.Testing;
-[TraitDiscoverer("CommunityToolkit.Aspire.Testing.RequiresWindowsDiscoverer", "CommunityToolkit.Aspire.Testing")]
+///
+/// Marks a test or test class as requiring a Linux operating system.
+/// Adds a trait so tests can be skipped or filtered when not running on Linux.
+///
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false)]
public class RequiresWindowsAttribute(string? reason = null) : Attribute, ITraitAttribute
{
+ /// Gets the optional reason why Windows is required.
public string? Reason { get; init; } = reason;
+ /// Gets a value indicating whether the current OS is Windows.
public static bool IsSupported => OperatingSystem.IsWindows();
+
+ public IReadOnlyCollection> GetTraits()
+ {
+ if (!IsSupported)
+ {
+ return [new KeyValuePair(XunitConstants.Category, "failing")];
+ }
+
+ return [];
+ }
}
diff --git a/tests/CommunityToolkit.Aspire.Testing/RequiresWindowsDiscoverer.cs b/tests/CommunityToolkit.Aspire.Testing/RequiresWindowsDiscoverer.cs
deleted file mode 100644
index ae20e801b..000000000
--- a/tests/CommunityToolkit.Aspire.Testing/RequiresWindowsDiscoverer.cs
+++ /dev/null
@@ -1,15 +0,0 @@
-using Xunit.Abstractions;
-using Xunit.Sdk;
-
-namespace CommunityToolkit.Aspire.Testing;
-
-public class RequiresWindowsDiscoverer : ITraitDiscoverer
-{
- public IEnumerable> GetTraits(IAttributeInfo traitAttribute)
- {
- if (!RequiresWindowsAttribute.IsSupported)
- {
- yield return new KeyValuePair("category", "unsupported-platform");
- }
- }
-}
\ No newline at end of file
diff --git a/tests/CommunityToolkit.Aspire.Testing/TestDistributedApplicationBuilder.cs b/tests/CommunityToolkit.Aspire.Testing/TestDistributedApplicationBuilder.cs
index aba9b5855..12b6fc6dd 100644
--- a/tests/CommunityToolkit.Aspire.Testing/TestDistributedApplicationBuilder.cs
+++ b/tests/CommunityToolkit.Aspire.Testing/TestDistributedApplicationBuilder.cs
@@ -3,7 +3,6 @@
// The .NET Foundation licenses this file to you under the MIT license.
using Aspire.Components.Common.TestUtilities;
-using Xunit.Abstractions;
namespace Aspire.Hosting.Utils;
diff --git a/tests/Directory.Build.props b/tests/Directory.Build.props
index 69221f9d8..c053eb938 100644
--- a/tests/Directory.Build.props
+++ b/tests/Directory.Build.props
@@ -3,16 +3,25 @@
$(DefaultTargetFramework)
+
+
+
+
+ $(NoWarn);xUnit1051
-
+
-
+
-
+
+
+
+
+
@@ -26,7 +35,14 @@
false
true
- $(MSBuildThisFileDirectory).runsettings
+
+
+
+
+ $(TestingPlatformCommandLineArguments) --ignore-exit-code 8 --filter-not-trait "category=failing"
+
+ true
\ No newline at end of file