mcpField
S
smoke-tests

smoke-tests

github.com/microsoftテスト・品質194.4k72 回インストール今日更新
リポジトリ

smoke-tests について

smoke-tests は、Electron、Web、リモート実行で VS Code のエンドツーエンドのスモークテストを実行・デバッグする方法をまとめています。コントリビューターや CI メンテナー向けに、絞り込み、トレース、シャーディングを説明します。

主な機能

  1. 01コンパイルあり・なしでのテスト実行
  2. 02Electron、Web、リモート実行の選択
  3. 03スイートの絞り込みと Playwright トレース
  4. 04推定時間に基づくスイート分割
  5. 05CI ログとスクリーンショットによる調査

活用シーン

  1. 01指定したエンドツーエンドテストの実行
  2. 02断続的な CI 障害の調査
  3. 03失敗実行のトレースとログの確認

インストール

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

$npx skills add https://github.com/microsoft/vscode --skill smoke-tests

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

詳細

スモークテストの実行

スモークテストは test/smoke/ にあり、エンドツーエンドのユーザーフローを通じて VS Code のインスタンス全体(Electron、Web、またはリモート)を操作します。

スクリプト

  • npm run smoketest — まずスモークテスト(test/smoke)をコンパイルし、その後実行します。
  • npm run smoketest-no-compile — コンパイル済みのスモークテストを実行します。CI では、明示的なコンパイル手順の後にこれを使用します。

どちらのスクリプトも、-- の後に指定された追加の引数をランナー(test/smoke/test/index.js)に渡します。

よく使うオプション

オプション説明
-g <pattern>(エイリアス -f)テスト名/スイート名に対する grep フィルター(mocha の grep)です。
--build <path>ソースからコンパイルした開発ビルドではなく、パッケージ化されたビルドに対して実行します。
--tracingPlaywright のトレースを記録します(失敗時にはスクリーンショットも記録します)。
--webElectron の代わりにブラウザーのスモークテストを実行します。
--headlessヘッドレスブラウザーを使用します(--web と併用)。
--remoteリモートのスモークテストを実行します。
--shard <index>/<total>トップレベルのスイートを分割したうちの一つだけを実行します。たとえば、--shard 1/2 のように指定します。スイートは推定所要時間に基づいて各シャードに均等に割り振られます(test/smoke/src/shard.ts を参照)。各スイートは必ず一つのシャードだけで実行されます。
# Run everything (Electron, from source)
npm run smoketest

# Run only a subset of suites by name, with tracing (replace <suite name> with your suite, e.g. "Agents Window")
npm run smoketest -- -g "<suite name>" --tracing

# Run against a packaged build (CI style)
npm run smoketest-no-compile -- --tracing --build "/path/to/VSCode-darwin-arm64/Code - OSS.app"

-g パターンはテスト名/スイート名に対して照合されます。たとえば、-g "Agents Window" は3つすべての Agents Window スイート(Agents Window、Agents Window (local AgentHost)、Agents Window (local AgentHost, SDK sandbox))に一致します。対象のスイートを特定できる部分文字列を指定してください。

いずれかのテストが失敗すると、ランナーはゼロ以外の終了コードで終了します。そのため、終了コードが 0 なら、選択したすべてのテストが成功したことを意味します。

PR CI でのシャーディング

