前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >JavaScript单元测试利器Jest+mocha+chai

JavaScript单元测试利器Jest+mocha+chai

原创
作者头像
晴空SunnySky
修改2023-09-28 15:50:59
3760
修改2023-09-28 15:50:59
举报
文章被收录于专栏:QA在路上QA在路上

一:mocha介绍

mocha是一款功能丰富的javascript单元测试框架,它既可以运行在nodejs环境中,也可以运行在浏览器环境中。 javascript是一门单线程语言,最显著的特点就是有很多异步执行。同步代码的测试比较简单,直接判断函数的返回值是否符合预期就行了,而异步的函数,就需要测试框架支持回调、promise或其他的方式来判断测试结果的正确性了。mocha可以良好的支持javascript异步的单元测试。 mocha会串行地执行我们编写的测试用例,可以在将未捕获异常指向对应用例的同时,保证输出灵活准确的测试结果报告。

chai 是一个针对 Node.js 和浏览器的行为驱动测试和测试驱动测试的断言库,可与任何 JavaScript 测试框架集成。

istanbul是一个 JavaScript 的代码覆盖率检查库。其有如下特性:

  • 可检查包括语句、分支和函数覆盖,以及反向工程的代码行覆盖
  • 模块加载钩子 可随时跟踪代码
  • 命令行工具 可运行带覆盖率检查的 node 单元测试,不需要对测试运行进行协作
  • 可生成 HTML 和 LCOV 报表
  • 可作为中间件使用,在浏览器进行测试
  • 可在命令行中以库的形式使用

二:JavaScript基础知识

(PS:不入虎穴焉得虎子,先自己搞定JS基础知识 再谈其他的)

2.1 JavaScript的变量

JS中变量的命名规则:

1.由字母、数字、下划线组成,区分大小写

2.必须以字母开头

3.变量名不能有空格,且大小写敏感

4.不能使用 JavaScript 中的关键字做变量名

变量声明:

在 JavaScript 中,用 Var 命令做声明变量,当然变量也可以不作声明,而在使用时再根据数据的类型来确其变量的类型;

代码语言:javascript
复制
length = 16;                                  // Number
 var string_name = "Johnson";                         // String
 var datalist = ["Audi", "Fox", "Lecsax"];              // Array 
 var person = {firstName:"John", lastName:"Doe"};  // Object

JS的变量类型分为值类型和引用类型:

值类型变量的特点是

代码语言:javascript
复制
1:占用空间固定,保存在栈中。
2:保存与赋值的是值本身。
3:使用typeof检测数据的类型。
4:基本类型数据是值类型。

引用类型的变量特点是

代码语言:javascript
复制
1:占用空间不固定,保存在堆中。
2:保存和赋值的是指向对象的一个指针。
3:使用instanceof检测数据的类型。
4:使用new()方法构造出的对象是引用型。

变量的作用域和生命周期:

全局变量(分为函数外定义的变量和在函数内定义的无var声明的变量)可以在任何位置调用。

局部变量(分为在函数内使用var声明的变量和函数的参数变量)只能在当前函数体内调用。

JavaScript变量生命周期: 在它声明时初始化。局部变量在函数执行完毕后销毁。

全局变量在页面关闭后销毁,即:除非被显式销毁,否则一直存在。

2.2JavaScript数据类型

Undefined:

使用var声明变量但是未进行初始化,对未初始化的变量及未声明的变量使用typeof运算符均会返回undefined;undefined的变量和null用”==”进行比较时会返回true,因为undefined派生自null。声明空对象时我们可以将其初始化为null。

Null:null表示一个空对象的指针,使用typeof检查null时会返回object。

Boolean:true为真,false为假。

我们使用boolen()对各种数据类型的变量进行强制转换时的规则如下:非空字符串,非零数值,非空对象进行boolen()转换时返回true。

空字符串,0及NaN,null及undefined进行boolen()转换时返回false。

String:单引号和双引号不能交叉使用;使用.length属性访问字符串长度;字符串一旦被创建,其值不能改变,若想改变必须销毁原有字符串。String中常见的转义:\n换行;\t制表符;\b空格;\r回车符;\f分页符;\\斜杠\。

强制类型转换为string的函数有两种,分别是toString()和String()。

其中number,boolean,string,object以及number类型的数值基数使用toString()进行转换。

Null,undefined使用String()函数进行强制类型转换的操作。

Number:NaN的含义:not a Number或者非数值。任何涉及NaN的操作都将返回NaN;NaN与任何数值都不相等包括其自身。

Object:Object是一组数据或功能的集合。

2.3JavaScript中的运算符

+

加法

-

减法

*

乘法

/

除法

%

取模(余数)

++

自增

--

自减

&&

逻辑与

||

逻辑或

!

逻辑非

2.4JavaScript中的流程控制语句

