mcpField
M
migrate-vstest-to-mtp

migrate-vstest-to-mtp

github.com/dotnetテスト・品質5.8k3.4k 回インストール1 日前に更新
リポジトリ

migrate-vstest-to-mtp について

.NET のテストソリューションを VSTest から Microsoft.Testing.Platform に移行するスキルです。フレームワーク別ランナーの設定、SDK に応じた dotnet test の構成、引数の変換、CI の更新を案内します。

主な機能

  1. 01テストフレームワークと SDK モードの確認
  2. 02フレームワーク別 MTP ランナーの設定
  3. 03SDK バージョンに応じた dotnet test 連携
  4. 04VSTest 引数とフィルターの変換
  5. 05CI コマンドの更新と結果の検証

活用シーン

  1. 01ソリューションのテストプロジェクトを MTP に移行
  2. 02リポジトリの SDK に合わせた dotnet test の調整
  3. 03CI の VSTest 専用コマンドの置き換え
  4. 04フィルター、カバレッジ、クラッシュダンプ設定の変換

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/dotnet/skills --skill migrate-vstest-to-mtp

インストール後、Claude Code で/migrate-vstest-to-mtpを入力して読み込まれたか確認します。

詳細

VSTest から Microsoft.Testing.Platform への移行

.NET のテストソリューションを VSTest から Microsoft.Testing.Platform(MTP)に移行します。すべてのテストプロジェクトが MTP で実行され、dotnet test が正しく動作し、CI/CD パイプラインが更新されたソリューションを目指します。

最初に行うこと

ウェブ検索や記憶に基づく回答の前に、提供されたプロジェクト、Directory.Build.props、global.json、CI ファイルを確認します。まずフレームワークと SDK モードを特定してください。.NET 9 以前では互換性プロパティと -- 区切り文字を使用します。.NET 10 のネイティブ MTP では global.json を使用し、そのプロパティを削除して、区切り文字を使わずに MTP 引数を渡します。中央管理されるプロパティでは、Directory.Build.props 内で IsTestProject を条件に使用しないでください。代わりに、MSBuildProjectName など、そこで利用可能なプロパティを使用してください。

重要:同じソリューションまたは実行構成内で、VSTest ベースの .NET テストプロジェクトと MTP ベースの .NET テストプロジェクトを混在させないでください。これはサポートされていない構成です。

使用する場面

  • サポートされている任意のテストフレームワークで、VSTest から Microsoft.Testing.Platform に切り替える
  • テストプロジェクトで dotnet run / dotnet watch /実行可能ファイルの直接実行を有効にする
  • Native AOT またはトリミングされたテスト実行を有効にする
  • MTP で vstest.console.exe を dotnet test に置き換える
  • VSTest タスクから .NET Core CLI タスクに CI/CD パイプラインを更新する
  • dotnet test の引数を VSTest 構文から MTP 構文に更新する

使用しない場面

  • プロジェクトがすでに Microsoft.Testing.Platform で実行されており、解決すべき MTP の動作上の違いが残っていない場合(例:テストが 0 件検出された場合の終了コード 8)
  • テストフレームワーク間の移行(例:MSTest から xUnit.net への移行)。これはまったく別の作業です
  • プロジェクトが UWP またはパッケージ化された WinUI テストプロジェクトをビルドする場合。MTP はまだこれらをサポートしていません
  • ソリューションに .NET と .NET 以外のテストアダプター(例:JavaScript または C++ アダプター)が混在する場合。VSTest が必要です
  • MSTest のバージョンをアップグレードする場合は、migrate-mstest-v1v2-to-v3 または migrate-mstest-v3-to-v4 を使用してください

入力

入力必須説明
プロジェクトまたはソリューションのパスいいえテストプロジェクトを含む .csproj、.sln、または .slnx のエントリーポイント。作業ディレクトリを glob で検索して自分で見つけてください。見つからない場合、または候補が実際に曖昧な場合にのみ確認してください
テストフレームワークいいえMSTest、NUnit、xUnit.net v2、または xUnit.net v3。パッケージ参照から自動検出されます
.NET SDK のバージョンいいえdotnet test の統合モードを決定します。リポジトリの global.json または明示された CI SDK を優先してください。リポジトリでバージョンが固定または指定されていない場合にのみ、ホストの dotnet --version を使用してください
CI/CD パイプラインファイルいいえvstest.console または dotnet test を呼び出すパイプライン定義のパス

