如何在Visual Studio Code中用Mocha对TypeScript进行测试

目录

使用TypeScript编写测试用例

在Visual Studio Code中使用调试器在线调试代码


首先,本文不是一篇介绍有关TypeScript、JavaScript或其它编程语言数据结构和算法的文章。如果你正在准备一场面试,或者学习某一个课程,互联网上可以找到许多相关的资源,我个人比较推崇hackerrank.com。

  本文的主要目的在于帮助你了解并熟知以下两点:

  1. 如何用TypeScript编写并运行测试用例?
  2. 如何在Visual Studio Code中使用调试器在线调试代码,并发现代码中的bug?

使用TypeScript编写测试用例

  在我的电脑中,我创建了一个目录ts-algorithms,在终端上运行下面的命令:

mkdir ts-algorithms
cd ts-algorithms
npm init -y

  这将创建一个最简单的项目结构,其中包含一个package.json文件,你可以根据自己的需要随意修改其中的内容,通常我会加入license、作者、描述和关键字等信息。

  接下来,我们编写一些代码,将其放在src目录中,和测试相关的代码则放在test目录中。手动创建这两个目录,然后用TypeScript编写一个模块。例如,下面是我编写的src/Stack.ts文件的代码:

/*** Implementation of a classic stack.*/
export class Stack<T> {// Internal storage for the stackprivate _items: T[] = [];/*** Creates a pre-populated stack.** @param {T[]} initialData the initial contents of the stack*/constructor(initialData: Array<T> = []) {this._items.push(...initialData)}/*** Adds an item to the top of the stack.** @param {T} item the item to be added to the stack*/push(item: T): void {this._items.push(item);}/*** Removes an item from the top of the stack, returning it.** @returns {T} the item at the top of the stack.*/pop(): T {return this._items.pop();}/*** Take a peek at the top of the stack, returning the top-most item,* without removing it.** @returns {T} the item at the top of the stack.*/peek(): T {if (this.isEmpty())return undefined;elsereturn this._items[this._items.length - 1];}/*** @returns {boolean} true if the stack is empty.*/isEmpty(): boolean {return this._items.length === 0;}/*** @returns {number} the number of items in the stack.*/size(): number {return this._items.length;}
}

   同时我还在src目录下添加了index.ts文件,用来导出所有的模块。目前只有简单的一行代码:

export { Stack } from './Stack';

  为了进行单元测试,我使用了mocha和chai这两个包,我们通过下面的命令将它们安装到项目里:

npm install --save-dev mocha chai

  由于mocha不会自动运行TypeScript代码,所以我们还需要用到ts-node

npm install --save-dev ts-node typescript

  另外,如果能让Visual Studio Code编辑器理解mochachai的类型并为其提供智能感知功能那就太好了,所以我们加上下面这两个包:

npm install --save-dev @types/chai @types/mocha

  然后,我们在package.json中加入一个script的入口,这样我们就可以通过一个命令行来运行我们的测试程序:

"scripts": {"tests": "mocha --require ts-node/register test/**/*.ts"
},

  注意这里的--require ts-node/register很重要,它将TypeScript注册为解释器,这样我们就可以用TypeScript编写测试用例了。

  让我们创建文件test/stack.ts,编写测试用例以对src/Stack.ts进行测试:

import { expect } from 'chai';
import { Stack } from '../src';describe('Stack', () => {it('can be initialized without an initializer', () => {const s = new Stack<number>();expect(s.size()).to.equal(0);});it('can be initialized with an initializer', () => {const s = new Stack<number>([ 1, 2, 3, 4 ]);expect(s.size()).to.equal(4);});it('can be pushed upon', () => {const s = new Stack<number>([ 1, 2, 3, 4 ]);s.push(5);expect(s.size()).to.equal(5);expect(s.peek()).to.equal(5);});it('can be popped', () => {const s = new Stack<number>([ 1, 2, 3, 4 ]);expect(s.pop()).to.equal(4);expect(s.size()).to.equal(3);});it('can be peeked', () => {const s = new Stack<number>([ 1, 2, 3, 4 ]);expect(s.peek()).to.equal(4);expect(s.size()).to.equal(4);});it('isEmpty() returns true when empty', () => {const s = new Stack<number>();expect(s.isEmpty()).to.be.true;});it('isEmpty() is false when not empty', () => {const s = new Stack<number>([1, 2, 3, 41]);expect(s.isEmpty()).to.be.false;});it('cannot pop when no elements', () => {const s = new Stack<number>();expect(s.pop()).to.be.undefined;});it('cannot peek when empty', () => {const s = new Stack<number>();expect(s.peek()).to.be.undefined;});
});

  为了确保TypeScript在编译时通过类型检查,我们还需要在项目的根目录下添加tsconfig.json文件,并将mocha添加到types配置节点中:

