# 测试插件
VS Code 为你的插件提供了运行和调试的能力。测试会运行在一个特殊的 VS Code 实例中——扩展开发环境
,这个特殊实例拥有访问 VS Code API 的全部权限。本篇侧重于 VS Code 的集成测试,至于单元测试,你可以使用任何流行的测试框架,如Mocha或者Jasmine。
# 概述
如果你原本使用vscode
库进行测试,可以参考从vscode
迁移部分
如果你正在使用yo code 生成器,那么生成的项目中应该已经包含了一些测试示例和指引。
使用npm run test
或者yarn test
启动集成测试,测试工程随后会:
- 下载并解压最新的 VS Code 版本
- 运行插件的测试脚本中所规定的Mocha测试
你可以在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>
2
3
4
5
6
测试入口(src/test/runTest.ts))使用了vscode-test
API,简化了下载、解压、启动 VS Code 的测试流程:
import * as path from "path";
import { runTests } from "vscode-test";
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("Failed to run tests");
process.exit(1);
}
}
main();
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
vscode-test
还支持:
- 启动 VS Code 时打开指定工作区
- 下载不同版本的 VS Code
- 使用其他 CLI 参数启动
你可以在microsoft/vscode-test中找到更多用法。
# 测试脚本
当你运行插件的集成测试时,--extensionTestsPath
会指向测试脚本(src/test/suite/index.ts),然后这个脚本会进一步运行测试套件。下面是helloworld-test-sample
中的测试脚本,它使用了 Mocha 运行测试套件。你可以把这个文件视为测试的起点,你可以用Mocha 的 API自定义启动时的配置,你也可以用其他任意喜欢的测试框架替代 Mocha。
import * as path from "path";
import * as Mocha from "mocha";
import * as glob from "glob";
export function run(): Promise<void> {
// Create the mocha test
const mocha = new Mocha({
ui: "tdd"
});
mocha.useColors(true);
const testsRoot = path.resolve(__dirname, "..");
return new Promise((c, e) => {
glob("**/**.test.js", { cwd: testsRoot }, (err, files) => {
if (err) {
return e(err);
}
// 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);
}
});
});
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
所有测试脚本和*.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.equal(-1, [1, 2, 3].indexOf(5));
assert.equal(-1, [1, 2, 3].indexOf(0));
});
});
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# 调试测试文件
调试测试文件和调试插件是一样的,我们看一个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"]
}
]
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 提示
# 使用 Insider 版本开发插件
由于 VS Code 的限制,如果你使用 VS Code 稳定版来运行集成测试,它会报错:
Running extension tests from the command line is currently only supported if no other instance of Code is running.
所以推荐你使用VS Code Insiders测试插件。
# 调试时禁用其他插件
当你在 VS Code 中对测试进行调试时,VS Code 使用的是全局安装的 VS Code 实例,它会加载所有插件。你可以在launch.json
中添加--disable-extensions
或者在runTests
的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"]
}
]
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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"]
});
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 使用vscode-test
自定义配置
你可能会需要自定义一些启动配置,比如启动测试前执行code --install-extension
安装一些其他插件这样的场景。vscode-test
提供粒度更细的 API 来操作这样的场景:
const cp = require("child_process");
const {
downloadAndUnzipVSCode,
resolveCliPathFromExecutablePath
} = require("vscode-test");
const vscodeExecutablePath = await downloadAndUnzipVSCode("1.34.0");
const cliPath = resolveCliPathFromExecutablePath(vscodeExecutablePath);
// Use cp.spawn / cp.exec for custom setup
cp.spawnSync(
cliPath,
["--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,
extensionPath,
testRunnerPath
});
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# 从 vscode 迁移
vscode
中的集成测试模块已迁移到vscode-test
,你可以按下面的步骤进行迁移:
移除
vscode
依赖添加
vscode-test
依赖由于旧的
vscode
模块会下载 VS Code 类型定义,所以你需要- 手动安装
@types/vscode
,这个版本需和你package.json
的engine.vscode
版本一致,比如你的engine.vscode
版本是1.30
,那么就安装@types/vscode@1.30
- 删除
package.json
中的"postinstall": "node ./node_modules/vscode/bin/install"
- 手动安装
添加一个测试入口,你可以像我们的示例一样,用
runTest.ts
作为入口。指定
package.json
中的test
脚本,运行编译后的runTest.ts
。添加一个测试脚本,你可以用sample test runner script作为入口。注意
vscode
过去依赖mocha@4
和glob
,现在你需要自己安装到devDependency
里去。
# 下一步
- 持续集成:将你的插件运行在持续集成服务中,比如 Azure Devops。