Hey there, .NET developers! Ready to level up your testing game with the Microsoft Testing Platform (MTP) and .NET 10? If you’ve been using dotnet test
with the traditional VSTest runner, buckle up—MTP is here to make your testing smoother, faster, and more flexible. In this conversational guide, we’ll explore what MTP, aka MicrosoftTestingPlatform, is, why it’s a step up from VSTest, and how to harness it with dotnet test in .NET 10 to build robust tests for your projects. I’ll walk you through the steps I took to experiment with this setup, from a basic MSTest project to a multi-project solution with a standalone executable. Let’s dive into the world of MTP, MicrosoftTestingPlatform, .NET 10, dotnet test and make testing easier and more fun!
Want an integrated, All-in-One platform for your Developer Team to work together with maximum productivity?
Apidog delivers all your demands, and replaces Postman at a much more affordable price!
Why Does Testing Matter in .NET Development
Before we get our hands dirty, let’s talk about why testing is a big deal. Whether you’re building a small app or a massive enterprise system, tests ensure your code works as expected, catches bugs early, and saves you from those late-night debugging sessions. Automated unit tests, like those we’ll create with MSTest and MTP, let you verify functionality, improve code quality, and make refactoring a breeze. With .NET 10’s performance boosts and MTP’s modern testing framework, you’re set to write tests that are fast, reliable, and easy to integrate into CI/CD pipelines. Ready to see how? Let’s follow my journey!
What Is the Microsoft Testing Platform (MTP)?
The Microsoft Testing Platform (MTP), or MicrosoftTestingPlatform, is Microsoft’s next-generation testing framework, introduced to replace the aging VSTest runner. Unlike VSTest, which relies on complex adapters and DLL-based execution, MTP offers a streamlined, native experience for running tests in .NET. It’s built into .NET 10, making it faster and more flexible, with features like standalone executable test runners and better integration with dotnet test
. MTP supports MSTest, NUnit, and xUnit, and it’s designed for modern workflows, including CI/CD and cross-platform development. You can think of it as VSTest’s cooler, more efficient sibling, optimized for .NET 10’s performance enhancements.
Step 1: Setting Up a Basic MSTest Project with MTP
Let’s start simple by creating a basic MSTest project to see MTP in action. Here’s how I kicked things off:
Create the Project:
- Open your terminal and scaffold a new MSTest project using the .NET CLI:
dotnet new mstest -n MyMtpTests
- This creates a project folder
MyMtpTests
with a default test file (UnitTest1.cs
) and a.csproj
file.
Check the Project File:
- The generated
MyMtpTests.csproj
looks something like this:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<IsPackable>false</IsPackable>
<IsTestProject>true</IsTestProject>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="coverlet.collector" Version="6.0.0" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.8.0" />
<PackageReference Include="MSTest.TestAdapter" Version="3.1.1" />
<PackageReference Include="MSTest.TestFramework" Version="3.1.1" />
</ItemGroup>
</Project>
- This sets up a standard MSTest project with VSTest, using Coverlet for code coverage and Microsoft.NET.Test.Sdk for test execution.
Run the Tests:
- Navigate to the project folder:
cd MyMtpTests
- Run the default test:
dotnet test
- The VSTest runner executes the sample test in
UnitTest1.cs
, and you’ll see output confirming the test passed, along with coverage stats from Coverlet.