実行と回答の契約

  • 現在の作業ディレクトリで、プロジェクト、props、global.json、パイプラインファイルを検出してください。検索結果として見つかったファイルを実際に開いてください。スキルディレクトリはユーザーのリポジトリではありません。スキルの有効化後も作業を続け、検出可能なパスについて質問しないでください。
  • 実装を依頼された場合は、ファイルを編集した後、実効的な MSBuild プロパティ、翻訳後のコマンド、テスト件数、依頼された成果物を検証してください。質問には、類似した選択肢を並べるのではなく、検出した SDK とフレームワークに対応する正確なコマンドまたは構成を 1 つ提示してください。
  • すべてのビルド引数を保持し、--no-build や新しい設定ファイル、無関係なパッケージのアップグレードを追加しないでください。そのファイルが存在しない限り、--settings <file> を残さないでください。
  • .NET 9 以前では、-- 区切り文字を表示してください。.NET 10 のネイティブ MTP モードでは、これを削除するよう明記してください。
  • 終了コード 8 の抑制が意図的な場合、広範な抑制は、不適切なフィルターによる意図しない空実行を隠す可能性があると警告してください。既知のテスト数ゼロのプロジェクトまたは構成に対象を限定してください。
  • 終了コード 8 に関する質問には、--ignore-exit-code 8、TestingPlatformCommandLineArguments、TESTINGPLATFORM_EXITCODE_IGNORE=8 の 3 つの具体的な形式をすべて示してください。
  • xUnit v3 のフィルターでは、そのまま使える --filter-class/--filter-method/--filter-trait コマンドを提示し、AND 動作について説明してください。解決された xUnit のバージョンが対応している場合は、複雑な式向けに --filter-query のパス構文も含め、xUnit のクエリフィルターのドキュメントにリンクしてください。
  • レポーター、カバレッジ、ダンプを翻訳する場合は、必要なパッケージをそれぞれ回答に明記してください。正しそうに見えるオプションでも、それを提供する拡張パッケージがなければ不完全です。
  • 最終結果には、フレームワークランナーのオプトイン、リポジトリで選択された SDK 統合モード、翻訳後の正確なコマンド、拡張パッケージ、検証の根拠を明記してください。

ワークフロー

ステップ 1:ソリューションを評価する
  1. 各テストプロジェクトのテストフレームワークを特定します。パッケージとフレームワークの対応表については、platform-detection スキルを参照してください。主な指標:
    • MSTest:MSTest または MSTest.TestAdapter を参照している、あるいは MSTest.Sdk を使用している(<IsTestApplication> が false に設定されていない)。注:MSTest.TestFramework のみの場合はライブラリ依存関係であり、テストプロジェクトではありません。
    • NUnit:NUnit3TestAdapter を参照している
    • xUnit.net:xunit と xunit.runner.visualstudio を参照している
  2. global.json またはユーザーが明示した情報から、リポジトリ/CI が使用する SDK を特定します。いずれもない場合に限り dotnet --version にフォールバックします。エージェントホストの SDK によって、明示された .NET 8/9 の CI ターゲットを暗黙に上書きしてはいけません。
  3. ソリューションまたはリポジトリのルートに Directory.Build.props ファイルがあるか確認します。一貫性を保つため、すべての MTP プロパティをそこに配置してください。
  4. CI スクリプトまたはパイプライン定義で vstest.console.exe が使用されているか確認します。
  5. CI スクリプトで VSTest 固有の dotnet test 引数が使われているか確認します:--filter、--logger、--collect、--settings、--blame*
  6. dotnet test を実行し、テストの合格数/失敗数のベースラインを確立します
ステップ 2:Directory.Build.props を設定する

