测试扩展
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 提供快速设置,还允许您使用 扩展测试运行器轻松运行和调试 VS Code UI 的测试。CLI 专门在底层使用 Mocha。
要开始使用,您需要首先安装 @vscode/test-cli
模块,以及 @vscode/test-electron
模块,该模块使测试能够在 VS Code Desktop 中运行
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
命令运行此测试,或者在安装 扩展测试运行器后,使用 VS Code 中的测试:运行所有测试命令。您还可以使用测试:调试所有测试命令调试测试。
高级设置:您自己的运行器
您可以在 helloworld-test-sample 中找到本指南的配置。本文档的其余部分将在示例的上下文中解释这些文件
- 测试脚本 (
src/test/runTest.ts
) - 测试运行器脚本 (
src/test/suite/index.ts
)
VS Code 提供了两个 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。
您可以在 microsoft/vscode-test 找到更多 API 用法示例。
测试运行器脚本
当运行扩展集成测试时,--extensionTestsPath
指向测试运行器脚本 (src/test/suite/index.ts
),该脚本以编程方式运行测试套件。以下是 helloworld-test-sample
的 测试运行器脚本,它使用 Mocha 运行测试套件。您可以将其用作起点,并使用 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 中的 CLI 运行测试,而是在 VS Code 稳定版中运行,此设置就可以正常工作。
另一种方法是从 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();
后续步骤
- 持续集成 - 在持续集成服务(如 Azure DevOps)中运行扩展测试。