当前位置: 首页 > news >正文

vscode插件开发之 - TestController

 TesController概要介绍

 TestController 组件是用于实现自定义测试框架和集成测试结果的。它允许开发者定义自己的测试运行器,以支持在VSCode中运行和展示测试。以下是一些使用 TestController 组件的主要场景:

自定义测试框架:如果你正在开发或使用一个非标准的测试框架,你可以使用 TestController 来集成这个框架的测试结果。

语言特定的测试:对于某些语言或框架,VSCode可能没有内置的测试支持。使用 TestController,你可以为这些语言或框架添加测试支持。

集成外部测试工具:如果你需要在VSCode中展示由外部测试工具生成的测试结果,TestController 可以用来映射这些结果到VSCode的测试UI。

测试结果可视化:通过 TestController,你可以控制测试结果如何在VSCode的测试面板中展示,包括测试的通过、失败、跳过等状态。

如何开发一款自定义的测试框架插件

  要开发一款基于vscode的自定义测试框架非常简单,有三个步骤。以读取markdown中的代码,执行测试为例子来看看如何自定义测试框架插件

步骤一:解析文档中内容,并将结果添加到testcontroller的testItem对象

  下面的代码中,对给定的文档内容通过正则表达式进行match,获取到markdown文件中的测试name,experssion,expected内容,并将parse出来的内容用于构建TestItem。下图图一假设是文本上的代码内容,下图图二是parse出来的Test对象内容。

function loadTestsFromDocument(testController: vscode.TestController, document: vscode.TextDocument) {const tests = parseTests(document.getText());for (const test of tests) {const testItem = testController.createTestItem(test.name, test.expression + "=" + test.expected);testController.items.add(testItem);}
}interface Test {name: string;expression: string;expected: number;
}function parseTests(text: string): Test[] {const testRegex = /^(\d+ \+ \d+) = (\d+) \/\/ (.+)$/gm;const tests: Test[] = [];let match;while ((match = testRegex.exec(text)) !== null) {tests.push({name: match[3],expression: match[1],expected: parseInt(match[2])});}return tests;
}

  上述代码中,TestController.createTestItem 方法用于创建一个新的 TestItem,它代表一个测试用例。以下是 createTestItem 方法的一些关键参数和它们的说明:输入参数:
id (string): 测试用例的唯一标识符。这里是用Test.name作为id
label (string): 测试用例的显示名称,通常在UI中展示给用户。这里是组装成的label信息,后面要通过解析label信息来执行测试。testItem.label=test.expression + "=" + test.expected
uri (vscode.Uri): 表示测试用例所属文件的位置。通常使用当前编辑器的文档URI。
range (vscode.Range): 测试用例在文件中的位置范围。这有助于用户快速定位到测试用例的代码。
children (TestItem[], optional): 如果这个测试用例是一个容器,比如一个测试套件,你可以在这里提供子测试用例的数组。
tags (string[], optional): 一组标签,可以用来对测试用例进行分类或标记。

步骤二:自定义测试执行逻辑

  下面定义了一个简单的runTest逻辑,通过解析testItem.label信息,判断expected和actual的值是否相等来判断测试执行结果。

async function runTest(testItem: vscode.TestItem) {const expression = testItem.label.split('=')[0].trim();const expected = parseInt(testItem.label.split('=')[1].trim());const actual = eval(expression);const result = actual === expected;if (result) {testItem.busy = false;return `${testItem.label}: PASSED`;} else {testItem.busy = false;return `${testItem.label}: FAILED`;}
}

