现已发布!阅读关于 12 月份的新功能和修复。

测试扩展

Visual Studio Code 支持运行和调试你的扩展测试。这些测试将在一个名为扩展开发主机的特殊 VS Code 实例中运行,并拥有对 VS Code API 的完全访问权限。我们称这些测试为集成测试,因为它们超越了无需 VS Code 实例即可运行的单元测试。本文档将重点介绍 VS Code 集成测试。

概述

如果你使用Yeoman 生成器来构建扩展,集成测试将已为你创建好。

在生成的扩展中,你可以使用 npm run testyarn test 来运行集成测试,这些测试将

  • 下载并解压最新版本的 VS Code。
  • 运行由扩展测试运行器脚本指定的Mocha测试。

快速入门:测试 CLI

VS Code 团队发布了一个用于运行扩展测试的命令行工具。你可以在扩展示例仓库中找到一个示例。

测试 CLI 提供快速设置,并且允许你使用扩展测试运行器轻松运行和调试 VS Code UI 的测试。CLI 在底层仅使用Mocha

要开始,你需要先安装 @vscode/test-cli 模块,以及支持在 VS Code 桌面版中运行测试的 @vscode/test-electron 模块。

npm install --save-dev @vscode/test-cli @vscode/test-electron

安装模块后,你将拥有 vscode-test 命令行工具,可以将其添加到 package.jsonscripts 部分。

{
  "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中找到本指南的配置。本文档的其余部分将结合示例来解释这些文件。

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-electronrunTests 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 等持续集成服务中运行你的扩展测试。
© . This site is unofficial and not affiliated with Microsoft.