{"compilerOptions": {"types": ["mocha"]}
}

  否则,直接运行测试,你可能会遇到下面这样的错误:

TSError: ⨯ Unable to compile TypeScript:
test/stack.ts:4:1 - error TS2593: Cannot find name 'describe'. Do you need to install type definitions for a test runner? Try `npm i --save-dev @types/jest` or `npm i --save-dev @types/mocha` and then add 'jest' or 'mocha' to the types field in your tsconfig.

  所有工作准备就绪后,我们通过下面的命令直接运行测试:

npm run tests

  你也可以在Visual Studio Code的集成终端窗口中运行上面的命令(View > Terminal)。如果一切正常,你应该会得到如下图所示的结果(所有9个测试用例都检测成功):

   注意这里所有的代码,包括测试用例,都是用TypeScript编写的。此外,借助于Visual Studio Code编辑器,你还可以在编译时进行类型检查,泛型类型审查以及获得对JavaScript所进行的一系列其它增强。

在Visual Studio Code中使用调试器在线调试代码

  我们不仅仅只能运行测试,我们还可以做得更好。如果我们的测试用例在运行中遇到问题怎么办?例如,让我们在src/Stack.ts文件中加入一行代码,使isEmpty()方法始终报错:

isEmpty(): boolean {throw new Error("Something went wrong");return this._items.length === 0;
}

  重新运行测试,首先失败的就是第三个测试用例——"can be pushed upon"。我很想知道它为什么会失败!在Visual Studio Code中打开Run and Debug

   然后左侧的窗口变成下面这样:

   在进行调试之前,我需要告诉Visual Studio Code如何在调试器中运行测试,点击Run and Debug按钮下方的create a launch.json file链接,然后在弹出的下拉列表中选择Node.js环境。这将在.vscode目录中创建一个launch.json配置文件,其中包含了一个默认的启动配置项,我们将该配置项删除,然后点击界面右下角的Add Configuration按钮,在弹出的列表中选择{} Node.js: Mocha Tests,这是运行mocha测试的基本配置项。不过,这里我们需要给mocha添加一些命令行参数,正如我们在package.json文件的script中向mocha添加的参数一样。

{// Use IntelliSense to learn about possible attributes.// Hover to view descriptions of existing attributes.// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387"version": "0.2.0","configurations": [{"args": ["--require", "ts-node/register","-u","bdd","--timeout","999999","--colors","${workspaceFolder}/test/**/*.ts"],"internalConsoleOptions": "openOnSessionStart","name": "Mocha Tests","program": "${workspaceFolder}/node_modules/mocha/bin/_mocha","request": "launch","type": "pwa-node"}]
}

  注意这里的args配置项,它包含了一些非常重要的配置,其中之一就是我们在package.json文件的script中向mocha添加的命令行参数"--require"和"ts-node/register"。另外就是"${WorkspaceFolder}/test/**/*.ts"用来指定测试文件所在的目录。还有一个就是我们将默认生成的配置项"tdd"改成"bdd"以确保mocha在Visual Studio Code的debugger模式下能正确运行。

  现在,我们可以在测试代码中打断点:

   然后,在Visual Studio Code的Run and Debug窗口中点击绿色的运行按钮:

   一旦断点被命中,程序会暂停,然后你可以逐步跟踪代码执行:

   该控制条会显示在屏幕的顶部,从左到右依次是:

  • 继续执行,直到下一个断点。
  • 执行到下一个语句。
  • 进入下一个语句内部。
  • 跳出当前语句。
  • 重新运行。
  • 停止运行。

  同时,Visual Studio Code的左侧也有一些和调试相关的窗口,其中包含当前程序运行的变量的信息(通常会非常有用)、被监视的变量的值、调用堆栈以及断点的位置信息等等。

  我们可以试着来调试一下。前两个测试用例已经成功运行了,我们创建了stack类并且测试了它的size。在接下来的测试中我想要测试push()peek()这两个方法。我们执行下面的操作:

  • 跳过stack类的创建。
  • 进入到push()方法内部。
  • 在push()方法内部跳过stack数组的push()调用。

  光标现在出现在push()方法的末尾,现在我可以查看一下变量的值——特别是this._items变量的值,因为它表示的是stack类中items的数量。目前一切看起来都很正常,让我们继续:

  • 跳过push()方法的返回。
  • 然后我们可以直接跳过对size()方法的测试语句,因为前面的测试用例已经测试过了。
  • 进入到peek()方法内部。
  • 进入到this.isEmpty()方法内部。
  • 然后我们看到程序抛出一个异常。

   如果想要暂时隐藏断点使其在程序运行时不被命中,可以在左侧的breakpoints窗口中点击Toggle Activate Breakpoints。再次点击时可以激活所有已添加的断点。

  你可以通过Visual Studio Code提供的这种在线调试工具来一步步跟踪执行我们的代码,从而分析每个步骤中各个变量的值,看看它们是否和你预期的一致。你熟知你的算法,在编码之前可以先在纸上将整个执行过程画一遍,然后看看最终程序运行时是否偏离了你的预期?

  另外需要注意的是,在调试过程中,我们看到的是TypeScript代码,而不是编译之后的JavaScript代码。

  现在我们可以使用Visual Studio Code来编写更多丰富的功能强大的TypeScript代码。


 以下是我收集到的比较好的学习教程资源,虽然不是什么很值钱的东西,如果你刚好需要,可以评论区,留言【777】直接拿走就好了