代码语言:javascript
复制
If/else if/else 选择语句:
If(条件表达式A){
代码段1
}else if(条件表达式B){
代码段2
}else{
代码段3
}

Switch/case 选择语句:

代码语言:javascript
复制
Switch(条件表达式){
Case 标签A:
代码段1;
Break;
Case 标签B
代码段2;
Break;
Default:
代码段n;
}

While循环语句:

代码语言:javascript
复制
While(条件表达式){
循环执行代码段
}

While循环先检查条件再进行循环操作,可能一次循环也不执行。

代码语言:javascript
复制
Do-while循环语句:
Do{
循环执行的代码段
}while(条件表达式);

Do-while循环先执行循环代码段再检查条件,do-while循环至少被执行一次。

For循环语句:

代码语言:javascript
复制
For(循环变量=初始值; 循环条件; 递增/递减计数器){
循环执行代码段
}

用循环变量的初始值与循环条件相比较来确定是否执行循环。

For-in循环语句:

代码语言:javascript
复制
For(声明变量 in 对象){
代码段
}

循环输出的变量顺序不可预知,对象的值不能是null或者undefined。

在循环体中有3种跳转语句:

代码语言:javascript
复制
Return==终止函数体的运行,并返回一个值。
Break==终止整个循环。
Continue==结束当前循环,判断是否执行下次循环。

异常处理语句有4中:

代码语言:javascript
复制
Throw==主动抛出异常。
Try==指明需要处理的代码段。
Catch==捕获异常。
Finally==后期处理。

2.5JavaScript中的函数

函数就是包裹在花括号中的代码块,前面使用了关键词 function:

代码语言:javascript
复制
function func_name(var1,var2)
 {
 执行代码
 }

当调用该函数时,会执行函数内的代码。

可以在某事件发生时直接调用函数(比如当用户点击按钮时),并且可由 JavaScript 在任何位置进行调用。

JavaScript 对大小写敏感。关键词 function 必须是小写的,并且必须以与函数名称相同的大小写来调用函数。

2.6JavaScript中的数组

数组对象是使用单独的变量名来存储一系列的值。

创建空数组:

代码语言:javascript
复制
var obj = new Array();

创建指定长度的数组:

代码语言:javascript
复制
var obj = new Array(9);

创建指定元素的数组:

代码语言:javascript
复制
var obj = new Array(‘hello’, ‘word’, ‘this’, ‘is’, ‘JS’);

代码语言:javascript
复制
单维数组的创建:var obj = [];

在一个数组中可以有不同的对象,所有的JavaScript变量都是对象。数组元素是对象。函数是对象。可以在一个数组中包含对象元素、函数、数组。

2.7JavaScript对DOM的操作

获取节点:

代码语言:javascript
复制
document.getElementById(元素ID)通过元素ID获取节点。
document.getElementsByName(元素name属性)通过元素的name属性获取节点。
document.getElementsByTagName(元素标签)通过元素标签获取节点。

对节点赋值:

代码语言:javascript
复制
document.getElementById("p1").innerHTML="新文本!";

2.8JavaScript中的window对象

window和document的区别:

1、window指窗体。document指页面。document是window的一个子对象。

2、用户不能改变document.location(因为这是当前显示文档的位置)。但是,可以改变window.location (用其它文档取代当前文档)window.location本身也是一个对象,而document.location不是对象只是一个可读的字符串。

Window对象中定位节点

代码语言:javascript
复制
window.document.getElementById("header");
Window对象对节点赋值
window.document.getElementById("txtOperationDay").value="${手术日期}";

PS: UI自动化测试对日历控件若不好操作,则可使用window.document.getElementById()等方法来赋值;

当然,对页面元素的赋值可使

代码语言:javascript
复制
Execute Javascript $("#txtSteepReference").val("${浸润危害}")

读取页面元素的值可用

代码语言:javascript
复制
Execute Javascript return $("#txtCancerBasicLevel").val()

通过JS来模拟点击事件

代码语言:javascript
复制
Execute Javascript $("#SaveInvolveRangeAndDerived").click()

三:环境配置及实战

首先安装node 不多说,请自行谷歌;

代码语言:javascript
复制
安装mocha:npm install –g mocha

代码语言:javascript
复制
安装chai:npm i –g chai

代码语言:javascript
复制
安装istanbul:npm install -g istanbul

环境配置完事儿

3.1:mocha+chai实例演练

我们先来个简单的小例子哈~

先写个add.js

代码语言:javascript
复制
function add(x, y) {
 return x + y;
 }
 //当前模块输出函数
 module.exports = add;

与exports相比module.exports是真正的接口,exports只不过是它的一个辅助工具。 最终返回给调用的是Module.exports而不是exports。 所有的exports收集到的属性和方法,都赋值给了module.exports。当然,这有个前提,就是module.exports本身不具备任何属性和方法。如果,module.exports已经具备一些属性和方法,那么exports收集来的信息将被忽略。

