Microsoft Testing Platform is cool!
20 Jul 2025 | testing dotnet devopsI love xUnit and I use it for most of my testing. With xUnit v3 the possibility of running the tests was added without the need of using any other external tools like console runners, dotnet test or VSTest. So a xUnit test suite is just a executable itself.
Not long after xUnit v3 were released I discovered Microsoft Testing Platform, which achieves something very similar. According to their own docs it “[..]is a lightweight and portable alternative to VSTest for running tests in all contexts”.
The cool thing about Microsoft Test Platform is that it provides this for all kinds of test libraries such as xUnit, NUnit, Expecto, MSTest and TUnit. So the Microsoft Testing Platform will work for you regardless of unit testing library you use, and regardless of the library supporting running standalone or not, since Microsoft Testing Platform will provide the runner as well.
I still use Microsoft Testing Platform with xUnit since they coorporate very well, and using them together simplifies a few things which required additional setup and libraries. So recently, I’ve been converting a few test suites to leverage Microsoft Testing Platform so let me share a few cool things I like about it.
So if you already have a Unit Test suite you can opt into the Microsoft Testing Platform bits by adding the following to your csproj file:
<UseMicrosoftTestingPlatformRunner>true</UseMicrosoftTestingPlatformRunner>
This way you can run the tests with dotnet run, now xUnit.v3 already has this built in, but opting into the Testing Platform will then use the Testing Platform runner instead. If you still want to support running with dotnet test you can also add:
<TestingPlatformDotnetTestSupport>true</TestingPlatformDotnetTestSupport>
You can also at this point remove references to packages such as, because the Microsoft Testing Platform also handles integration with your IDE:
<PackageReference Include="xunit.runner.visualstudio">
Report formats
One cool thing about using Microsoft Testing Platform with xUnit is the wide variety of output types you get for reports. For instance some other tools I use such as SonarCloud, only supports xUnit, VSTest of NUnit report types. While some other tools I use require a CTRF type report. This is no issue and can be easily configured when executing the tests with commandline arguments. To export a TRX (VSTest) and CTRF report I do:
dotnet run --project UnitTest/UnitTest.csproj -- \
--report-xunit-trx --report-xunit-trx-filename UnitTestReport.xml \
--report-ctrf --report-ctrf-filename UnitTestReport.ctrf.json
This gives me both formats which I then can use for whatever other tools I use. Great!
When using NUnit you can also specify its reports with:
--report-nunit --report-nunit-filename UnitTestReport.xml
And for xUnit reports you can do:
--report-xunit --report-xunit-filename UnitTestReport.xml
So you have high flexibility of exporting whatever you need.
Code coverage
Gathering code coverage with Microsoft Testing Platform is also made super easy, previously I was relying on another package called coverlet.collector, however this package is designed for VSTest and does not work with Microsoft Testing Platform. Instead you can use their own extension Microsoft.Testing.Extensions.CodeCoverage, it can export code coverage reports in a VS binary format, XML and cobertura.
<PackageReference Include="Microsoft.Testing.Extensions.CodeCoverage">
So in a very similar fashion like the various types of test report formats, adding code coverage after having added the NuGet package is done in a very similar fashion. So piecing everything together:
dotnet run --project UnitTest/UnitTest.csproj -- \
--report-xunit-trx --report-xunit-trx-filename UnitTestReport.xml \
--report-ctrf --report-ctrf-filename UnitTestReport.ctrf.json \
--coverage --coverage-output CoverageReport.coverage --coverage-output-format cobertura
Super convenient. To generate a report locally you can still use the awesome .NET tool dotnet-reportgenerator-globaltool which can generate very nice HTML and markdown reports among many other exports.
Reporting test summary with GitHub Actions
So as I mentioned previously being able to export to various formats is a very powerful feature. One thing I use the CTRF reports for is to post Unit Test summaries on GitHub Actions runs. This summary looks something like this:
This is powered by the ctrf-io/github-test-reporter action configured like this:
- name: Publish Test Report
uses: ctrf-io/github-test-reporter@073c73100796cafcbfdc4722c7fa11c29730439e #v1.0.18
with:
report-path: ${{ github.workspace }}/ctrf/*.ctrf.json
summary-report: true
github-report: true
pull-request: true
update-comment: true
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
Running builds with Cake
I use Cake Build in a lot of my build pipelines, since I can run all the steps locally and debug without need of committing and triggering stuff in a CI pipeline.
Currently there is no Settings class that know of all the combinations of what Microsoft Testing Platform can receive, but you can still use dotnet run to start your tests. For this I use a code block looking something like this:
var projectName = project.GetFilenameWithoutExtension();
var runSettings = new DotNetRunSettings
{
NoBuild = true,
Configuration = context.BuildConfiguration,
Verbosity = context.VerbosityDotNet,
ArgumentCustomization = args => args
.Append("-- ")
.Append($"--report-xunit-trx --report-xunit-trx-filename {projectName}.trx")
.Append($"--report-ctrf --report-ctrf-filename {projectName}.ctrf.json")
.Append($"--coverage --coverage-output {projectName}.coverage --coverage-output-format cobertura")
};
context.DotNetRun(project.FullPath, runSettings);
There is a discussion going on requesting to add the Microsoft Testing Platform capabilities to Cake, so hopefully this will come in the future.
I really like the flexibility and capabilities that MS Testing Platform with xUnit gives me. I was able to migrate to Microsoft Testing Platform pretty easily and simplify some of my CI setup. Also the fact that you would be able to have tests using various frameworks and provide the same arguments to the runner is something that seems pretty interesting too. Since Microsoft Testing Platform would be taking care of the running and argument processing. This would allow someone to easily understand the setup but also swap it out for something else without having to mess with the arguments.
Another outcome from writing this article is getting to know of TUnit, which seems to take a slightly different approach to xUnit and other frameworks and base fully on top of Microsoft Testing Platform instead of adopting it. I might have to check this one out in the near future and see what it can do! The promise of heavily relying on Source Generators, supporting NativeAOT and fully trimmable sounds great.