What’s Happening? This is a traditional setup using VSTest, but it’s a solid baseline before we upgrade to MTP. The project runs tests as a DLL, which is fine but not as flexible as MTP’s executable approach.
Step 2: Evolving to an MTP Executable-Based Test Runner
Now, let’s make things more exciting by switching to MTP’s standalone executable runner, which lets you run tests without dotnet test
. Here’s how I did it:
Update the Project File:
- Modify
MyMtpTests.csproj
to enable MTP and create an executable:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<IsPackable>false</IsPackable>
<IsTestProject>true</IsTestProject>
<!-- Enable MTP runner and executable output -->
<EnableMSTestRunner>true</EnableMSTestRunner>
<TestingPlatformDotnetTestSupport>true</TestingPlatformDotnetTestSupport>
<OutputType>Exe</OutputType>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="coverlet.collector" Version="6.0.0" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.8.0" />
<PackageReference Include="MSTest.TestFramework" Version="3.10.2" />
<PackageReference Include="MSTest.TestAdapter" Version="3.10.2" />
</ItemGroup>
<ItemGroup>
<Using Include="Microsoft.VisualStudio.TestTools.UnitTesting" />
</ItemGroup>
</Project>
Key changes:
<EnableMSTestRunner>true</EnableMSTestRunner>
: Activates MTP’s test runner.<TestingPlatformDotnetTestSupport>true</TestingPlatformDotnetTestSupport>
: Ensures compatibility withdotnet test
.<OutputType>Exe</OutputType>
: Outputs a standalone executable instead of a DLL.
Build the Project:
- Run:
dotnet build
- This generates an executable (e.g.,
MyMtpTests.exe
) in thebin/Debug/net8.0
folder.

Run the Executable:
- Navigate to the output directory:
cd bin/Debug/net8.0
- Run the executable:
- Windows:
MyMtpTests.exe
- macOS/Linux:
./MyMtpTests
- The tests run as a standalone console app, no
dotnet test
needed!

Why This Rocks: The executable approach is perfect for custom CI/CD setups or environments without the .NET SDK installed. It’s a game-changer for flexibility, and MTP makes it faster than VSTest by reducing overhead.
Step 3: Going Pro with .NET 10 and Multi-Project Testing
To see MTP and .NET 10 shine in a real-world scenario, let’s build a multi-project solution with a class library and tests. Here’s how I set it up:
Final Project structure:
MyMtpSolution/
│
├── MyLibrary/
│ ├── Calculator.cs
│ └── MyLibrary.csproj
│
├── MyLibrary.Tests/
│ ├── CalculatorTests.cs
│ └── MyLibrary.Tests.csproj
│
├── MyMtpSolution.sln
└── dotnet.config
1. Create a Solution:
- Start fresh with a solution:
dotnet new sln -n MyMtpSolution
2. Create a Class Library:
- Add a class library project:
dotnet new classlib -n MyLibrary
- Implement a
Calculator
class inMyLibrary/Calculator.cs
:
namespace MyLibrary
{
public class Calculator
{
public int Add(int a, int b) => a + b;
public int Subtract(int a, int b) => a - b;
public int Multiply(int a, int b) => a * b;
public int Divide(int a, int b) =>
b == 0 ? throw new ArgumentException("Cannot divide by zero.") : a / b;
}
}
3. Create a Test Project:
- Scaffold an MSTest project:
dotnet new mstest -n MyLibrary.Tests
- Add tests in
MyLibrary.Tests/UnitTest1.cs
:
using Microsoft.VisualStudio.TestTools.UnitTesting;
using MyLibrary;
namespace MyLibrary.Tests
{
[TestClass]
public class CalculatorTests
{
private Calculator _calculator;
[TestInitialize]
public void Setup()
{
_calculator = new Calculator();
}
[TestMethod]
public void Add_ReturnsCorrectSum()
{
Assert.AreEqual(5, _calculator.Add(2, 3));
}
[TestMethod]
public void Subtract_ReturnsCorrectDifference()
{
Assert.AreEqual(1, _calculator.Subtract(3, 2));
}
[TestMethod]
public void Multiply_ReturnsCorrectProduct()
{
Assert.AreEqual(6, _calculator.Multiply(2, 3));
}
[TestMethod]
public void Divide_ReturnsCorrectQuotient()
{
Assert.AreEqual(2, _calculator.Divide(6, 3));
}
[TestMethod]
[ExpectedException(typeof(ArgumentException))]
public void Divide_ByZero_ThrowsException()
{
_calculator.Divide(6, 0);
}
}
}
4. Add Project References:
- Link the test project to the library:
dotnet add MyLibrary.Tests reference MyLibrary
5. Add Projects to Solution:
- Include both projects in the solution:
dotnet sln MyMtpSolution.sln add MyLibrary/MyLibrary.csproj
dotnet sln MyMtpSolution.sln add MyLibrary.Tests/MyLibrary.Tests.csproj
6. Configure for MTP:
- Update
MyLibrary.Tests.csproj
to enable MTP:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<IsPackable>false</IsPackable>
<IsTestProject>true</IsTestProject>
<EnableMSTestRunner>true</EnableMSTestRunner>
<TestingPlatformDotnetTestSupport>true</TestingPlatformDotnetTestSupport>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="coverlet.collector" Version="6.0.0" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.8.0" />
<PackageReference Include="MSTest.TestFramework" Version="3.10.2" />
<PackageReference Include="MSTest.TestAdapter" Version="3.10.2" />
</ItemGroup>
<ItemGroup>
<Using Include="Microsoft.VisualStudio.TestTools.UnitTesting" />
</ItemGroup>
</Project>
- Optionally, update
MyLibrary.csproj
for consistency (though not strictly needed):
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
</Project>
7. Upgrade to .NET 10:
- Download the .NET 10 SDK from dotnet.microsoft.com (ensure it’s compatible with your OS—Windows, macOS, or Linux).