重要:可能な限り、MTP ランナーのプロパティはプロジェクトごとではなく、ソリューションまたはリポジトリのルートにある Directory.Build.props で設定してください。これにより、一部のプロジェクトでは VSTest を使用し、ほかのプロジェクトでは MTP を使用するという、一貫性のない設定(サポート対象外のシナリオ)を防げます。 注:MTP を使用するには、テストプロジェクトの <OutputType>Exe</OutputType> も必要です。これを自動で設定するのは MSTest.Sdk のみです。それ以外のすべての構成(EnableMSTestRunner を使用する MSTest NuGet パッケージ、EnableNUnitRunner を使用する NUnit、YTest.MTP.XUnit2 を使用する xUnit.net)では、テストプロジェクトだけを対象にする条件を指定して、Directory.Build.props で <OutputType>Exe</OutputType> を一元的に設定することをおすすめします。Directory.Build.props からテストプロジェクトだけを確実に対象にできない場合は、プロジェクトごとに <OutputType>Exe</OutputType> を設定しても問題ありません。

Directory.Build.props での条件設定:Condition="'$(IsTestProject)' == 'true'" は使用しないでください。IsTestProject は評価の後半でテスト SDK のターゲットによって設定されるため、Directory.Build.props がインポートされる時点では使用できません。代わりに、MSBuildProjectName など、早い段階で利用できるプロパティを使用して、命名規則によりテストプロジェクトを対象にしてください。たとえば、すべてのテストプロジェクト名が .Tests で終わる場合は、次のようにします。

<PropertyGroup Condition="$(MSBuildProjectName.EndsWith('.Tests'))">
  <OutputType>Exe</OutputType>
</PropertyGroup>

リポジトリのテストプロジェクトの命名規則に合わせて、条件を調整してください(例:.EndsWith('Tests')、.Contains('.Test'))。

該当する一元管理プロパティはすべて、同じ条件内に設定してください。これには OutputType、フレームワークのランナーを有効にする設定、および .NET 9 以前の TestingPlatformDotnetTestSupport が含まれます。本番プロジェクトにも影響するランナープロパティを、無条件で設定したままにしないでください。

ステップ 3:フレームワーク固有の MTP ランナーを有効にする

各フレームワークには、それぞれ固有のオプトインプロパティがあります。一貫性を保つため、これらは Directory.Build.props に追加してください。

MSTest

オプション A -- MSTest NuGet パッケージ(3.2.0 以降):

<PropertyGroup>
  <EnableMSTestRunner>true</EnableMSTestRunner>
  <OutputType>Exe</OutputType>
</PropertyGroup>

プロジェクトが MSTest 3.2.0 以降を参照していることを確認してください。すでに 3.2.0 以降であれば、MTP への移行にあたって MSTest のバージョンをアップグレードする必要はありません。

オプション B -- MSTest.Sdk:

MSTest.Sdk を使用する場合、MTP はデフォルトで有効です。EnableMSTestRunner プロパティも OutputType Exe プロパティも必要ありません(SDK が両方を自動的に設定します)。必要な操作は、プロジェクトに <UseVSTest>true</UseVSTest> がある場合に、削除することだけです。このプロパティを設定すると、プロジェクトは MTP ではなく VSTest を使用します。

NUnit

NUnit3TestAdapter 5.0.0 以降が必要です。

  1. NUnit3TestAdapter を 5.0.0 以降に更新します。
<PackageReference Include="NUnit3TestAdapter" Version="5.0.0" />
  1. NUnit ランナーを有効にします。
<PropertyGroup>
  <EnableNUnitRunner>true</EnableNUnitRunner>
  <OutputType>Exe</OutputType>
</PropertyGroup>
xUnit.net

YTest.MTP.XUnit2 への参照を追加します。このパッケージを使用すると、xunit.v3 にアップグレードせずに、xUnit.net v2 プロジェクトで MTP をサポートできます。また、OutputType を Exe に設定する必要があります。

<PackageReference Include="YTest.MTP.XUnit2" Version="0.4.0" />
<PropertyGroup>
  <OutputType>Exe</OutputType>
</PropertyGroup>

注:YTest.MTP.XUnit2 は VSTest の --filter 構文を維持するため、xUnit.net v2 ではフィルターを移行する必要はありません。また、runsettings(xUnit 固有の設定のみ)用の --settings、xunit.runner.json、--report-trx による TRX レポート、および --treenode-filter もサポートしています。

xUnit.net v3

xUnit.net v3(xunit.v3 パッケージ)には MTP のサポートが組み込まれています。次の設定で有効にします。

<PropertyGroup>
  <UseMicrosoftTestingPlatformRunner>true</UseMicrosoftTestingPlatformRunner>
</PropertyGroup>

