# 测试插件

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

例如:

# - 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>
1
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();
1
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);
      }
    });
  });
}
1
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));
  });
});
1
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"]
    }
  ]
}
1
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.
1

所以推荐你使用VS Code Insiders测试插件。

# 调试时禁用其他插件

当你在 VS Code 中对测试进行调试时,VS Code 使用的是全局安装的 VS Code 实例,它会加载所有插件。你可以在launch.json中添加--disable-extensions或者在runTestslaunchArgs选项中添加该项以禁用其他插件。

{
  "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"]
    }
  ]
}
1
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"]
});
1
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
});
1
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.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。