GitHub の PR ワークフローでは、Electron スモークテストを複数のシャードに分割しています。.github/workflows/pr-linux-test.yml と pr-darwin-test.yml の electron-smoke-1 および electron-smoke-2 ジョブ、ならびに pr-win32-test.yml の electron-smoke-1 から electron-smoke-3 までのジョブは、最初のシャードで WSL もセットアップし、SMOKE_SHARD_INDEX/SMOKE_SHARD_TOTAL 環境変数を --shard としてランナーに渡します。各ジョブは <OS> / Electron-Smoke (shard 1/2) および <OS> / Electron-Smoke (shard 2/2)、または Windows / Electron-Smoke (shard 1/3) から Windows / Electron-Smoke (shard 3/3) として結果を報告します。Windows では、リモートスモークテストも Windows / Remote (integration) と並行して、独立した Windows / Remote (smoke) ジョブで実行されます。PR Gate ジョブ(pr-gate)は、ワークフロー内のすべてのジョブに対して単一のチェックを報告し、いずれかのシャードが成功しなかった場合は失敗します。プルリクエストでスモークテストが読み取れないパスのみが変更された場合、シャードはスキップされ、ゲートは成功します(.github/actions/detect-changes/detect.ts を参照)。プラットフォームのシャード数を変更するには、そのワークフローで electron-smoke-<index> ジョブを追加または削除し、すべてのジョブの名前と環境変数に含まれるシャード番号を更新します。各シャードの smoke-test-runner.log の先頭付近にある Running smoke test shard <index>/<total> の行には、そのシャードで実行されたスイートが記載されます。