重要:MTP での xUnit.net v3 は、VSTest の --filter 構文をサポートしていません。フィルターを xUnit.net v3 のネイティブなフィルターオプションに変換する必要があります(ステップ 5 を参照)。

ステップ 4:dotnet test との統合を設定する

dotnet test との統合方法は、.NET SDK のバージョンによって異なります。

.NET 10 SDK 以降(推奨)

global.json に test セクションを追加して、ネイティブの MTP モードを使用します。

{
  "sdk": {
    "version": "10.0.100"
  },
  "test": {
    "runner": "Microsoft.Testing.Platform"
  }
}

このモードでは、dotnet test の引数はそのまま渡されます。たとえば、dotnet test --report-trx のように実行します。

重要:global.json では末尾のカンマは使用できません。JSON が厳密に有効であることを確認してください。

.NET 9 SDK 以前

Directory.Build.props に次のプロパティを追加し、dotnet test コマンドの VSTest モードを使用して MTP テストプロジェクトを実行します。

<PropertyGroup>
  <TestingPlatformDotnetTestSupport>true</TestingPlatformDotnetTestSupport>
</PropertyGroup>

重要:このモードでは、-- を使用して dotnet test のビルド引数と MTP の引数を区切る必要があります。たとえば、dotnet test --no-build -- --list-tests のようにします。

Step 5: dotnet test のコマンドライン引数を更新する

VSTest 固有の引数は、MTP の同等の引数に変換する必要があります。ビルド関連の引数(-c、-f、--no-build、--nologo、-v など)は変更ありません。

VSTest の引数MTP の同等の引数備考
--test-adapter-path該当なしMTP では外部アダプターの検出を使用しません
--blame該当なし
--blame-crash--crashdumpMicrosoft.Testing.Extensions.CrashDump NuGet パッケージが必要です
--blame-crash-dump-type <TYPE>--crashdump-type <TYPE>CrashDump 拡張機能が必要です
--blame-hang--hangdumpMicrosoft.Testing.Extensions.HangDump NuGet パッケージが必要です
--blame-hang-dump-type <TYPE>--hangdump-type <TYPE>HangDump 拡張機能が必要です
--blame-hang-timeout <TIMESPAN>--hangdump-timeout <TIMESPAN>HangDump 拡張機能が必要です
--collect "Code Coverage;Format=cobertura"--coverage --coverage-output-format cobertura拡張機能ごとの引数です
-d|--diag <LOG_FILE>--diagnostic
--filter <EXPRESSION>--filter <EXPRESSION>MSTest、NUnit、xUnit.net v2(YTest.MTP.XUnit2 使用時)で同じ構文です。xUnit.net v3 については、以下のフィルター移行を参照してください
-l|--logger trx--report-trxMicrosoft.Testing.Extensions.TrxReport NuGet パッケージが必要です
--results-directory <DIR>--results-directory <DIR>同じです
-s|--settings <FILE>--settings <FILE>MSTest と NUnit は引き続き .runsettings をサポートします
-t|--list-tests--list-tests同じです
-- <RunSettings args>--test-parameterMSTest と NUnit のみ適用されます
フィルターの移行

MSTest、NUnit、xUnit.net v2(YTest.MTP.XUnit2 使用時):VSTest の --filter 構文は、VSTest と MTP の両方で同一です。変更は不要です。

xUnit.net v3(ネイティブ MTP):xUnit.net v3 は、MTP で VSTest の --filter 構文をサポートしていません。フィルターを xUnit.net v3 のネイティブなフィルターオプションに変換する必要があります。

xUnit.net v3 のフィルターフラグ
フラグ説明
--filter-class "name"指定したクラス内のすべてのテストを実行します。ワイルドカード(*)をサポートします。
--filter-not-class "name"指定したクラス内のすべてのテストを除外します
--filter-method "name"指定したテストメソッドを実行します
--filter-not-method "name"指定したテストメソッドを除外します
--filter-namespace "name"指定した名前空間内のすべてのテストを実行します
--filter-not-namespace "name"指定した名前空間内のすべてのテストを除外します
--filter-trait "name=value"一致するトレイトを持つテストを実行します
--filter-not-trait "name=value"一致するトレイトを持つテストを除外します

1 つのフラグに複数の値を指定できます:--filter-class Foo Bar。

