MSTest 4.5 は VSTest なしで UWP と WinUI 3 の UI テストを実行できます
MSTest.Sdk 4.5 と Microsoft.Testing.Platform 2.5 により、UWP や WinUI 3 アプリ自体がテストホストになります。[UITestMethod] は各テストを実際のディスパッチャー上で実行し、パッケージ化アプリと AppContainer アプリはサイドカーコントローラー経由で AUMID によりアクティブ化され、パッケージ化されていない WinUI もついに動作します。
2026年10月5日、Amaury Levé 氏が “UWP and WinUI 3 apps: UI testing with MSTest” を公開しました。要点は次のとおりです。MSTest.Sdk 4.5 (Microsoft.Testing.Platform 2.5 を含みます) を使えば、Windows XAML アプリでテストを実行するのに VSTest は不要になります。Microsoft.NET.Test.Sdk も vstest.console も、Visual Studio のインストールに含まれる UwpTestHostRuntimeProvider も必要ありません。
最後の点は見た目以上に重要です。VSTest は UseWinUI プロジェクトをすべてこのプロバイダー経由で処理し、ビルド出力から AppxManifest.xml を読み取っていました。パッケージ化されていない WinUI アプリにはマニフェストがないため、FileNotFoundException で失敗していました (testfx#2784)。MTP ではアプリ自体がテストホストになるため、この問題はなくなります。
アプリが OnLaunched からプラットフォームをホストします
WinUI アプリは ApplicationDefinition から自前の Main をすでに生成します。MSTest.Sdk はそれを検出して独自のエントリポイントを抑止し、ウィンドウの作成後に一度呼び出すだけの MicrosoftTestingPlatformApplication.RunAsync ヘルパーを生成します。
using Microsoft.VisualStudio.TestTools.UnitTesting.AppContainer;
protected override async void OnLaunched(LaunchActivatedEventArgs args)
{
_window = new Window();
_window.Activate();
UITestMethodAttribute.DispatcherQueue = _window.DispatcherQueue;
try
{
Environment.ExitCode = await MicrosoftTestingPlatformApplication.RunAsync(
Environment.GetCommandLineArgs()[1..]);
}
finally
{
_window.Close();
Exit();
}
}
生成される WinUI の Main は void を返すため、終了コードは手動で設定します。これを省略すると、何が失敗しても CI 上では成功として扱われます。
STATestMethod ではなく UITestMethod を使います
[STATestMethod] は STA スレッドを提供しますが、WinUI のディスパッチャーは提供しません。そのため、そこで Grid を作成すると依然として例外がスローされます。[UITestMethod] は、[TestInitialize] と [TestCleanup] を含む MSTest の呼び出し全体を、公開された DispatcherQueue に送ります。
[UITestMethod]
public async Task GridCanBeCreatedOnTheUIThread()
{
await Task.Yield();
var grid = new Grid();
Assert.IsTrue(grid.DispatcherQueue.HasThreadAccess);
}
興味深いのは await Task.Yield() の行です。継続処理が UI スレッドに戻るため、非同期テストでもスレッドアクセスが維持されます。
5 つのアプリモデルを 1 つの SDK で扱えます
testfx のガイドでは、クラシック UWP (uap10.0)、UseUwp を使う .NET 10 上のモダン UWP、パッケージ化された WinUI 3、パッケージ化されていない WinUI 3 (WindowsPackageType=None)、そして TrustLevel="appContainer" を指定した WinUI 3 を扱っています。パッケージ化されたアプリやサンドボックス化されたアプリは Process.Start では起動できないため、MSBuild はフルトラストのサイドカーコントローラーを実行します。このコントローラーはパッケージを登録し、AUMID でアクティブ化し、終了後にパッケージのストレージから TRX、ハングダンプ、リトライの出力を収集します。AppContainer の場合、コントローラーのパイプはアプリの正確なパッケージ SID にアクセスを許可し、ALL APPLICATION PACKAGES は拒否します。
モダン UWP のテストプロジェクトは、今ではこれだけで済みます。
<Project Sdk="MSTest.Sdk">
<PropertyGroup>
<TargetFramework>net10.0-windows10.0.26100.0</TargetFramework>
<UseUwp>true</UseUwp>
<PublishAot>true</PublishAot>
</PropertyGroup>
</Project>
パッケージ化されていないアプリとフルトラストのパッケージ化アプリは、dotnet test --project MyWinUiTests.csproj -c Release -a x64 で実行できます。UWP と AppContainer では、引き続き Visual Studio の MSBuild が必要です: msbuild MyUwpTests.csproj /t:InvokeTestingPlatform /p:Platform=x64。
4.5.0 を固定する前に
元の記事では global.json に "MSTest.Sdk": "4.5.0" を固定していますが、この記事の執筆時点で NuGet.org が最新の MSTest.Sdk として掲載しているのはまだ 4.4.1 です。CI を更新する前にフィードを確認してください。また、CI エージェントについても計画が必要です。パッケージ化アプリと AppContainer の実行には開発者モードまたはサイドロードのポリシーが必要で、AppContainer のテストは昇格なしで実行する必要があり、Windows App SDK のランタイムをエージェントにインストールしておく必要があります。
すでに MSTest 4.4 の Native AOT ソースジェネレーターのために MTP を使っているなら、今回の変更は同じランナーを、VSTest がまだ必要だった最後のアプリモデルまで拡張したものです。
Comments
Sign in with GitHub to comment. Reactions and replies thread back to the comments repo.