拡張機能のテスト
Visual Studio Code は、拡張機能のテストの実行とデバッグをサポートしています。これらのテストは、Extension Development Host と呼ばれる 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 デスクトップでテストを実行できるようにする @vscode/test-electron モジュールをインストールする必要があります。
npm install --save-dev @vscode/test-cli @vscode/test-electron
モジュールをインストールすると、vscode-test コマンドラインが使用できるようになります。これを package.json の scripts セクションに追加できます。
{
"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 の Test: Run All Tests コマンドを使用して実行できます。Test: Debug All Tests コマンドを使用してテストをデバッグすることもできます。
高度なセットアップ: 独自のランナー
このガイドの構成は helloworld-test-sample で見つけることができます。このドキュメントの残りの部分では、サンプルをコンテキストとしてこれらのファイルについて説明します。
- テストスクリプト (
src/test/runTest.ts) - テストランナースクリプト (
src/test/suite/index.ts)
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 Stable でテストを実行し、開発には VS Code Insiders を使用できます。VS Code Insiders で CLI からテストを実行せず、VS Code Stable で実行する限り、このセットアップは問題なく機能します。
別の方法として、VS Code 自体の中からデバッグ起動構成から拡張機能テストを実行することもできます。これにより、テストをデバッグできるという追加の利点があります。
デバッグ中に他の拡張機能を無効にする
VS Code で拡張機能テストをデバッグすると、VS Code はグローバルにインストールされている VS Code インスタンスを使用し、インストールされているすべての拡張機能を読み込みます。--disable-extensions 構成を launch.json または @vscode/test-electron の runTests API の launchArgs オプションに追加できます。
{
"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();
ワークスペース信頼動作のテスト
拡張機能が package.json で capabilities.untrustedWorkspaces を宣言している場合、信頼されたワークスペースと信頼されていないワークスペースの両方で統合テストを追加してください。拡張機能テストからワークスペースの信頼をプログラムで付与または取り消すことはできません。信頼された状態と信頼されていない状態には、別々のテスト実行を使用してください。
@vscode/test-cli を使用する場合は、各信頼状態を個別に実行できるように、別々のテスト構成を定義してください。
- trustedWorkspaceTests: 信頼制限が適用されないベースライン実行を提供します。これは、拡張機能の全機能動作を検証し、信頼されたパスにおけるリグレッションを検出するのに役立ちます。
- untrustedWorkspaceTests: ワークスペースの信頼がまだ有効な状態で、制限モードの動作を検証します。専用の
--user-data-dirを使用すると、以前に永続化された信頼決定によってこの実行が誤って信頼されるのを防ぎます。
各構成には独自の label があるため、それぞれを個別に実行したり (例: vscode-test --label trustedWorkspaceTests および vscode-test --label untrustedWorkspaceTests)、両方を順番に実行したりできます。
// .vscode-test.js
const { defineConfig } = require('@vscode/test-cli');
const path = require('path');
module.exports = defineConfig([
{
label: 'trustedWorkspaceTests',
files: 'out/test/**/*.test.js',
workspaceFolder: './test/fixtures/trusted-workspace',
// Optional: disables Workspace Trust for this run
launchArgs: ['--disable-workspace-trust']
},
{
label: 'untrustedWorkspaceTests',
files: 'out/test/**/*.test.js',
workspaceFolder: './test/fixtures/untrusted-workspace',
// Keep Workspace Trust enabled and isolate user data for deterministic runs
launchArgs: [
'--user-data-dir',
path.join(__dirname, '.vscode-test', 'user-data-untrusted')
]
}
]);
テストでは、vscode.workspace.isTrusted を確認して信頼を意識した動作をアサートしてください。
import * as assert from 'assert';
import * as vscode from 'vscode';
suite('Workspace Trust Tests', () => {
test('extension behavior changes by trust state', async () => {
const isFeatureAvailable = await vscode.commands.executeCommand<boolean>(
'myExtension.isRestrictedFeatureEnabled'
);
if (vscode.workspace.isTrusted) {
assert.strictEqual(isFeatureAvailable, true);
} else {
assert.strictEqual(isFeatureAvailable, false);
}
});
});
拡張機能マニフェストで信頼要件を宣言する方法と、vscode.workspace.isTrusted API を使用する方法の詳細については、ワークスペース信頼拡張機能ガイドを参照してください。
次のステップ
- 継続的インテグレーション - Azure DevOps などの継続的インテグレーションサービスで拡張機能テストを実行します。
- ワークスペース信頼拡張機能ガイド - 拡張機能でワークスペースの信頼を宣言し、処理する方法を学びます。