VSTest → xUnit.net v3 のフィルター変換表
VSTest の --filter 構文xUnit.net v3 MTP の同等の引数備考
FullyQualifiedName~ClassName--filter-class *ClassName*部分一致にはワイルドカードが必要です
FullyQualifiedName=Ns.Class.Method--filter-method Ns.Class.Method完全修飾メソッド名で完全一致します
Name=MethodName--filter-method *MethodName*部分一致にはワイルドカードが必要です
Category=Value(トレイト)--filter-trait "Category=Value"トレイト名と値のペアでフィルターします
複雑な式--filter-query "expr"xUnit.net のクエリフィルター言語を使用します(以下を参照)
xUnit.net v3 クエリフィルター言語

複雑な式には、パスセグメント構文を使用する --filter-query を指定します。

/<assemblyFilter>/<namespaceFilter>/<classFilter>/<methodFilter>[traitName=traitValue]

各セグメントは、アセンブリ名、名前空間、クラス名、メソッド名に対して一致を判定します。どのセグメントでも「すべてに一致」を表す * を使用できます。ドキュメント:https://xunit.net/docs/query-filter-language

元のフィルターを表現できる場合は、対応する --filter-class/--filter-method/ --filter-trait フラグを優先してください。--filter-query は、クエリを --list-tests で検証してから使用してください。構文上は受け入れられてもテストが 1 件も選択されないクエリは、適切に変換できたとはいえません。

変換例
# VSTest
dotnet test --filter "FullyQualifiedName~IntegrationTests&Category=Smoke"

# xUnit.net v3 MTP -- using individual filters (AND behavior)
dotnet test -- --filter-class *IntegrationTests* --filter-trait "Category=Smoke"

# xUnit.net v3 MTP -- using query language (assembly/namespace/class/method[trait])
dotnet test -- --filter-query "/*/*/*IntegrationTests*/*[Category=Smoke]"

注:--filter-class と --filter-trait を組み合わせる場合は、両方の条件に一致する必要があります(AND 動作)。複雑な式には、パスセグメント構文を使用する --filter-query を指定してください。詳しくは、xUnit.net クエリフィルター言語のドキュメントを参照してください。

手順 6:必要に応じて MTP 拡張パッケージをインストールする

CI スクリプトで TRX レポート、クラッシュダンプ、ハングダンプ、またはカバレッジを使用する場合は、それらを提供するパッケージを追加します。中央パッケージ管理を使用する場合のプロジェクト参照は次のとおりです。

<ItemGroup>
  <PackageReference Include="Microsoft.Testing.Extensions.TrxReport" />
  <PackageReference Include="Microsoft.Testing.Extensions.CrashDump" />
  <PackageReference Include="Microsoft.Testing.Extensions.HangDump" />
  <PackageReference Include="Microsoft.Testing.Extensions.CodeCoverage" />
</ItemGroup>

Directory.Packages.props に対応する PackageVersion エントリを追加します。中央パッケージ管理を使用しない場合は、設定済みのフィードから解決した正確なバージョンをこれらの参照に指定します。選択した MTP スタックと互換性のあるバージョンを使用してください。移行ガイダンスに記載された固定バージョンをコピーしないでください。

手順 7:CI/CD パイプラインを更新する
Azure DevOps

VSTest タスク(VSTest@3)を使用している場合:.NET Core CLI タスク(DotNetCoreCLI@2)に置き換えます。

# Before (VSTest task)
- task: VSTest@3
  inputs:
    testAssemblyVer2: '**/*Tests.dll'
    runSettingsFile: 'test.runsettings'

# After (.NET Core CLI task)
- task: DotNetCoreCLI@2
  displayName: Run tests
  inputs:
    command: 'test'
    arguments: '--no-build --configuration Release'

すでに DotNetCoreCLI@2 を使用している場合:手順 5 の変換に従って引数を更新します。.NET 9 以前では、-- セパレーターを忘れないでください。

- task: DotNetCoreCLI@2
  displayName: Run tests
  inputs:
    command: 'test'
    arguments: '--no-build -- --report-trx --results-directory $(Agent.TempDirectory)'
GitHub Actions

ワークフローファイル内の dotnet test の呼び出しを、手順 5 と同じ引数変換に従って更新します。

vstest.console.exe を置き換える

