# 测试插件
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-testAPI,简化了下载、解压、启动 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。