🚀 VS Code で で入手しましょう!

拡張機能のテスト

Visual Studio Code は、拡張機能のテストの実行とデバッグをサポートしています。これらのテストは、拡張機能開発ホストという名前の VS Code の特別なインスタンス内で実行され、VS Code API にフルアクセスできます。これらのテストは、VS Code インスタンスなしで実行できるユニットテストを超えるため、統合テストと呼びます。このドキュメントでは、VS Code 統合テストに焦点を当てています。

概要

Yeoman Generator を使用して拡張機能をスキャフォールドする場合、統合テストはすでに作成されています。

生成された拡張機能では、npm run test または yarn test を使用して統合テストを実行できます。

  • 最新バージョンの VS Code をダウンロードして解凍します。
  • 拡張機能テストランナースクリプトで指定された Mocha テストを実行します。

クイックセットアップ: テスト CLI

VS Code チームは、拡張機能テストを実行するためのコマンドラインツールを公開しています。例は、拡張機能サンプルリポジトリにあります。

テスト CLI は、クイックセットアップを提供し、Extension Test Runner を使用して VS Code UI のテストを簡単に実行およびデバッグできるようにします。CLI は、内部的に Mocha を排他的に使用します。

開始するには、最初に @vscode/test-cli モジュールと、VS Code Desktop でテストを実行できるようにする @vscode/test-electron モジュールをインストールする必要があります。

npm install --save-dev @vscode/test-cli @vscode/test-electron

モジュールをインストールすると、vscode-test コマンドラインが使用可能になります。これは、package.jsonscripts セクションに追加できます。