スクリプトで vstest.console.exe を直接呼び出している場合は、dotnet test に置き換えます。テストプロジェクトは実行可能ファイルになったため、直接実行することもできます。

手順 8:動作の違いに対処する
テストが 0 件の場合の終了コード

VSTest は、検出されたテストが 0 件でも暗黙的に成功します。MTP は終了コード 8で失敗します。次の方法があります。

  • テスト実行時に --ignore-exit-code 8 を渡す
  • Directory.Build.props に追加する:
<PropertyGroup>
  <TestingPlatformCommandLineArguments>$(TestingPlatformCommandLineArguments) --ignore-exit-code 8</TestingPlatformCommandLineArguments>
</PropertyGroup>
  • 環境変数 TESTINGPLATFORM_EXITCODE_IGNORE=8 を使用する
手順 9:VSTest 専用パッケージを削除する(任意)

移行が完了し、検証も済んだら、VSTest でのみ必要なパッケージを削除します。

  • Microsoft.NET.Test.Sdk -- MTP では不要です(MSTest.Sdk v4 では既定で含まれません)
  • xunit.runner.visualstudio -- xUnit.net の VSTest によるテスト検出でのみ必要です(YTest.MTP.XUnit2 を使用する場合は不要です)
  • NUnit3TestAdapter の VSTest 専用機能 -- アダプター自体は引き続き必要ですが、MTP ランナー用としてのみ必要です

注:移行期間中に VSTest との互換性を維持する必要がある場合は、これらのパッケージを残してください。

手順 10:検証する
  1. dotnet build を実行し、エラーが 0 件であることを確認する
  2. dotnet test を実行し、すべてのテストが成功することを確認する
  3. テストの成功数/失敗数を移行前のベースラインと比較する
  4. テスト実行可能ファイルを直接実行する(例:./bin/Debug/net8.0/MyTests.exe)-- 正常に動作することを確認する
  5. CI パイプラインで期待されるテスト結果の成果物(TRX ファイル、コードカバレッジ、クラッシュダンプ)が生成されることを確認する
  6. Visual Studio(17.14+)または VS Code のテスト エクスプローラーでテストが検出され、実行されることを確認する

検証

  • すべてのテストプロジェクトで MTP ランナーが使用されている(VSTest 専用の構成が残っていない)
  • dotnet build がエラーなしで完了する
  • dotnet test ですべてのテストが成功し、テスト数が移行前のベースラインと一致する
  • テスト実行ファイルを直接実行できる(例:./bin/Debug/net8.0/MyTests.exe)
  • CI パイプラインで想定されるテスト結果の成果物(TRX ファイル、コードカバレッジ、クラッシュダンプ)が生成される
  • Visual Studio または VS Code のテストエクスプローラーでテストが検出され、実行される
  • CI スクリプトに vstest.console.exe の呼び出しが残っていない
  • MSTest.Sdk 以外のすべてのテストプロジェクトで <OutputType>Exe</OutputType> が設定されている

よくある落とし穴

落とし穴解決策
同じソリューション内で VSTest プロジェクトと MTP プロジェクトを混在させるすべてのテストプロジェクトをまとめて移行してください。混在モードはサポートされていません
.NET 9 以前では dotnet test の引数が無視される-- を使ってビルド引数と MTP 引数を区切ってください:dotnet test -- --report-trx
CI で失敗がないのに終了コード 8 が返されるMTP はテストが 0 件の場合に失敗します。--ignore-exit-code 8 を使うか、テストの検出を修正してください
MSTest.Sdk v4 と vstest.console の組み合わせが機能しなくなったMSTest.Sdk v4 は Microsoft.NET.Test.Sdk を追加しなくなりました。明示的に追加するか、dotnet test に切り替えてください
<OutputType>Exe</OutputType> が設定されていない自動的に設定される MSTest.Sdk を除くすべてのセットアップで必須です
Directory.Build.props で Condition="'$(IsTestProject)' == 'true'" を使用しているDirectory.Build.props の評価時には IsTestProject がまだ定義されていません。代わりに $(MSBuildProjectName.EndsWith('.Tests'))(または同様の名前ベースのチェック)を使用してください

次のステップ

  • 新しい MTP プラットフォームでテストを実行するには run-tests を使用します
  • MTP でホットリロードを使ってテストを反復的に修正するには mtp-hot-reload を使用します

詳細情報

コメント