VSCode:使用executeCommand打开示例项目后测试将无法继续

ksh*_*ine 6 unit-testing mocha.js typescript visual-studio-code vscode-extensions

我正在尝试将一些单元测试添加到我正在开发的 Visual Studio Code 扩展中。我遵循此处描述的设置扩展测试的方法:https ://code.visualstudio.com/api/working-with-extensions/testing-extension

然而,这个秘籍并没有显示任何实际测试扩展的有用信息,只是显示了进行测试的框架。

对于我想做的测试,我想做的第一件事就是打开一个示例项目。这就是我陷入困境的地方。这只是我尝试打开项目文件夹的多种变体之一:

import assert from 'assert';
import { after, before, it } from 'mocha';
import path from 'path';
import { commands, Extension, extensions, Uri, window } from 'vscode';

suite('Extension Tests', () => {
  let extension: Extension<any>;
  const projectFolder = Uri.file(path.join(__dirname, '../../../test/suite/sample-project'));

  window.showInformationMessage('Start all tests.');

  before(() => {
    extension = extensions.getExtension('kshetline.ligatures-limited');
    const cmd = commands.executeCommand('vscode.openFolder', projectFolder).then(
      () => console.log('opened'),
      () => console.log('didn\'t open'));
    console.log('before');
    return cmd;
  });

  after(() => {
    console.log('after');
  });

  it('should load and activate extension', () => {
    assert.ok(extension);
    assert.ok(extension.isActive);
  });

  it('second test', () => {
    assert.ok(true);
  });
});
Run Code Online (Sandbox Code Playgroud)

如果我取出executeCommand,两个测试都会运行,并且测试套件会正确终止,测试窗口也会关闭。

如果我离开executeCommand,有时两个测试都不会执行,有时只是第一个测试。测试套件不会终止——测试窗口保持打开状态,我必须手动停止测试。

我尝试过的变体:

  • 制作该before函数async,然后awaiting executeCommand
  • 添加done参数(对于异步async和非异步),并done()在函数末尾before或在Promisethen的子句中调用executeCommand
  • 回报或不回报executeCommand承诺。

如何正确执行此操作的示例很难找到。我查看了一个又一个扩展的存储库,似乎对扩展进行测试并不是很受欢迎。VSCode 扩展编写者通常显然不会经常进行测试。(也许我遇到的麻烦就是原因?)

我可以看到示例项目确实打开了,并且没有看到任何控制台错误来表明测试为何卡住并且无法进一步进行。

Ara*_*ker 7

不幸的是,当您打开或关闭文件夹时,vscode 会重新加载窗口。这意味着扩展主机将重新启动并断开与调试器以及当前运行的测试脚本的连接。这就是为什么你的before函数永远不会返回并且你的测试中途终止的原因。

尽管与测试无关,但此行为存在一个悬而未决的问题。

窗口重新加载的原因是切换工作空间可能会改变 vscode 环境。设置可能会被覆盖,工作区信任发生变化,正在运行的扩展的整个状态和缓存会失效,并且可能会激活不同的扩展。不幸的是,这不会重新加载传递到 vscode 的测试--extensionTestsPath,很可能在测试代码触发窗口或扩展主机重新加载时防止无限循环。


在问题得到解决之前,您在启动时打开文件夹的方法是正确的。不过,如果您只是这样做,Unit Tests您可以打开单个文件并直接调用命令/事件使用的函数。如果您正在进行端到端或类似用户的测试并且有与工作区相关的测试activationEvents,您可能无法绕过打开文件夹。

我找不到任何文档来证实这一点,但根据我的经验,默认情况下您的扩展是启用的,您可以直接调用任何命令,因此通常不需要打开工作区。


关于测试文档,我强烈建议遵循vscode 网站上的指南。当您按照此处的建议引导扩展程序时yeoman,您已经设置了一个测试运行程序,其中包括一些示例代码。它还生成launch.json可用于调试测试的文件。

有关更多示例,请查看 vscode 的内置扩展(例如TypeScript 语言功能)或一些微软自己的扩展。其中大多数都包含不同复杂程度的测试。您可能会找到最适合您的设置的一个。


示例:使用runTestfromvscode-test

vscode 中的函数runTest接受多个选项,包括您在以下文件中使用的参数launch.json

# From the typings of vscode-test

interface TestOptions {
    ...,
    /**
     * Absolute path to the extension root. Passed to `--extensionDevelopmentPath`.
     * Must include a `package.json` Extension Manifest.
     */
    extensionDevelopmentPath: string;
    /**
     * Absolute path to the extension tests runner. Passed to `--extensionTestsPath`.
     * Can be either a file path or a directory path that contains an `index.js`.
     * Must export a `run` function of the following signature:
     *
     * ```ts
     * function run(): Promise<void>;
     * ```
     *
     * When running the extension test, the Extension Development Host will call this function
     * that runs the test suite. This function should throws an error if any test fails.
     *
     */
    extensionTestsPath: string;
    /**
     * 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?: string[];
}
Run Code Online (Sandbox Code Playgroud)

src/test/runTest.ts使用yeoman加载多个工作区并在其中运行特定测试来编辑脚手架应该相当容易。

const workspaceTests = [
    { testDir: '../your/tests', workspaceDir: '../your/workspace' },
    ...
]

async function main() {
  try {
    const extensionDevelopmentPath = path.resolve(__dirname, '../../');

    for (const { testDir, workspaceDir } of workspaceTests) {  
        const extensionTestsPath = path.resolve(__dirname, testDir);
        const workspacePath = path.resolve(__dirname, workspaceDir);

        // Run tests in the specified workspace
        await runTests({
            extensionDevelopmentPath,
            extensionTestsPath,
            launchArgs: [ workspacePath ]
        });
    }
  } catch (err) {
    console.error('Failed to run tests');
    process.exit(1);
  }
}
Run Code Online (Sandbox Code Playgroud)


ksh*_*ine 0

由于我不太清楚的原因,vscode.openFolder在单元测试运行时使用该命令简直是一件坏事。我想它会以某种方式破坏测试窗口和测试环境之间的连接。

幸运的是,在这种特殊情况下,我可以只打开一个文件夹,这可以在启动测试代码之前在我的“launch.json”配置中完成。

{
  "version": "0.1.0",
  "configurations": [
    {
      ...
    },
    {
      "name": "Test Extension",
      "type": "extensionHost",
      "request": "launch",
      "runtimeExecutable": "${execPath}",
      "args": [
        "--extensionDevelopmentPath=${workspaceFolder}",
        "--extensionTestsPath=${workspaceFolder}/out/test/suite",
        "${workspaceFolder}/test/suite/sample-project"  // <-- project to open goes here
      ],
      "outFiles": [
        "${workspaceFolder}/out/test/**/*.js"
      ],
      "preLaunchTask": "npm"
    },
  ]
}
Run Code Online (Sandbox Code Playgroud)

一旦我通过打开这个示例项目来启动我的测试环境,我就可以安全地使用该vscode.open命令从示例项目文件夹中打开特定文档,然后监视和测试我的扩展对这些文档的操作。