各位想获取资料的朋友请点赞 + 评论 + 收藏,三连!

三连之后我会在评论区挨个私信发给你们~

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/74600.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

tdengine入门详解

TDengine是什么&#xff1f; TDengine 是一款开源、高性能、云原生的时序数据库&#xff08;Time Series Database, TSDB&#xff09;, 它专为物联网、车联网、工业互联网、金融、IT 运维等场景优化设计&#xff0c;基于C语言开发。 什么是时序数据库&#xff1f;时序数据产生…

C++ 对象数组

**数组元素不仅可以是基本数据类型&#xff0c;也可以是自定义类型。**例如&#xff0c;要存储和处理某单位全体雇员的信息&#xff0c;就可以建立一个雇员类的对象数组。对象数组的元素是对象&#xff0c;不仅具有数据成员&#xff0c;而且还有函数成员。 因此&#xff0c;和基…

Libevent开源库的介绍与应用

libeventhttps://libevent.org/ 一、初识 1、libevent介绍 Libevent 是一个用C语言编写的、轻量级的开源高性能事件通知库&#xff0c;主要有以下几个亮点&#xff1a;事件驱动&#xff08; event-driven&#xff09;&#xff0c;高性能;轻量级&#xff0c;专注于网络&#xff…

Linux系统安装部署MongoDB完整教程(图文详解)

前言&#xff1a;本期给大家分享一下目前最新Linux系统安装部署MongoDB完整教程&#xff0c;我的服务器采用的是Centos7&#xff0c;在部署之前我重装了我的服务器&#xff0c;目的是为了干净整洁的给大家演示我是如何一步步的操作的&#xff0c;整体部署还是挺简洁&#xff0c…

如何维护你的电脑:提升性能和延长使用寿命

如何维护你的电脑&#xff1a;提升性能和延长使用寿命 &#x1f607;博主简介&#xff1a;我是一名正在攻读研究生学位的人工智能专业学生&#xff0c;我可以为计算机、人工智能相关本科生和研究生提供排忧解惑的服务。如果您有任何问题或困惑&#xff0c;欢迎随时来交流哦&…

【机器学习】西瓜书习题3.3Python编程实现对数几率回归

参考代码 结合自己的理解&#xff0c;添加注释。 代码 导入相关的库 import numpy as np import pandas as pd import matplotlib from matplotlib import pyplot as plt from sklearn import linear_model导入数据&#xff0c;进行数据处理和特征工程 # 1.数据处理&#x…

Go语音介绍

Go语言介绍 Go 即Golang&#xff0c;是Google公司2009年11月正式对外公开的一门编程语言。 Go是静态强类型语言&#xff0c;是区别于解析型语言的编译型语言。 解析型语言——源代码是先翻译为中间代码&#xff0c;然后由解析器对代码进行解释执行。 编译型语言——源代码编…

Redis 6.5 服务端的读取缓冲区和输出缓冲区执行源码

通篇全文都是不开启事务&#xff0c;不开启多线程&#xff0c;只有主线程去执行 借鉴 Redis源码与设计剖析 – 18.Redis网络连接库分析 客户端与集群之间数据的交互 IO多路复用与客户端、输出缓冲区和读取缓冲区之间的关系一、读取缓冲区1、新客户端连接时注册从socket读取事件…

【css】解决元素浮动溢出问题

