VSCode:使用 executeCommand 打开示例项目后,测试不会继续

Posted

技术标签:

【中文标题】VSCode:使用 executeCommand 打开示例项目后,测试不会继续【英文标题】:VSCode: Tests won't proceed after using executeCommand to open a sample project 【发布时间】:2020-09-05 10:56:38 【问题描述】:

我正在尝试将一些单元测试添加到我正在开发的 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);
  );
);

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

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

我尝试过的变体:

创建before 函数asyncawaiting executeCommand。 为async 和非异步添加done 参数,并在before 函数的末尾或executeCommand 承诺的then 子句中调用done()。 返回或不返回 executeCommand 承诺。

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

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

【问题讨论】:

【参考方案1】:

由于我不完全清楚的原因,在单元测试运行时使用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"
    ,
  ]

一旦我启动了我的测试环境并开始打开这个示例项目,我可以安全地使用vscode.open 命令从示例项目文件夹中打开特定文档,然后监视和测试我的扩展处理这些文件。

【讨论】:

【参考方案2】:

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

此行为有一个open issue,尽管未连接到测试。

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


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

我找不到任何确认文件,但根据我的经验,您的扩展默认启用,您可以直接调用任何命令,因此通常不需要打开工作区。


关于测试文档,我强烈建议遵循guides on the vscode website。当您按照那里的建议使用yeoman 引导您的扩展时,您已经设置了一个测试运行程序,包括一些示例代码。它还会生成一个launch.json,可用于调试您的测试。

如需更多示例,请查看 vscode 的内置扩展(例如 TypeScript Language Features)或 microsofts own extensions 的某些扩展。其中大多数包括具有不同复杂性的测试。您可能会找到与您的设置最匹配的一款。


示例:使用来自vscode-testrunTest

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[];

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

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);
  

【讨论】:

我写了一些扩展,虽然它们都不是很复杂,而且从来不需要打开多个工作区。具有“最佳”测试的可能是这个:github.com/1nVitr0/plugin-vscode-blocksort。或许这也能给你一些启发 我已经阅读了指南,在“hello world”级别之上没有太多示例。我需要删除 executeCommand 并重构才能调用我的私有方法而不是 github.com/jonny64/vludik/blob/t/test/suite/…,对吗? 使用executeCommand 非常好,只是更深入到端到端 测试方向。不要误会我的意思,端到端测试并不是一个坏主意。我只是说 单元测试 你的代码 executeCommand 通常不需要 只执行触发重新加载扩展主机的命令是个问题 @jonny 我添加了一个基于 yeoman 脚手架的示例。我认为它为编写测试提供了一个很好的结构

以上是关于VSCode:使用 executeCommand 打开示例项目后,测试不会继续的主要内容,如果未能解决你的问题,请参考以下文章

IN 语句中的 Datacontext ExecuteCommand 参数

WinSCP ExecuteCommand报告IsSuccess = true但ExitCode = 1

VS Code扩展Api获取文档整个文本的范围?

我们可以在 WP8 的 SqlCE LinqToSQL 上调用 DataContext.ExecuteCommand(sqlQuery) 吗?

使用hdc命令进行查看或者安装应用的时候报错[Fail]ExecuteCommand need connect-key解决方法

使用hdc命令进行查看或者安装应用的时候报错[Fail]ExecuteCommand need connect-key解决方法