步骤三:注册命令执行测试

  定义好前面的内容后,就可以注册命令,将testController.items的内容转换成数组,在逐个执行runTest方法,并把执行结果通过showInfomationMessage显示出来。

        vscode.commands.registerCommand('markdownTestController.runTests', async () => {const tests = Array.from(testController.items)const results: string[] = [];for (const [, testItem] of tests) {vscode.window.showInformationMessage(JSON.stringify(testItem));const resultMessage = await runTest(testItem);results.push(resultMessage);}if (results.length > 0) {vscode.window.showInformationMessage(results.join('\n'));} else {vscode.window.showInformationMessage('No tests executed.');}});
}

  编写好脚本后,就可以执行了,在markdown文件中准备了一个数学计算,然后执行命令,可以看到message中显示执行结果,另外,为了调试,这里还显示testItem对象的值。

  除了自定义测试执行逻辑,实际在开发vscode测试相关类插件时,还可以调用第三方已有的测试工具执行测试,代码的例子是调用jest执行测试的例子。

  上面只定义了一个简单的runTest逻辑,在实际项目中,更多的是集成第三方测试执行插件,例如集成jest,在runTest方法里面只需通过“child_process.exec(`npx jest -t "${testItem.label}" --json`”来执行对应的测试即可。下面的使用vscode的testcontroller等组件,集成test来执行测试的例子。所有代码如下所示:

import * as vscode from 'vscode';
import * as child_process from 'child_process';export function activate(context: vscode.ExtensionContext) {const testController = vscode.tests.createTestController('jestTestController', 'Jest Tests');context.subscriptions.push(testController);context.subscriptions.push(vscode.commands.registerCommand('extension.runJestTests', async () => {await runAllTests(testController);}));async function runAllTests(testController: vscode.TestController) {const testItems: vscode.TestItem[] = [];testController.items.forEach(testItem => testItems.push(testItem));const request = new vscode.TestRunRequest(testItems);const run = testController.createTestRun(request);let allTestsPassed = true;const testResults: { [key: string]: boolean } = {};for (const test of testItems) {run.started(test);const result = await runJestTest(test);testResults[test.id] = result;if (result) {run.passed(test);} else {run.failed(test, new vscode.TestMessage('Test failed'));allTestsPassed = false;}}run.end();if (allTestsPassed) {vscode.window.showInformationMessage('All tests passed.');} else {vscode.window.showInformationMessage('Some tests failed. Check test results for details.');}}context.subscriptions.push(vscode.workspace.onDidOpenTextDocument(doc => {if (doc.languageId === 'typescript' || doc.languageId === 'javascript') {loadTestsFromDocument(testController, doc);}}));vscode.workspace.textDocuments.forEach(doc => {if (doc.languageId === 'typescript' || doc.languageId === 'javascript') {loadTestsFromDocument(testController, doc);}});
}function loadTestsFromDocument(testController: vscode.TestController, document: vscode.TextDocument) {const tests = parseTests(document.getText());for (const test of tests) {const testItem = testController.createTestItem(test.name, test.name, document.uri);testController.items.add(testItem);}
}interface Test {name: string;
}function parseTests(text: string): Test[] {const testRegex = /test\(['"](.+)['"]/g;const tests: Test[] = [];let match;while ((match = testRegex.exec(text)) !== null) {tests.push({name: match[1]});}return tests;
}async function runJestTest(testItem: vscode.TestItem): Promise<boolean> {return new Promise((resolve) => {const options = {cwd: vscode.workspace.workspaceFolders ? vscode.workspace.workspaceFolders[0].uri.fsPath : undefined,};child_process.exec(`npx jest -t "${testItem.label}" --json`, options, (err, stdout, stderr) => {if (err) {console.error(stderr);vscode.window.showErrorMessage(`Test failed to run: ${stderr}`);resolve(false);} else {try {const result = JSON.parse(stdout);vscode.window.showInformationMessage(`${testItem.label}: ${result.numFailedTests === 0 ? 'Passed' : 'Failed'}`);resolve(result.numFailedTests === 0);} catch (parseError) {console.error(`Failed to parse test result: ${parseError}`);vscode.window.showErrorMessage(`Failed to parse test result: ${parseError}`);resolve(false);}}});});
}export function deactivate() { }

   为了验证上面的插件是否工作,需要再准备一个包含jest测试的项目,该项目包含一个简单sum函数,以及用jest框架测试add函数的测试脚本。

import { add } from './adder';test('first', () => {expect(add(1, 2)).toBe(4);
});test('second', () => {expect(add(0, 0)).toBe(0);
});

    运行插件,可以看到执行了两个测试,其中一个成功,一个失败,说明成功调用jest执行了测试,并获取到了测试结果。结果如下图所示:

   以上就是vscode插件开发TestController组件的使用介绍,在实际项目,例如playwright-vscode插件就会使用这些组件,完成对ui测试的执行。后续的博客将从源码层面来解析playwright-vscode插件实现原理。

相关文章:

vscode插件开发之 - TestController

TesController概要介绍 TestController 组件是用于实现自定义测试框架和集成测试结果的。它允许开发者定义自己的测试运行器&#xff0c;以支持在VSCode中运行和展示测试。以下是一些使用 TestController 组件的主要场景&#xff1a; 自定义测试框架&#xff1a;如果你正在开发…...

QBitArray使用详解

QBitArray使用详解 一、创建和初始化 QBitArray1.1 QBitArray默认构造1.2 QBitArray指定大小的构造1.3 QBitArray指定大小和初始值的构造 二、设置和访问位2.1 QBitArray设置单个位2.2 QBitArray访问单个位2.3 QBitArray使用下标操作符 三、设置所有位3.1 QBitArray将所有位设置…...

基于Python的自然语言处理项目 ChatTTS 推荐

**项目名称&#xff1a;ChatTTS**  ChatTTS是一个基于Python的自然语言处理项目&#xff0c;旨在实现一个简单的文本到语音转换系统。它使用深度学习技术&#xff0c;通过自然语言处理和语音合成算法&#xff0c;将文本转换为语音输出。  **项目介绍**&#xff1a;  Chat…...

论 To B 产品:从概念到市场实践

本文作者为 360 奇舞团产品经理 论 To B 产品&#xff1a;从概念到市场实践 To B 产品在商业世界中扮演着至关重要的角色。相较于面向消费者的To C市场&#xff0c;To B市场更专注于为其他企业提供产品和服务。理解和成功运营To B产品需要对其特定的市场需求和运作方式有深刻的…...

如何通过自定义模块DIY出专属个性化的CSDN主页?一招教你搞定!

个人主页&#xff1a;学习前端的小z 个人专栏&#xff1a;HTML5和CSS3悦读 本专栏旨在分享记录每日学习的前端知识和学习笔记的归纳总结&#xff0c;欢迎大家在评论区交流讨论&#xff01; 文章目录 &#x1f4af;如何通过HTMLCSS自定义模板diy出自己的个性化csdn主页&#x…...

[BSidesCF 2020]Had a bad day1

看到页面有两个按钮 先随便点一个试一下&#xff0c;当我们点击之后发现url是有变动的 感觉url是有点东西的&#xff0c;可能是某种注入&#xff0c;先尝试一下sql注入&#xff0c;发现给出了报错 通过报错我们可以确定是文件包含漏洞&#xff0c;那我们试试php伪协议去读取一下…...

从媒体网站的频道划分看媒体邀约的分类?

传媒如春雨&#xff0c;润物细无声&#xff0c;大家好&#xff0c;我是51媒体网胡老师。 媒体宣传加速季&#xff0c;100万补贴享不停&#xff0c;一手媒体资源&#xff0c;全国100城线下落地执行。详情请联系胡老师。 在我们举行活动的时候&#xff0c;通常会邀请媒体到现场来…...

Day40

Day40 监听器 概念&#xff1a; 监听器用于监听web应用中某些对象信息的创建、销毁、增加&#xff0c;修改&#xff0c;删除等动作的 发生&#xff0c;然后作出相应的响应处理。当范围对象的状态发生变化的时候&#xff0c;服务器自动调用 监听器对象中的方法。 常用于统计在线…...

linux基础 - 内核的基础概念

目录 零. 前言 一. 源码简介 二. 存储管理 物理内存管理&#xff1a; 虚拟内存管理&#xff1a; 内存分配与回收&#xff1a; 三. CPU 和进程管理 进程管理&#xff1a; CPU 管理&#xff1a; 四. 文件系统 文件系统的概念 常见的 Linux 文件系统类型 文件系统的工…...

centos7系统使用docker-compose安装部署jenkins

CentOS7系统使用docker-compose安装部署jenkins&#xff0c;并实现前后端自动构建 记录一次工作中部署jenkins的真实经历&#xff0c;总结了相关经验 1.准备环境 1.java 由于最新的jenkins需要jdk11以上才能支持&#xff0c;而系统里的jdk是1.8的&#xff0c;因此等jenkins安…...

传染病报卡内容——丙型

--丙型 select a.morbiditdate 发病日期, diagnosedate 诊断日期, a.deathdate 死亡日期, a.casetypequality 病例分类,a.hcvrna "HCR_RNA定量" from zl_sdmb.t_报卡记录 t, c1_infectiousv1_6 a where t.id a.fileid and t.卡片种类 传…...

本地快速部署大语言模型开发平台Dify并实现远程访问保姆级教程

文章目录 前言1. Docker部署Dify2. 本地访问Dify3. Ubuntu安装Cpolar4. 配置公网地址5. 远程访问6. 固定Cpolar公网地址7. 固定地址访问 前言 本文主要介绍如何在Linux Ubuntu系统使用Docker快速部署大语言模型应用开发平台Dify,并结合cpolar内网穿透工具实现公网环境远程访问…...

《Cloud Native Data Center Networking》(云原生数据中心网络设计)读书笔记 -- 02 Clos拓扑

本章回答以下问题&#xff1a; 什么是 Clos 拓扑&#xff0c;它与“接入 - 汇聚 - 核心”拓扑有何不同?Clos 拓扑的特征是什么?Clos 拓扑对数据中心网络的影响是什么? Clos拓扑 云原生数据中心基础设施的先行者们想要构建一种支持大规模水平扩展网络。 基本的Clos拓扑如图…...

VUE3版本新特性

VUE3版本新特性 VUE3和VUE2的区别路由的使用vite安装项目新特性使用 1.VUE3和VUE2的区别 2020年9月18日&#xff0c;Vue.js发布版3.0版本&#xff0c;代号&#xff1a;One Piece 于 2022 年 2 月 7 日星期一成为新的默认版本! Vue3性能更高,初次渲染快55%, 更新渲染快133% 。…...

【Oracle篇】Oracle数据库坏块处理:rman修复坏块实践与案例分析(第七篇,总共八篇)

&#x1f4ab;《博主介绍》&#xff1a;✨又是一天没白过&#xff0c;我是奈斯&#xff0c;DBA一名✨ &#x1f4ab;《擅长领域》&#xff1a;✌️擅长Oracle、MySQL、SQLserver、阿里云AnalyticDB for MySQL(分布式数据仓库)、Linux&#xff0c;也在扩展大数据方向的知识面✌️…...

学懂C#编程:从一个简单的例子理解事件处理

在C#中&#xff0c;事件是一种特殊的委托类型&#xff0c;用于在对象上发生某些事情时通知订阅者。事件的处理通常包括定义事件&#xff0c;创建触发事件的条件&#xff0c;以及订阅该事件的事件处理程序。 以下是一个简单的C#事件处理示例&#xff1a; using System;// 定义…...

深入理解指针(2)

4. const 修饰指针 4.1 const修饰变量 变量是可以修改的&#xff0c;如果把变量的地址交给⼀个指针变量&#xff0c;通过指针变量的也可以修改这个变量。 但是如果我们希望⼀个变量加上⼀些限制&#xff0c;不能被修改&#xff0c;怎么做呢&#xff1f;这就是const的作⽤。 …...

C#.Net筑基-集合知识全解

01、集合基础知识 .Net 中提供了一系列的管理对象集合的类型&#xff0c;数组、可变列表、字典等。从类型安全上集合分为两类&#xff0c;泛型集合 和 非泛型集合&#xff0c;传统的非泛型集合存储为Object&#xff0c;需要类型转。而泛型集合提供了更好的性能、编译时类型安全…...

AI PPT生成器,一键在线智能生成PPT工具

PPT作为商业沟通和教育培训中的重要工具&#xff0c;PPT制作对于我们来说并不陌生。但是传统的PPT制作不仅耗时&#xff0c;而且想要做出精美的PPT&#xff0c;需要具备一定的设计技能。下面小编就来和大家分享几款AI PPT工具&#xff0c;只要输入主题&#xff0c;内容就可以在…...

stm32学习笔记---零基础入门介绍2

目录 STM32介绍 STM32家族系列 ARM介绍 ARM内核型号种类 我们学习用的STM32 片上资源/外设&#xff08;Peripheral&#xff09; 命名规则 系统结构 引脚定义 STM32的启动配置 STM32最小系统电路和其他部分电路 最小系统板的实物图 附&#xff1a;安装软件准备 声明…...

搭建取图系统app源码开发,满足广泛应用需求

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 前言 图片已成为信息传递的重要媒介&#xff0c;广泛应用于各个领域。为满足日益增长的图片需求&#xff0c;搭建一款高效的取图系统&#xff0c;可以为用户提供便捷、全面的…...

语音质量评价方法之MOS

引言 在语音增强、语音合成、语音转换、声音转换、语音克隆、语音修复等等领域&#xff0c;常常要对输出的语音进行评价。对语音的质量评价一般关注两个方面&#xff0c;即主观评价和客观评价。主观评价就是人凭借听觉感受对语音进行打分&#xff0c;客观评价比较广泛&#xf…...

gorm简介

【1】ORM: 即Object-Relational Mapping,它的作用是在关系型数据库和对象之间作一个映射&#xff0c;这样我们在具体的操作数据库的时候&#xff0c;就不需要再去和复杂的SQL语句打交道&#xff0c;只要像平时操作对象一样操作它们就可以了。 【2】GORM gorm是go语言的一个orm…...

MySQL:SELECT list is not in GROUP BY clause 报错 解决方案

一、前言 一大早上测试环境&#xff0c;发现测试环境的MySQL报错了。 SELECT list is not in GROUP BY clause and contains nonaggregated column二、解决方案 官方文档中提到&#xff1a; 大致意思&#xff1a; 用于GROUP BY的SQL / 92标准要求满足以下条件&#xff1a; SE…...

IPython的使用技巧

1、解释说明 IPython是一个强大的Python交互式shell&#xff0c;它提供了丰富的功能&#xff0c;如自动补全、历史记录、内置帮助等。IPython使得在命令行下编写和测试Python代码变得更加方便和高效。 2、使用示例 安装IPython&#xff1a; pip install ipython启动IPython…...

Spring Boot 多线程例子

在Spring Boot中&#xff0c;多线程可以通过Java的并发工具来实现。以下是一些常见的多线程实现方法&#xff1a; 1. 使用Async注解和CompletableFuture&#xff1a; 首先&#xff0c;需要在Spring Boot应用的主类上添加EnableAsync注解&#xff0c;以启用异步支持。 java Spr…...

java干货 线程池的分析和使用

文章目录 一、了解线程池1.1 什么是线程池1.2 为什么需要线程池 二、四种线程池的使用2.1 newFixedThreadPool2.2 newCachedThreadPool2.3 newSingleThreadExecutor2.4 newScheduledThreadPool 三、自定义线程池3.1 线程池七大核心参数3.2 线程池内部处理逻辑 一、了解线程池 …...

文本张量入门

张量&#xff0c;英文为Tensor&#xff0c;是机器学习的基本构建模块&#xff0c;是以数字方式表示数据的形式。 张量的基本类型: 创建一个标量&#xff08;0维张量&#xff09;&#xff0c;也就是一个单独的数字 scalar torch.tensor(7) scalar.ndim # 返回张量的维度 0 # …...

js文字如何轮播?

<div class"td-style"> <span class"td-text">内容1内容1内容1内容1内容1内容1</span> </div> css&#xff1a; <style> .td-style { width: 160px; height: 72px; overflow: hidden; white-…...

Linux 五种IO模型

注&#xff1a;还有一种信号驱动IO&#xff0c;使用较少暂不讨论&#xff1b; 一&#xff0c;区分阻塞、非阻塞和同步、异步 看了很多文章对这两组概念解释和对比&#xff0c;说的太复杂了&#xff0c;其实没必要&#xff0c;两句话就能说清楚。 首先&#xff0c;对于读数据rec…...

做网站的图片=gif/志鸿优化设计官网

最近一个项目从Ubuntu移植到Redhat&#xff0c;需要安装tomcat。安装完毕后&#xff0c;按惯例需要进行配置&#xff0c;修改/etc/profile以及/etc/envirmonment两个文件。由于配置内容的内容比较多&#xff0c;是直接把配置内容存到一个txt文件中&#xff0c;再在Redhat中用ge…...

政府网站建设经验/应用商店aso

今天收到程序组提交的一个兼容BUG&#xff0c;在火狐中使用模态框加载日期控件时选择时间下拉菜单没有效果(不能点击)&#xff0c;而在谷歌中却是好的&#xff0c;排错思路&#xff1a;1&#xff0c;在当前页面主层放置一个时间控件&#xff0c;测试通过2&#xff0c;在ajax加载…...

哈尔滨网站建设网站制作/网络平台运营是做什么的

这个游戏使用了quake3的引擎&#xff0c;所以画面相当好&#xff0c;在ubuntu里面安装非常简单 sudo apt-get install tremulous 这个游戏只有多人版本&#xff0c;进入游戏之后把网络改成internet&#xff0c;然后get newserver&#xff0c;就可以获取网上的服务器了&#xff…...

wordpress支付宝网页支付/免费外链工具

react-router自版本4开始&#xff0c;发生了很大的变化&#xff0c;其中一点就是&#xff0c;开始倡导组件式使用&#xff0c;不再支持集中式的配置&#xff0c;而出于开发的习惯以及便于项目路由的管理&#xff0c;还是有许多地方希望可用使用集中式的方式来配置路由。下面介绍…...

传媒公司名字起名大全/seo网站排名全选

2019独角兽企业重金招聘Python工程师标准>>> External ID模块名技术名称备注base.module_website网站生成器website base.module_website_sale电子商务website_sale base.module_website_crm联系表单website_crm base.module_website_crm_partner_assign经销商we…...

网站架构分析工具/做个公司网站多少钱

前因后果&#xff1a; 最近公司职位调动&#xff0c;腾出了空闲时间。闲来无事&#xff0c;便寻思着温故而知新。毕竟总不能在公司坐着发呆吧。所以想到了开个博客&#xff0c;把自己知道的发布到网上&#xff0c;寻求更多同道中友。希望自己知道的能帮到更多的人&#xff0c;就…...