Microsoft.Testing.Platform statt VSTest

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