一部の割り当てはワークフローと連動しており、test/smoke/src/shard.ts で定義されています。

  • WSL: WSL Dev Container スイートはシャード 1 に固定されており、pr-win32-test.yml ではシャード 1 のみで WSL をプロビジョニングします。すべてのシャードで VSCODE_SMOKE_TEST_WSL_REQUIRED を設定したままにしてください。これにより、すべてのシャードで同じスイートが登録され、同じ分割が計算されます。Windows では、シャード 1 は vscode-large-runners-windows-8-core の大規模ランナーではなく、1ES プールで実行されます。GitHub がホストする Windows ランナーでは、WSL2 がディストリビューションをプロビジョニングしている間に断続的にフリーズすることがあり(actions/runner-images#14938)、GitHub がランナーとの通信が途絶えたと報告するまで、チェックが約 45 分間保留状態になります。
  • WSL のバージョン: エージェントの Windows Server 2022 イメージに含まれるのは標準搭載の WSL のみであるため、プロビジョニングでは build/checksums/wsl.txt に固定された WSL リリースをインストールします(build/azure-pipelines/common/wsl.psm1 を参照)。バージョンを更新するには、microsoft/WSL releases にある、より新しい wsl.<version>.x64.msi の SHA256 とファイル名をそこに記載します。インストーラーのキャッシュキーはそのファイルを基にしており、pr-node-modules.yml が main の GitHub キャッシュを作成します。
  • macOS のプロキシ実行: macOS では、PAC プロキシを使用する Agents Window のテストは最後のシャードでのみ実行されるため、バランサーはその実行時間を最後のシャードに割り当てます。

すべてのシャードで同じスイートを登録する必要があります。そうでない場合、スイートがスキップされたり、二重に実行されたりする可能性があります。シャードごとに異なる条件に基づいてスイートを登録しないでください。

実行が完了すると、ランナーは最上位の各スイートの所要時間を、長い順に出力します。アプリの起動(約 20 秒)より大幅に時間がかかるスモークスイートを追加した場合、または出力された所要時間が test/smoke/src/shard.ts の suiteDurations と大きく異なるようになった場合は、シャード間の負荷を均等に保つため、このテーブルを更新してください。

不安定な CI テストを調査するためにスイートを一時的にループ実行する

スモークテストが CI でのみ断続的に失敗する場合は、疑わしいスイートを一時的に連続して何度も実行し、最初の失敗で停止する方法が役立ちます。これにより、関連のない PR で自然に再発するのを待つのではなく、実際の CI 環境で不安定な動作を再現し、そのトレースやスクリーンショットを取得できます。

これはデバッグ用の手段であり、CI に恒久的に追加するものではありません。

  • 一時的なブランチに追加してプッシュし、CI を実行します。再現できるまで繰り返し、その後、不安定な動作を修正します。
  • マージ前にループを削除してください。残しておくと、実行のたびにプラットフォームごとに約 1 時間追加されます。
  • これは特定のスイート専用ではありません。調査対象のスイートに合わせて -g フィルターを指定してください(以下の例では "Agents Window" を使用していますが、対象に応じて置き換えてください)。
追加する場所

ループは、既存の Electron スモークテストのステップの隣に配置し、同じ条件で実行されるようにします。フレークが再現するプラットフォームのテストステップに追加してください。シャード分割された GitHub PR ワークフローでは、下の例のように単一のシャードでのみ実行される条件も追加し、すべてのシャードで実行されないようにします。

GitHub PR ワークフロー(ソースから実行し、--build は指定しません):

  • .github/workflows/pr-linux-test.yml(bash。DISPLAY: ":10" を設定)
  • .github/workflows/pr-darwin-test.yml(bash。DISPLAY なし)
  • .github/workflows/pr-win32-test.yml(PowerShell)

Azure DevOps のテストステップ(--build を指定してパッケージ済みビルドに対して実行):

  • build/azure-pipelines/linux/steps/product-build-linux-test.yml
  • build/azure-pipelines/darwin/steps/product-build-darwin-test.yml
  • build/azure-pipelines/win32/steps/product-build-win32-test.yml
構成

N 回(例:20 回)ループし、最初に失敗した実行で中断します。余裕のあるタイムアウトを設定してください。約 3 分かかるスイートを N 回連続で実行すると、1 時間ほどかかる場合があります。

Bash(Linux/macOS):

# TEMPORARY: loop the suite to reproduce a flaky failure. Remove before merge.
# Replace <suite name> with the suite you're investigating (e.g. "Agents Window").
- name: 🧪 Smoke test flakiness probe (TEMPORARY)
  if: ${{ env.ELECTRON_TESTS == 'true' && env.SMOKE_TESTS == 'true' && env.SMOKE_SHARD_INDEX == '1' }}
  timeout-minutes: 60
  run: |
    for i in $(seq 1 20); do
      echo "::group::Smoke probe run $i/20"
      npm run smoketest-no-compile -- --tracing -g "<suite name>" || { echo "::error::Smoke test failed on run $i/20"; exit 1; }
      echo "::endgroup::"
    done

PowerShell(Windows)では各実行後に $LASTEXITCODE を確認し、失敗した場合は exit 1 を実行します。AzDO 版では、フェイルファストのために set -e(bash)/$LASTEXITCODE(pwsh)を使用し、--build "<packaged app path>" を追加します。

フェイルファストにする理由

このループは調査用です。最初の失敗が兆候となります。すぐに停止すれば、失敗した実行のトレースやスクリーンショットを(ログアーティファクト内に)残せます。また、すでにフレークが発生していると分かった実行を終えるために、エージェントの時間を約 1 時間も費やさずに済みます。

CI スモークテストの失敗をデバッグする

どちらの CI システムも、スモークテストランナーのプラットフォーム別ログ(.build/logs ディレクトリ)をダウンロード可能なアーティファクトとして公開します。アーティファクト内の構成はどちらも同じで、異なるのはアーティファクト名とダウンロードツールだけです。

ログアーティファクトのダウンロード
GitHub Actions

GitHub PR ワークフローでは、アーティファクトが logs-<os>-<arch>-<suite>-<attempt> という名前でアップロードされます。<os> は linux/macos/windows、<suite> はジョブを識別する名前(例:electron、browser、remote、または最初の Electron スモークシャードの場合は electron-smoke-shard1)、<attempt> は実行の試行回数です(例:logs-macos-arm64-electron-smoke-shard1-1)。

実行 ID は実行/ジョブの URL に含まれる数値です。…/actions/runs/<run-id>/job/<job-id> の場合は <run-id> を使用します。gh CLI でダウンロードします。

# A specific artifact into ./logs
gh run download <run-id> -n logs-<os>-<arch>-<suite>-<attempt> -D ./logs

# Or every artifact from the run
gh run download <run-id>

gh run view <run-id> を実行すると、実行のジョブ/アーティファクトが一覧表示されます。ブラウザーで実行の概要ページを開き、下部の Artifacts セクションから確認することもできます。

Azure DevOps

アーティファクト名は、生成元のパイプラインによって異なります。

  • Product build(product-build-<os>.yml):logs-<os>-<arch>-<attempt>。suite セグメントはありません。例:logs-macos-arm64-1。
  • Suite-split CI build(product-build-<os>-ci.yml):logs-<os>-<arch>-<suite>-<attempt>。<suite> セグメントは lower(VSCODE_TEST_SUITE)(例:electron)です。そのため、例として logs-macos-arm64-electron-1 となります(GitHub と同じ形式です)。

<os> は linux/macos/windows、<arch> は x64/arm64、<attempt> は $(System.JobAttempt) です。Azure CLI でダウンロードします。

az pipelines runs artifact download \
  --org <ORG_URL> --project <PROJECT_NAME> \
  --run-id <BUILD_ID> --artifact-name <artifact-name> \
  --path ./logs

VS Code のビルドでは --org https://dev.azure.com/monacotools --project Monaco を指定します。<BUILD_ID> の確認方法については、azure-pipelines スキルを参照してください。

アーティファクトの内容

smoke-tests-<suite>/ の下(実行されたスイートに応じて smoke-tests-electron/、smoke-tests-browser/、または smoke-tests-remote/)には、次のファイルがあります。

  • smoke-test-runner.log — mocha ドライバーの出力に加え、モック LLM サーバーを使用するスイートでは、リクエスト/レスポンス本文の詳細ログも含まれます(request body: を探してください)。Copilot CLI/Copilot セッションの失敗時には、キャプチャされた Copilot ランタイムログの末尾も記録されます(下記を参照)。
  • <N>_suite_<Suite_Name>/copilot-runtime-logs/process-*.log — Copilot ランタイム(@github/copilot CLI)のプロセスログです。Copilot ランタイムセッションの失敗時に、dumpFailureDiagnostics がこれを取得します。ハングや「Timed out waiting for response」が発生した場合は、まずこれを確認してください。SDK/CLI が実行した処理(起動、認証、モデルリクエスト、ターンのライフサイクル、パニック/順序が不正なイベント/プロトコルエラー)を記録するため、テストエラーだけでは分からないタイムアウトの原因を説明できます。Agent Host セッション(Agents Window/ローカル AgentHost)では、trace レベルの完全なログが出力されます(chat.agentHost.copilotSdk.logLevel)。Chat Sessions エディター(Copilot CLI/Claude)と Local セッションでは、SDK はプロセス内で実行され、ここには最小限の起動ログ(Server started, waiting for requests)だけが記録されます。これはランタイムが起動したかどうかを確認するのに十分です。モデルやターンに関する詳細な診断情報は、下記の GitHub Copilot Chat.log にあります。(Claude/Codex セッションでは別のランタイムを使用するため、ここには記録されません。)
  • <N>_suite_<Suite_Name>/window2/exthost/<extension>/…log — スイートごとの拡張機能ホストログです(例:GitHub.copilot-chat/GitHub Copilot Chat.log)。診断ログの多くは、スイートが before フックで有効にする設定に左右されます。想定されるログ行が見つからない場合は、スイートのセットアップを確認してください。
  • <N>_suite_<Suite_Name>/playwright-screenshot-*.png — テスト失敗時に取得された最終フレームのスクリーンショットです(スイートを --tracing 付きで実行した場合のみ)。

<Suite_Name> は、単語以外の文字を _ に置き換えた mocha スイートのタイトルです。code-oss-logs スキルも参照してください。

他のテスト種別との違い

  • ユニットテスト(.test.ts)→ scripts/test.sh/runTests ツール(unit-tests スキルを参照)。
  • 統合テスト(.integrationTest.ts および拡張機能テスト)→ scripts/test-integration.sh(integration-tests スキルを参照)。
  • スモークテスト(test/smoke/)→ npm run smoketest — UI のエンドツーエンドフロー全体。

コメント