{
  "name": "my-cool-extension",
  "scripts": {
+   "test": "vscode-test"

vscode-test は、現在の作業ディレクトリに対する相対パスで .vscode-test.js/mjs/cjs ファイルを探します。このファイルは、テストランナーの構成を提供し、定義全体は こちらにあります。

一般的なオプションには以下が含まれます

  • (必須) files - 実行するテストを含むパターン、パターンリスト、または絶対パス。
  • version - テストの実行に使用する VS Code のバージョン (デフォルトは stable)。
  • workspaceFolder - テスト中に開くワークスペースへのパス。
  • extensionDevelopmentPath - 拡張機能フォルダーへのパス (デフォルトは構成ファイルのディレクトリ)。
  • mocha - Mocha に渡す追加の オプションを含むオブジェクト。

構成は次のように単純な場合があります

// .vscode-test.js
const { defineConfig } = require('@vscode/test-cli');

module.exports = defineConfig({ files: 'out/test/**/*.test.js' });

...またはより高度な場合もあります

// .vscode-test.js
const { defineConfig } = require('@vscode/test-cli');

module.exports = defineConfig([
  {
    label: 'unitTests',
    files: 'out/test/**/*.test.js',
    version: 'insiders',
    workspaceFolder: './sampleWorkspace',
    mocha: {
      ui: 'tdd',
      timeout: 20000
    }
  }
  // you can specify additional test configurations, too
]);

配列を渡して複数の構成を定義すると、vscode-test を実行したときに順番に実行されます。label でフィルタリングし、--label フラグを使用して個別に実行できます。たとえば、vscode-test --label unitTests などです。コマンドラインオプションの完全なセットについては、vscode-test --help を実行してください。

テストスクリプト

CLI を設定したら、テストを記述して実行できます。テストスクリプトは VS Code API にアクセスでき、Mocha の下で実行されます。サンプルは (src/test/suite/extension.test.ts) です

import * as assert from 'assert';

// You can import and use all API from the 'vscode' module
// as well as import your extension to test it
import * as vscode from 'vscode';
// import * as myExtension from '../extension';

suite('Extension Test Suite', () => {
  suiteTeardown(() => {
    vscode.window.showInformationMessage('All tests done!');
  });

  test('Sample test', () => {
    assert.strictEqual(-1, [1, 2, 3].indexOf(5));
    assert.strictEqual(-1, [1, 2, 3].indexOf(0));
  });
});

このテストは、npm test コマンドを使用するか、Extension Test Runner をインストールした後、VS Code で テスト: すべてのテストを実行 コマンドを使用して実行できます。テスト: すべてのテストをデバッグ コマンドを使用してテストをデバッグすることもできます。

高度なセットアップ: 独自のランナー

このガイドの構成は、helloworld-test-sample にあります。ドキュメントの残りの部分では、サンプルをコンテキストとしてこれらのファイルについて説明します。

VS Code は、拡張機能テストを実行するための 2 つの CLI パラメーター、--extensionDevelopmentPath および --extensionTestsPath を提供します。

例:

# - Launches VS Code Extension Host
# - Loads the extension at <EXTENSION-ROOT-PATH>
# - Executes the test runner script at <TEST-RUNNER-SCRIPT-PATH>
code \
--extensionDevelopmentPath=<EXTENSION-ROOT-PATH> \
--extensionTestsPath=<TEST-RUNNER-SCRIPT-PATH>

テストスクリプト (src/test/runTest.ts) は、@vscode/test-electron API を使用して、拡張機能テストパラメーターを使用して VS Code をダウンロード、解凍、および起動するプロセスを簡素化します

import * as path from 'path';

import { runTests } from '@vscode/test-electron';

async function main() {
  try {
    // The folder containing the Extension Manifest package.json
    // Passed to `--extensionDevelopmentPath`
    const extensionDevelopmentPath = path.resolve(__dirname, '../../');

    // The path to the extension test runner script
    // Passed to --extensionTestsPath
    const extensionTestsPath = path.resolve(__dirname, './suite/index');

    // Download VS Code, unzip it and run the integration test
    await runTests({ extensionDevelopmentPath, extensionTestsPath });
  } catch (err) {
    console.error(err);
    console.error('Failed to run tests');
    process.exit(1);
  }
}

main();

@vscode/test-electron API では、次のことも可能です

  • 特定のワークスペースで VS Code を起動します。
  • 最新の安定版リリースではなく、別のバージョンの VS Code をダウンロードします。
  • 追加の CLI パラメーターを指定して VS Code を起動します。

API の使用例の詳細については、microsoft/vscode-test を参照してください。

テストランナースクリプト

拡張機能統合テストを実行すると、--extensionTestsPath は、テストスイートをプログラムで実行するテストランナースクリプト (src/test/suite/index.ts) を指します。以下は、Mocha を使用してテストスイートを実行する helloworld-test-sampleテストランナースクリプト です。これを開始点として使用し、Mocha の API を使用してセットアップをカスタマイズできます。Mocha を、プログラムで実行できる他のテストフレームワークに置き換えることもできます。

import * as path from 'path';
import * as Mocha from 'mocha';
import { glob } from 'glob';

export function run(): Promise<void> {
  // Create the mocha test
  const mocha = new Mocha({
    ui: 'tdd',
    color: true
  });

  const testsRoot = path.resolve(__dirname, '..');

  return new Promise((c, e) => {
    glob('**/**.test.js', { cwd: testsRoot })
      .then(files => {
        // Add files to the test suite
        files.forEach(f => mocha.addFile(path.resolve(testsRoot, f)));

        try {
          // Run the mocha test
          mocha.run(failures => {
            if (failures > 0) {
              e(new Error(`${failures} tests failed.`));
            } else {
              c();
            }
          });
        } catch (err) {
          e(err);
        }
      })
      .catch(err => {
        return e(err);
      });
  });
}

テストランナースクリプトと *.test.js ファイルの両方から VS Code API にアクセスできます。

サンプルテストを次に示します (src/test/suite/extension.test.ts)

import * as assert from 'assert';
import { after } from 'mocha';

// You can import and use all API from the 'vscode' module
// as well as import your extension to test it
import * as vscode from 'vscode';
// import * as myExtension from '../extension';

suite('Extension Test Suite', () => {
  after(() => {
    vscode.window.showInformationMessage('All tests done!');
  });

  test('Sample test', () => {
    assert.strictEqual(-1, [1, 2, 3].indexOf(5));
    assert.strictEqual(-1, [1, 2, 3].indexOf(0));
  });
});

テストのデバッグ

テストのデバッグは、拡張機能のデバッグと似ています。

サンプル launch.json デバッガー構成を次に示します

{
  "version": "0.2.0",
  "configurations": [
    {
      "name": "Extension Tests",
      "type": "extensionHost",
      "request": "launch",
      "runtimeExecutable": "${execPath}",
      "args": [
        "--extensionDevelopmentPath=${workspaceFolder}",
        "--extensionTestsPath=${workspaceFolder}/out/test/suite/index"
      ],
      "outFiles": ["${workspaceFolder}/out/test/**/*.js"]
    }
  ]
}

ヒント

拡張機能開発に Insiders バージョンを使用する

VS Code の制限により、VS Code 安定版リリースを使用しており、CLI で統合テストを実行しようとすると、エラーがスローされます。

Running extension tests from the command line is currently only supported if no other instance of Code is running.

一般に、CLI から拡張機能テストを実行する場合、テストが実行されるバージョンはすでに実行されているバージョンであってはなりません。回避策として、VS Code 安定版でテストを実行し、開発には VS Code Insiders を使用できます。VS Code Insiders ではなく VS Code 安定版で CLI からテストを実行しない限り、このセットアップは正常に機能します。

別の方法は、VS Code 自体からデバッグ起動構成から拡張機能テストを実行することです。これには、テストをデバッグすることもできるという追加の利点があります。

デバッグ中に他の拡張機能を無効にする

VS Code で拡張機能テストをデバッグすると、VS Code はグローバルにインストールされた VS Code のインスタンスを使用し、インストールされているすべての拡張機能をロードします。launch.json または @vscode/test-electronrunTests API の launchArgs オプションに --disable-extensions 構成を追加できます。

{
  "version": "0.2.0",
  "configurations": [
    {
      "name": "Extension Tests",
      "type": "extensionHost",
      "request": "launch",
      "runtimeExecutable": "${execPath}",
      "args": [
        "--disable-extensions",
        "--extensionDevelopmentPath=${workspaceFolder}",
        "--extensionTestsPath=${workspaceFolder}/out/test/suite/index"
      ],
      "outFiles": ["${workspaceFolder}/out/test/**/*.js"]
    }
  ]
}
await runTests({
  extensionDevelopmentPath,
  extensionTestsPath,
  /**
   * A list of launch arguments passed to VS Code executable, in addition to `--extensionDevelopmentPath`
   * and `--extensionTestsPath` which are provided by `extensionDevelopmentPath` and `extensionTestsPath`
   * options.
   *
   * If the first argument is a path to a file/folder/workspace, the launched VS Code instance
   * will open it.
   *
   * See `code --help` for possible arguments.
   */
  launchArgs: ['--disable-extensions']
});

@vscode/test-electron を使用したカスタムセットアップ

code --install-extension を実行して別の拡張機能をインストールしてからテストを開始するなど、カスタムセットアップを実行したい場合があります。@vscode/test-electron には、そのケースに対応するためのより詳細な API があります。

import * as cp from 'child_process';
import * as path from 'path';
import {
  downloadAndUnzipVSCode,
  resolveCliArgsFromVSCodeExecutablePath,
  runTests
} from '@vscode/test-electron';

async function main() {
  try {
    const extensionDevelopmentPath = path.resolve(__dirname, '../../../');
    const extensionTestsPath = path.resolve(__dirname, './suite/index');
    const vscodeExecutablePath = await downloadAndUnzipVSCode('1.40.1');
    const [cliPath, ...args] = resolveCliArgsFromVSCodeExecutablePath(vscodeExecutablePath);

    // Use cp.spawn / cp.exec for custom setup
    cp.spawnSync(
      cliPath,
      [...args, '--install-extension', '<EXTENSION-ID-OR-PATH-TO-VSIX>'],
      {
        encoding: 'utf-8',
        stdio: 'inherit'
      }
    );

    // Run the extension test
    await runTests({
      // Use the specified `code` executable
      vscodeExecutablePath,
      extensionDevelopmentPath,
      extensionTestsPath
    });
  } catch (err) {
    console.error('Failed to run tests');
    process.exit(1);
  }
}

main();

次のステップ