- Update both
.csproj
files to target .NET 10:
<TargetFramework>net10.0</TargetFramework>
8. Create a dotnet.config File:
- In the solution root, create
dotnet.config
with:
[dotnet.test.runner]
name = "Microsoft.Testing.Platform"
- This enables MTP’s native integration with
dotnet test
in .NET 10.
9. Build and Run Tests:
- From the solution root:
dotnet test
- MTP runs the tests, leveraging .NET 10’s optimizations. You’ll see output for all tests, including pass/fail and coverage stats.

Why This Is Awesome: .NET 10 brings performance improvements (faster JIT, better memory management), and MTP’s native integration eliminates VSTest’s legacy bridges, making tests faster and more reliable. The multi-project setup mimics real-world apps, with a library and separate test project.
How .NET 10 and MTP Improve Testing
MTP and .NET 10 take testing to the next level:
- Speed: MTP’s native runner is optimized for .NET 10, reducing startup time compared to VSTest.
- Flexibility: Standalone executables make tests portable, ideal for custom CI/CD or containerized environments.
- Scalability: Multi-project support handles complex solutions, with MTP ensuring consistent test execution.
- Modern Features: .NET 10’s AOT compilation and memory optimizations make tests run faster, while MTP supports advanced features like parallel test execution and custom reporters.
Users are buzzing about MTP: “It’s like VSTest but without the baggage—faster and cleaner!” With .NET 10, you get cutting-edge performance, and MTP makes dotnet test
a joy.
Troubleshooting Tips
- Tests Not Running? Ensure the .NET 10 SDK is installed and
TargetFramework
is set tonet10.0
. - MTP Not Enabled? Check that
EnableMSTestRunner
andTestingPlatformDotnetTestSupport
are in the.csproj
ordotnet.config
. - Coverage Missing? Verify
coverlet.collector
is included and rundotnet test --collect:"XPlat Code Coverage"
. - Executable Fails? Ensure
OutputType
isExe
and rundotnet build
before executing the.exe
.
Conclusion
You’re now a pro at using MTP (MicrosoftTestingPlatform), .NET 10, dotnet test to build a modern testing setup! From a basic MSTest project to a multi-project solution with a standalone executable, you’ve seen how MTP outshines VSTest and how .NET 10 boosts performance. Try adding more tests, integrating into your CI/CD pipeline, or exploring MTP’s advanced features like parallel execution. Got cool test setups? Share them—let’s keep the testing vibes going!