再写测试用例:

代码语言:javascript
复制
var add = require('./add.js');
 var expect = require('chai').expect;
 
 describe('函数的测试', function()
 {
 it('4和3的结果 应该等于 8', function()
 {
 expect(add(4, 3)).to.be.equal(7);
 });
 
 it('Hello和3的结果 应该等于Hello3', function()
 {
 expect(add('Hello', 3)).to.be.equal('Hello3');
 });
 
 it('Hello和World的结果 应该等于HelloWorld', function()
 {
 expect(add('Hello', 'World')).to.be.equal('HelloWorld');
 });
 }
 );

/* describe块的作用类似于"测试套件"(test suite),表示一组相关的测试。 it块才是真正执行的部分,it块作用就是"测试用例"(test case),表示一个单独的测试,是测试的最小单位。 describe块中可以包含无数个it块。 chai断言库中有expect和should两种断言api可以用,根据个人喜好选择。 /*

我们切换到项目目录下来执行命令:mocha add.test.js 结果如图:

C:\Users\IP-206\AppData\Roaming\Tencent\Users\834321678\QQ\WinTemp\RichOle\0)~ZSCZC_}V2(MKEO`5VM$1.png
C:\Users\IP-206\AppData\Roaming\Tencent\Users\834321678\QQ\WinTemp\RichOle\0)~ZSCZC_}V2(MKEO`5VM$1.png

实际项目中,我们一般把js源文件和单元测试文件分开放在不同的目录下:

下面是根据业务判断逻辑设计出的用例(我这里使用的是判定条件覆盖的方法)

代码语言:javascript
复制
/*
* @Author: linbin.jiang
* @Date: 2023-06-01
* @LastEditors: linbin.jiang
* @LastEditTime: 2023-06-09
* @Description:
*/
var expect = require('chai').expect
var out_link = require('../../../src/utils/outer-link')
describe('是否外链', function()
{
it('传参非token字符串,预期返回false', function()
{
expect(out_link.outLinkCheck('123456')).to.be.false;
}),
it('传参非token,预期返回false', function()
{
expect(out_link.outLinkCheck('abcdefg')).to.be.false;
}),
it('传参非token,预期true(演示断言失败)', function()
{
expect(out_link.outLinkCheck('abcdefg')).to.be.true;
})
}
);

我们看到有红色的输出就说明我们用例有失败的,一目了然哪个case是失败的

3.2:Jest实例演练

代码语言:javascript
复制
安装jest:npm install -g jest
代码语言:javascript
复制
初始化项目的jest配置: jest --init

针对JS方法的测试用例:

代码语言:javascript
复制
import { timestampToTime, timestampToTimeString } from '../src/utils/util-time'
describe('timestampToTime', () => {
test('时间戳转换成日期对象', () => {
const d = new Date(2020, 4, 11, 12, 25).getTime()
expect(timestampToTime(d)).toEqual({
day: 11,
hours: 12,
minutes: 25,
month: '05',
year: 2020
})
expect(timestampToTime(null)).toBe(null)
})
})
describe('timestampToTimeString', () => {
test('时间戳转换成日期字符串', () => {
const d = new Date(2020, 4, 11, 12, 25).getTime()
expect(timestampToTimeString(d, 'yyyy-MM-dd HH:mm')).toBe('2020-05-11 12:25')
expect(timestampToTimeString(d, 'yyyy-MM-dd')).toBe('2020-05-11')
})
})

测试结果:执行jest即可自动执行。

参考文档: mocha官网:https://mochajs.bootcss.com/ chai官网:https://www.chaijs.com/ istanbul官网:https://istanbul.js.org/ Jest中文站:https://www.jestjs.cn/ vue-test-utils: https://vue-test-utils.vuejs.org/zh/

我正在参与2023腾讯技术创作特训营第二期有奖征文,瓜分万元奖池和键盘手表

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一:mocha介绍
  • 二:JavaScript基础知识
    • 2.1 JavaScript的变量
      • 2.2JavaScript数据类型
        • 2.3JavaScript中的运算符
          • 2.4JavaScript中的流程控制语句
            • 2.5JavaScript中的函数
              • 2.6JavaScript中的数组
                • 2.7JavaScript对DOM的操作
                  • 2.8JavaScript中的window对象
                  • 三:环境配置及实战
                    • 3.1:mocha+chai实例演练
                      • 3.2:Jest实例演练
                      相关产品与服务
                      消息队列 TDMQ
                      消息队列 TDMQ (Tencent Distributed Message Queue)是腾讯基于 Apache Pulsar 自研的一个云原生消息中间件系列,其中包含兼容Pulsar、RabbitMQ、RocketMQ 等协议的消息队列子产品,得益于其底层计算与存储分离的架构,TDMQ 具备良好的弹性伸缩以及故障恢复能力。
                      领券
                      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档