diff --git a/CHANGELOG.md b/CHANGELOG.md
index 6418cad..c147c0f 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -7,6 +7,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [Unreleased]
+## [2.2.2] - 2026-08-16
+
+### Changed
+- **Tests:** migrate to **xunit.v3** **4.0.0** + **Microsoft Testing Platform** only (`src/global.json` `test.runner`; no VSTest / **coverlet.collector** / **Microsoft.NET.Test.Sdk** / **xunit.runner.visualstudio**). Use **coverlet.MTP**; **TestRunner** always uses `--coverlet`.
+- Package version **2.2.2**.
+
## [2.2.1] - 2026-08-14
### Changed
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 1f69ead..3ac09aa 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -35,6 +35,8 @@ pwsh -File .\utils\engines\test\Invoke-TestEngine.ps1
Or double-click `utils\Invoke-TestEngine.bat`.
+Tests run under **Microsoft Testing Platform** (`src/global.json` `test.runner`) with **xunit.v3** and **coverlet.MTP**.
+
Quick local run:
```bash
diff --git a/README.md b/README.md
index 3797f45..7339582 100644
--- a/README.md
+++ b/README.md
@@ -1,8 +1,8 @@
# MaksIT.Dapr
-
-
-
+
+
+
NuGet facade over [Dapr](https://dapr.io/) for ASP.NET Core: pub/sub, state, invocation, bindings, secrets, configuration, cryptography, sidecar, lock, HA work leases, actors, and workflows — all with `MaksIT.Results` outcomes.
@@ -76,7 +76,7 @@ dotnet add package MaksIT.Dapr
Or in your `.csproj`:
```xml
-
+
```
## Registering services
diff --git a/src/MaksIT.Dapr.Tests/MaksIT.Dapr.Tests.csproj b/src/MaksIT.Dapr.Tests/MaksIT.Dapr.Tests.csproj
index e607b04..0347bda 100644
--- a/src/MaksIT.Dapr.Tests/MaksIT.Dapr.Tests.csproj
+++ b/src/MaksIT.Dapr.Tests/MaksIT.Dapr.Tests.csproj
@@ -5,18 +5,16 @@
enable
enable
false
+ true
+ Exe
+ true
$(NoWarn);xUnit1051
-
- all
- runtime; build; native; contentfiles; analyzers; buildtransitive
-
-
+
-
-
+
diff --git a/src/MaksIT.Dapr/MaksIT.Dapr.csproj b/src/MaksIT.Dapr/MaksIT.Dapr.csproj
index 2b27a4b..b10b434 100644
--- a/src/MaksIT.Dapr/MaksIT.Dapr.csproj
+++ b/src/MaksIT.Dapr/MaksIT.Dapr.csproj
@@ -8,7 +8,7 @@
MaksIT.Dapr
- 2.2.1
+ 2.2.2
Maksym Sadovnychyy
MAKS-IT
MaksIT.Dapr
diff --git a/src/global.json b/src/global.json
new file mode 100644
index 0000000..3140116
--- /dev/null
+++ b/src/global.json
@@ -0,0 +1,5 @@
+{
+ "test": {
+ "runner": "Microsoft.Testing.Platform"
+ }
+}
diff --git a/utils/modules/TestRunner.psm1 b/utils/modules/TestRunner.psm1
index aac3308..d1e2eea 100644
--- a/utils/modules/TestRunner.psm1
+++ b/utils/modules/TestRunner.psm1
@@ -7,7 +7,7 @@
.DESCRIPTION
Provides the Invoke-TestsWithCoverage function for running .NET tests
- with Coverlet code coverage collection and parsing results.
+ with Microsoft.Testing.Platform and coverlet.MTP code coverage.
.NOTES
Author: MaksIT
@@ -65,6 +65,20 @@ function Write-TestRunnerLogInternal {
Write-Host $Message -ForegroundColor Gray
}
+function Get-CoberturaCoverageFiles {
+ param(
+ [Parameter(Mandatory = $true)]
+ [string]$ResultsDirectory
+ )
+
+ # coverlet.MTP: [prefix.]coverage.cobertura[.timestamp].xml
+ $files = @(
+ Get-ChildItem -Path $ResultsDirectory -Recurse -File -ErrorAction SilentlyContinue |
+ Where-Object { $_.Name -like '*coverage.cobertura*.xml' }
+ )
+ return @($files | Sort-Object FullName -Unique)
+}
+
function Invoke-TestsWithCoverage {
<#
.SYNOPSIS
@@ -155,7 +169,7 @@ function Invoke-TestsWithCoverage {
New-Item -ItemType Directory -Path $ResultsDir -Force | Out-Null
if (-not $Silent) {
- Write-TestRunnerLogInternal -Level "STEP" -Message "Running tests with code coverage..."
+ Write-TestRunnerLogInternal -Level "STEP" -Message "Running tests with code coverage (Microsoft.Testing.Platform / coverlet.MTP)..."
foreach ($d in $resolvedProjectDirs) {
Write-TestRunnerLogInternal -Level "INFO" -Message "Test Project: $d"
}
@@ -164,11 +178,15 @@ function Invoke-TestsWithCoverage {
foreach ($TestProjectDir in $resolvedProjectDirs) {
Push-Location $TestProjectDir
try {
+ $projectName = [System.IO.Path]::GetFileName($TestProjectDir)
$dotnetArgs = @(
"test"
- "--collect:XPlat Code Coverage"
"--results-directory", $ResultsDir
"--verbosity", $(if ($Silent) { "quiet" } else { "normal" })
+ "--coverlet"
+ "--coverlet-output-format", "cobertura"
+ "--coverlet-file-prefix", $projectName
+ "--coverlet-include", "[MaksIT.*]*"
)
Import-ExternalCommandSupportInternal
@@ -192,7 +210,7 @@ function Invoke-TestsWithCoverage {
}
}
- $coverageFiles = @(Get-ChildItem -Path $ResultsDir -Filter "coverage.cobertura.xml" -Recurse | Sort-Object FullName)
+ $coverageFiles = @(Get-CoberturaCoverageFiles -ResultsDirectory $ResultsDir)
if ($coverageFiles.Count -eq 0) {
return [PSCustomObject]@{
@@ -455,7 +473,7 @@ function Get-DotNetCoverageFromResultsDirectory {
[switch]$Silent
)
- $coverageFiles = @(Get-ChildItem -Path $ResultsDirectory -Filter 'coverage.cobertura.xml' -Recurse -ErrorAction SilentlyContinue | Sort-Object FullName)
+ $coverageFiles = @(Get-CoberturaCoverageFiles -ResultsDirectory $ResultsDirectory)
if ($coverageFiles.Count -eq 0) {
return [PSCustomObject]@{
Success = $false
@@ -566,7 +584,7 @@ function Get-CoverageFromResultsDirectory {
}
}
- $hasDotNet = @(Get-ChildItem -Path $resolvedDirectory -Filter 'coverage.cobertura.xml' -Recurse -ErrorAction SilentlyContinue).Count -gt 0
+ $hasDotNet = @(Get-CoberturaCoverageFiles -ResultsDirectory $resolvedDirectory).Count -gt 0
$jestSummary = Join-Path $resolvedDirectory 'coverage-summary.json'
$hasNpm = Test-Path -LiteralPath $jestSummary -PathType Leaf