测试插件

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中找到本篇示例,本篇剩余部分将解释例子中的如下部分:

测试入口


VS Code 提供了 2 个 CLI 参数来运行插件测试——--extensionDevelopmentPath--extensionTestsPath

例如:

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

测试入口src/test/runTest.ts))使用了vscode-testAPI,简化了下载、解压、启动 VS Code 的测试流程:

  1. import * as path from "path";
  2. import { runTests } from "vscode-test";
  3. async function main() {
  4. try {
  5. // The folder containing the Extension Manifest package.json
  6. // Passed to `--extensionDevelopmentPath`
  7. const extensionDevelopmentPath = path.resolve(__dirname, "../../");
  8. // The path to the extension test runner script
  9. // Passed to --extensionTestsPath
  10. const extensionTestsPath = path.resolve(__dirname, "./suite/index");
  11. // Download VS Code, unzip it and run the integration test
  12. await runTests({ extensionDevelopmentPath, extensionTestsPath });
  13. } catch (err) {
  14. console.error("Failed to run tests");
  15. process.exit(1);
  16. }
  17. }
  18. main();

vscode-test还支持:

  • 启动 VS Code 时打开指定工作区
  • 下载不同版本的 VS Code
  • 使用其他 CLI 参数启动

你可以在microsoft/vscode-test中找到更多用法。

测试脚本


当你运行插件的集成测试时,--extensionTestsPath会指向测试脚本(src/test/suite/index.ts),然后这个脚本会进一步运行测试套件。下面是helloworld-test-sample中的测试脚本,它使用了 Mocha 运行测试套件。你可以把这个文件视为测试的起点,你可以用Mocha 的 API自定义启动时的配置,你也可以用其他任意喜欢的测试框架替代 Mocha。

  1. import * as path from "path";
  2. import * as Mocha from "mocha";
  3. import * as glob from "glob";
  4. export function run(): Promise<void> {
  5. // Create the mocha test
  6. const mocha = new Mocha({
  7. ui: "tdd"
  8. });
  9. mocha.useColors(true);
  10. const testsRoot = path.resolve(__dirname, "..");
  11. return new Promise((c, e) => {
  12. glob("**/**.test.js", { cwd: testsRoot }, (err, files) => {
  13. if (err) {
  14. return e(err);
  15. }
  16. // Add files to the test suite
  17. files.forEach(f => mocha.addFile(path.resolve(testsRoot, f)));
  18. try {
  19. // Run the mocha test
  20. mocha.run(failures => {
  21. if (failures > 0) {
  22. e(new Error(`${failures} tests failed.`));
  23. } else {
  24. c();
  25. }
  26. });
  27. } catch (err) {
  28. e(err);
  29. }
  30. });
  31. });
  32. }

所有测试脚本和*.test.js文件都有访问 VS Code API 的权限。 看看这个例子(src/test/suite/extension.test.ts)

  1. import * as assert from "assert";
  2. import { after } from "mocha";
  3. // You can import and use all API from the 'vscode' module
  4. // as well as import your extension to test it
  5. import * as vscode from "vscode";
  6. // import * as myExtension from '../extension';
  7. suite("Extension Test Suite", () => {
  8. after(() => {
  9. vscode.window.showInformationMessage("All tests done!");
  10. });
  11. test("Sample test", () => {
  12. assert.equal(-1, [1, 2, 3].indexOf(5));
  13. assert.equal(-1, [1, 2, 3].indexOf(0));
  14. });
  15. });

调试测试文件


调试测试文件和调试插件是一样的,我们看一个launch.json调试器配置的例子:

  1. {
  2. "version": "0.2.0",
  3. "configurations": [
  4. {
  5. "name": "Extension Tests",
  6. "type": "extensionHost",
  7. "request": "launch",
  8. "runtimeExecutable": "${execPath}",
  9. "args": [
  10. "--extensionDevelopmentPath=${workspaceFolder}",
  11. "--extensionTestsPath=${workspaceFolder}/out/test/suite/index"
  12. ],
  13. "outFiles": ["${workspaceFolder}/out/test/**/*.js"]
  14. }
  15. ]
  16. }

提示


使用 Insider 版本开发插件

由于 VS Code 的限制,如果你使用 VS Code 稳定版来运行集成测试,它会报错:

  1. 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或者在runTestslaunchArgs选项中添加该项以禁用其他插件。

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

使用vscode-test自定义配置

你可能会需要自定义一些启动配置,比如启动测试前执行code --install-extension安装一些其他插件这样的场景。vscode-test提供粒度更细的 API 来操作这样的场景:

  1. const cp = require("child_process");
  2. const {
  3. downloadAndUnzipVSCode,
  4. resolveCliPathFromExecutablePath
  5. } = require("vscode-test");
  6. const vscodeExecutablePath = await downloadAndUnzipVSCode("1.34.0");
  7. const cliPath = resolveCliPathFromExecutablePath(vscodeExecutablePath);
  8. // Use cp.spawn / cp.exec for custom setup
  9. cp.spawnSync(
  10. cliPath,
  11. ["--install-extension", "<EXTENSION-ID-OR-PATH-TO-VSIX>"],
  12. {
  13. encoding: "utf-8",
  14. stdio: "inherit"
  15. }
  16. );
  17. // Run the extension test
  18. await runTests({
  19. // Use the specified `code` executable
  20. vscodeExecutablePath,
  21. extensionPath,
  22. testRunnerPath
  23. });

从 vscode 迁移

vscode中的集成测试模块已迁移到vscode-test,你可以按下面的步骤进行迁移:

  • 移除vscode依赖
  • 添加vscode-test依赖
  • 由于旧的vscode模块会下载 VS Code 类型定义,所以你需要

    • 手动安装@types/vscode,这个版本需和你package.jsonengine.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@4glob,现在你需要自己安装到devDependency里去。

下一步

  • 持续集成:将你的插件运行在持续集成服务中,比如 Azure Devops。