如果一个元素比包含它的元素高&#xff0c;并且它是浮动的&#xff0c;它将“溢出”到其容器之外&#xff1a;然后可以向包含元素添加 overflow: auto;&#xff0c;来解决此问题&#xff1a; 代码&#xff1a; <!DOCTYPE html> <html> <head> <style>…

基于遗传算法的试题组卷(二)

实例讲解 一、准备工作 1、问题实体 问题实体包含编号、类型&#xff08;类型即题型&#xff0c;分为五种&#xff1a;单选&#xff0c;多选&#xff0c;判断&#xff0c;填空&#xff0c;问答&#xff0c; 分别用1、2、3、4、5表示&#xff09;、分数、难度系数、知识点。一…

C++ 智能指针

C 智能指针 为什么需要智能指针&#xff1f;auto_ptrunique_ptrshared_ptrweak_ptr智能指针的核心实现unique_ptr的简单实现Counter的简单实现share_ptr的简单实现weak_ptr简单实现 shared_ptr的线程安全性多线程无保护读写 shared_ptr 可能出现的问题make_shared()share_ptr/u…

卸载本机已安装的node.js(v.16.13.0版本)

因为要用多版本的node&#xff0c;准备安装一个nvm管理&#xff0c;所以需要先卸载掉原来安装的v.16.13.0版本。 记录一下卸载过程 1、在系统设置-应用里卸载node 妈蛋这样卸载报错。。找了下根本没有这个路径 那就只能最简单的方法了&#xff0c;全部删掉 1、删除node的安装…

IDEA用Gradle构建项目时,lombok插件无效的解决办法

Lombok 可用来帮助开发人员消除 Java 的重复代码&#xff0c;尤其是对于简单的 Java 对象&#xff08;POJO&#xff09;&#xff0c;比如说getter/setter/toString等方法的编写。它通过注解实现这一目的。 正确使用姿势 一、安装Lombok插件 菜单栏File -> Settings ->…

通过MySQL删除Hive元数据信息

之前遇到过一个问题&#xff0c;在进行Hive的元数据采集时&#xff0c;因为Hive表的文件已经被删除了&#xff0c;当时是无法删除表&#xff0c;导致元数据采集也发生了问题&#xff0c;所以希望通过删除Hive表的元数据解决上述问题。 之前安装时&#xff0c;经过特定的配置后…

Qt实现自定义QDoubleSpinBox软键盘

在Qt应用程序开发中&#xff0c;经常会遇到需要自定义输入控件的需求。其中&#xff0c;对于QDoubleSpinBox控件&#xff0c;如果希望在点击时弹出一个自定义的软键盘&#xff0c;以便用户输入数值&#xff0c;并将输入的值设置给QDoubleSpinBox&#xff0c;该如何实现呢&#…

【MySQL】MySQL数据类型

文章目录 一、数据类型的分类二、tinyint类型2.1 创建有符号数值2.2 创建无符号数值 三、bit类型三、浮点类型3.1 float3.2 decimal类型 四、字符串类型4.1 char类型4.2 varchar类型 五、日期和时间类型六、枚举和集合类型6.1 enum的枚举值和set的位图结构6.2 查询集合find_in_…

大数据技术之Clickhouse---入门篇---SQL操作、副本

星光下的赶路人star的个人主页 积一勺以成江河&#xff0c;累微尘以崇峻极 文章目录 1、SQL操作1.1 Insert1.2 Update 和 Delete1.3 查询操作1.4 alter操作1.5 导出数据 2、副本2.1 副本写入流程2.2 配置步骤 1、SQL操作 基本上来说传统关系型数据库&#xff08;以 MySQL 为例…

Java 使用 Google Guava 实现接口限流

一、引入依赖 <dependency><groupId>com.google.guava</groupId><artifactId>guava</artifactId><version>30.0-jre</version> </dependency>二、自定义注解及限流拦截器 自定义注解&#xff1a;Limiter package com.haita…

linux 常用命令

防火墙 1.查看下防火墙的状态&#xff1a;systemctl status firewalld systemctl stop firewalld 关闭 systemctl disable firewalld 开机不启永久关闭 2.查看已开放的端口firewall-cmd --zonepublic --list-ports firewall-cmd --permanent --zonepublic --…

【Android Framework系列】第9章 AMS之Hook实现登录页跳转

1 前言 前面章节我们学习了【Android Framework系列】第5章 AMS启动流程和【Android Framework系列】第6章 AMS原理之Launcher启动流程&#xff0c;大概了解了AMS的原理及启动流程&#xff0c;这一章节我们通过反射和动态代理对不同Android版本下的AMS进行Hook&#xff0c;实现…