Microsoft.Testing.Platform statt VSTest
- Matt
Meine Testprojekte liefen bisher alle über dotnet test und damit über
VSTest, ohne dass ich mir groß Gedanken darüber gemacht habe, was im
Hintergrund passiert. Aufgefallen ist mir das erst, als ich nach dem
Aufsetzen meines eigenen Runners
genauer hingeschaut habe, warum ein Testprojekt mit knapp zwanzig Tests
spürbar länger braucht als das Kompilieren selbst. Ein Teil davon geht auf
das Konto von vstest.console, das für jeden Lauf einen eigenen
Testhost-Prozess startet und die Adapter erst zur Laufzeit einsammelt. Genau
das will Microsoft.Testing.Platform (MTP) loswerden.
Ein Assembly, kein Adapter-Zoo mehr
MTP dreht das Prinzip um: Aus dem Testprojekt wird ein eigenständiges,
ausführbares Programm, das die Plattform direkt referenziert.
Microsoft.Testing.Platform.dll selbst hat keine Abhängigkeiten außer der
Runtime, und Erweiterungen wie Codeabdeckung oder der TRX-Report werden zur
Kompilierzeit registriert statt zur Laufzeit gesucht. Es gibt also kein
vstest.console.exe mehr, das im NuGet-Cache nach passenden Adaptern sucht
– die kompilierte Testassembly ist gleichzeitig der Runner und lässt sich
auch direkt starten, ganz ohne dotnet test.
Umstieg in der Praxis
Bei MSTest ist die Unterstützung ab Version 3.2.0 eingebaut. Am einfachsten
geht der Umstieg über das MSTest SDK, das Microsoft.NET.Sdk ersetzt und MTP
dabei standardmäßig aktiviert:
<Project Sdk="MSTest.Sdk/4.1.0">
<PropertyGroup>
<TargetFramework>net10.0</TargetFramework>
</PropertyGroup>
</Project>
Wer das SDK nicht tauschen kann, etwa weil ein Projekt auf
Microsoft.NET.Sdk.Web aufbaut, setzt die Eigenschaften manuell und am besten
in Directory.Build.props, damit alle Projekte einer Solution gemeinsam
umgestellt werden:
<PropertyGroup>
<EnableMSTestRunner>true</EnableMSTestRunner>
<OutputType>Exe</OutputType>
</PropertyGroup>
Bei dotnet test selbst kommt es auf die SDK-Version an. Bis einschließlich
.NET 9 läuft MTP nur über eine VSTest-Brücke, aktiviert mit
TestingPlatformDotnetTestSupport, und die Plattform-Argumente müssen hinter
einem zusätzlichen -- stehen. Ab .NET 10 reicht ein Eintrag in
global.json:
{
"test": {
"runner": "Microsoft.Testing.Platform"
}
}
Danach läuft dotnet test nativ gegen MTP, ohne den doppelten Trenner davor.
Wo es hakt
Zwei Dinge haben mich beim Umstieg überrascht. Erstens: Ein Testprojekt,
dessen Filter zufällig keinen einzigen Test trifft, gilt bei MTP als
Fehlschlag mit Exit-Code 8 – VSTest hat einen leeren Lauf stillschweigend als
Erfolg gewertet. Das hat mir einen roten Pipeline-Lauf beschert, obwohl kein
einziger Test tatsächlich fehlgeschlagen war. Abhilfe schafft
--ignore-exit-code 8 oder die Eigenschaft
TestingPlatformCommandLineArguments im Projekt. Zweitens: VSTest- und
MTP-Projekte lassen sich nicht gemischt in derselben Solution ausführen, und
der Visual-Studio-Test-Explorer setzt mindestens Version 17.14 voraus. Wer
noch RunSettings mit VSTest-spezifischen Loggern oder Collectors einsetzt,
sollte den Umstieg pro Solution planen und nicht nur pro Projekt, weil
--collect und --logger in MTP keine zentralen Schalter mehr sind, sondern
jede Erweiterung ihre eigenen Optionen mitbringt.
Quelle: Migration guide from VSTest to Microsoft.Testing.Platform (MTP), Microsoft Learn