diff --git a/.github/workflows/main-build.yaml b/.github/workflows/main-build.yaml index 2e98281b..3207e8b0 100644 --- a/.github/workflows/main-build.yaml +++ b/.github/workflows/main-build.yaml @@ -86,7 +86,7 @@ jobs: run: dotnet build --no-restore --configuration Release /p:TreatWarningsAsErrors=true - name: Run tests - run: dotnet test --no-build --configuration Release --verbosity normal --collect:"XPlat Code Coverage" --results-directory ./coverage + run: dotnet test --no-build --configuration Release --verbosity normal --results-directory ./coverage --coverage --coverage-output-format cobertura - name: Stop SonarQube env: @@ -99,7 +99,7 @@ jobs: - name: Upload coverage reports uses: codecov/codecov-action@v5 with: - files: ./coverage/**/coverage.cobertura.xml + files: ./coverage/**/*.cobertura.xml disable_search: true token: ${{ secrets.CODECOV_TOKEN }} fail_ci_if_error: true \ No newline at end of file diff --git a/.github/workflows/pr-build.yaml b/.github/workflows/pr-build.yaml index 1dc945b3..a9c8e0ff 100644 --- a/.github/workflows/pr-build.yaml +++ b/.github/workflows/pr-build.yaml @@ -107,7 +107,7 @@ jobs: run: dotnet build --no-restore --configuration Release /p:TreatWarningsAsErrors=true - name: Run tests - run: dotnet test --no-build --configuration Release --verbosity normal --collect:"XPlat Code Coverage" --results-directory ./coverage + run: dotnet test --no-build --configuration Release --verbosity normal --results-directory ./coverage --coverage --coverage-output-format cobertura - name: Stop SonarQube env: @@ -120,7 +120,7 @@ jobs: - name: Upload coverage reports uses: codecov/codecov-action@v5 with: - files: ./coverage/**/coverage.cobertura.xml + files: ./coverage/**/*.cobertura.xml disable_search: true token: ${{ secrets.CODECOV_TOKEN }} fail_ci_if_error: true diff --git a/CLAUDE.md b/CLAUDE.md index bb29332c..4de85d18 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -82,6 +82,64 @@ internal async Task MyTest( - Combine both: use `[AutoNSubstituteData]` with `[Frozen]` to inject configured mocks from a manual fixture +# Test Commands + +Task wrappers (recommended): + +```bash +task test:all # dotnet test (Release) +task test:verbose # dotnet test (detailed logs) +task test:coverage # dotnet test + coverage +task test:watch # dotnet watch ... test +``` + +Direct `dotnet` commands: +```bash +# Run the full test suite (solution-level) +DOTNET_NOLOGO=1 dotnet test --configuration Release + +# Faster inner loop: run a single target framework (projects are multi-targeted) +DOTNET_NOLOGO=1 dotnet test --configuration Release -f net10.0 + +# Run a single test project +DOTNET_NOLOGO=1 dotnet test \ + --project tests/MinimalLambda.UnitTests/MinimalLambda.UnitTests.csproj \ + --configuration Release -f net10.0 + +# Verbose output for debugging +DOTNET_NOLOGO=1 dotnet test --configuration Release --logger "console;verbosity=detailed" +``` + +Run a single test (xUnit v3 + Microsoft.Testing.Platform) + +This repo pins the test runner in `global.json`: + +```json +"test": {"runner": "Microsoft.Testing.Platform"} +``` + +```bash +# list tests (copy fully-qualified name) +DOTNET_NOLOGO=1 dotnet test \ + --project tests/MinimalLambda.UnitTests/MinimalLambda.UnitTests.csproj \ + -f net10.0 -v q \ + --list-tests --no-progress --no-ansi + +# run one test method +DOTNET_NOLOGO=1 dotnet test \ + --project tests/MinimalLambda.UnitTests/MinimalLambda.UnitTests.csproj \ + -f net10.0 -v q \ + --filter-method "MyNamespace.MyTestClass.MyTestMethod" \ + --minimum-expected-tests 1 \ + --no-progress --no-ansi + +# handy filters +DOTNET_NOLOGO=1 dotnet test --project tests/MinimalLambda.UnitTests/MinimalLambda.UnitTests.csproj -f net10.0 -v q \ + --filter-class "MyNamespace.MyTestClass" --minimum-expected-tests 1 --no-progress --no-ansi +DOTNET_NOLOGO=1 dotnet test --project tests/MinimalLambda.UnitTests/MinimalLambda.UnitTests.csproj -f net10.0 -v q \ + --filter-namespace "MyNamespace.Tests" --minimum-expected-tests 1 --no-progress --no-ansi +``` + # C# 14 Extension Members - Valid Syntax ## This is VALID C# 14 syntax - do NOT change it diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index a5021eb3..482713cd 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -293,8 +293,8 @@ dotnet test tests/MinimalLambda.UnitTests # Run with verbose output dotnet test --verbosity detailed -# Run with coverage (if configured) -dotnet test /p:CollectCoverage=true +# Run with coverage (MTP) +dotnet test --coverage --coverage-output-format cobertura ``` ### Test Requirements diff --git a/Directory.Packages.props b/Directory.Packages.props index 830af210..4df426c3 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -50,6 +50,7 @@ + diff --git a/global.json b/global.json index 672cfe47..4ea65709 100644 --- a/global.json +++ b/global.json @@ -1,6 +1,9 @@ { "sdk": { "rollForward": "latestMinor", - "version": "10.0.102" + "version": "10.0.101" + }, + "test": { + "runner": "Microsoft.Testing.Platform" } -} \ No newline at end of file +} diff --git a/opencode.json b/opencode.json new file mode 100644 index 00000000..81bc9f48 --- /dev/null +++ b/opencode.json @@ -0,0 +1,6 @@ +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "git": "ask" + } +} \ No newline at end of file diff --git a/src/MinimalLambda.Testing/LambdaApplicationFactory.cs b/src/MinimalLambda.Testing/LambdaApplicationFactory.cs index a10e0b2c..e2c5bbfc 100644 --- a/src/MinimalLambda.Testing/LambdaApplicationFactory.cs +++ b/src/MinimalLambda.Testing/LambdaApplicationFactory.cs @@ -286,6 +286,13 @@ private void ConfigureHostBuilder( if (string.IsNullOrEmpty(options.BootstrapOptions.RuntimeApiEndpoint)) options.BootstrapOptions.RuntimeApiEndpoint = "localhost"; }); + + services.PostConfigure(options => + { + var minShutdownTimeout = TimeSpan.FromSeconds(30); + if (options.ShutdownTimeout < minShutdownTimeout) + options.ShutdownTimeout = minShutdownTimeout; + }); }); // Build the host but DON'T start it - server will start it diff --git a/tasks/TestTasks.yml b/tasks/TestTasks.yml index 92b53388..6c25f337 100644 --- a/tasks/TestTasks.yml +++ b/tasks/TestTasks.yml @@ -14,7 +14,7 @@ tasks: silent: true cmds: - echo "🧪 Running unit tests" - - dotnet test --configuration Release --filter "Category=Unit" --no-build + - dotnet test --configuration Release --filter-trait "Category=Unit" --no-build - echo "✅ Unit tests completed!" coverage: @@ -22,7 +22,7 @@ tasks: silent: true cmds: - echo "📊 Running tests with coverage collection" - - dotnet test --configuration Release --collect:"XPlat Code Coverage" --no-build + - dotnet test --configuration Release --coverage --coverage-output-format cobertura --no-build - echo "✅ Coverage collection completed!" watch: @@ -30,7 +30,7 @@ tasks: silent: true cmds: - echo "👀 Starting test watch mode" - - dotnet watch --project tests/MinimalLambda.Tests test --configuration Release + - dotnet watch --project tests/MinimalLambda.UnitTests test --configuration Release verbose: desc: Run tests with detailed output for debugging diff --git a/tests/MinimalLambda.Envelopes.UnitTests/MinimalLambda.Envelopes.UnitTests.csproj b/tests/MinimalLambda.Envelopes.UnitTests/MinimalLambda.Envelopes.UnitTests.csproj index 3aedce4e..775bccf4 100644 --- a/tests/MinimalLambda.Envelopes.UnitTests/MinimalLambda.Envelopes.UnitTests.csproj +++ b/tests/MinimalLambda.Envelopes.UnitTests/MinimalLambda.Envelopes.UnitTests.csproj @@ -1,4 +1,4 @@ - + net8.0;net9.0;net10.0 preview @@ -17,6 +17,7 @@ + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/tests/MinimalLambda.OpenTelemetry.UnitTests/MinimalLambda.OpenTelemetry.UnitTests.csproj b/tests/MinimalLambda.OpenTelemetry.UnitTests/MinimalLambda.OpenTelemetry.UnitTests.csproj index e8940ea9..6e6496bd 100644 --- a/tests/MinimalLambda.OpenTelemetry.UnitTests/MinimalLambda.OpenTelemetry.UnitTests.csproj +++ b/tests/MinimalLambda.OpenTelemetry.UnitTests/MinimalLambda.OpenTelemetry.UnitTests.csproj @@ -1,4 +1,4 @@ - + net9.0;net10.0 preview @@ -26,6 +26,7 @@ + all diff --git a/tests/MinimalLambda.SourceGenerators.UnitTests/MinimalLambda.SourceGenerators.UnitTests.csproj b/tests/MinimalLambda.SourceGenerators.UnitTests/MinimalLambda.SourceGenerators.UnitTests.csproj index 56bd27fd..03343d24 100644 --- a/tests/MinimalLambda.SourceGenerators.UnitTests/MinimalLambda.SourceGenerators.UnitTests.csproj +++ b/tests/MinimalLambda.SourceGenerators.UnitTests/MinimalLambda.SourceGenerators.UnitTests.csproj @@ -1,4 +1,4 @@ - + net8.0;net9.0;net10.0 latest @@ -18,6 +18,7 @@ + diff --git a/tests/MinimalLambda.Testing.UnitTests/Tests/MinimalLambda.Testing.UnitTests/MinimalLambda.Testing.UnitTests.csproj b/tests/MinimalLambda.Testing.UnitTests/Tests/MinimalLambda.Testing.UnitTests/MinimalLambda.Testing.UnitTests.csproj index b9a2609d..ef7cfe69 100644 --- a/tests/MinimalLambda.Testing.UnitTests/Tests/MinimalLambda.Testing.UnitTests/MinimalLambda.Testing.UnitTests.csproj +++ b/tests/MinimalLambda.Testing.UnitTests/Tests/MinimalLambda.Testing.UnitTests/MinimalLambda.Testing.UnitTests.csproj @@ -1,4 +1,4 @@ - + net8.0;net9.0;net10.0 enable @@ -23,6 +23,7 @@ + all diff --git a/tests/MinimalLambda.UnitTests/MinimalLambda.UnitTests.csproj b/tests/MinimalLambda.UnitTests/MinimalLambda.UnitTests.csproj index 7cf404d3..20855508 100644 --- a/tests/MinimalLambda.UnitTests/MinimalLambda.UnitTests.csproj +++ b/tests/MinimalLambda.UnitTests/MinimalLambda.UnitTests.csproj @@ -1,4 +1,4 @@ - + net8.0;net9.0;net10.0 enable @@ -33,6 +33,7 @@ + all runtime; build; native; contentfiles; analyzers; buildtransitive