基于mocha+chai+istanbul(nyc新版)的node.js单元测试

191 阅读4分钟

一、技术栈:

1、mocha:

发音("摩卡")诞生于2011年,是现在最流行的JavaScript测试框架之一,在浏览器和Node环境都可以使用。 所谓"测试框架",就是运行测试的工具。通过它,可以为JavaScript应用添加测试,从而保证代码的质量。

2、chai:

所谓"断言",就是判断源码的实际执行结果与预期结果是否一致,如果不一致就抛出一个错误。所有的测试用例(it块)都应该含有一句或多句的断言。它是编写测试用例的关键。 断言功能由断言库来实现,Mocha本身不带断言库,所以必须先引入断言库。

3、istanbul(建议用新版nyc,新版兼容es6):

发音("伊斯坦布尔“),测试的时候,我们常常关心,是否所有代码都测试到了,这个指标就叫做“代码覆盖率”(code coverage)。它有四个测量维度:

  • 行覆盖率(line coverage):是否每一行都执行了?
  • 函数覆盖率(function coverage):是否每个函数都调用了?
  • 分支覆盖率(branch coverage):是否每个if代码块都执行了?
  • 语句覆盖率(statement coverage):是否每个语句都执行了?

二、搭建test(项目是require引入依赖的)

1、在项目目录src同级目录创建test文件,进入test

npm init

2、在test目录下安装依赖

npm install mocha chai instanbul

3、package.json

{
  "name": "test",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "chai": "^4.3.10",
    "istanbul": "^0.4.5",
    "mocha": "^10.2.0"
  }
}

4、创建入口文件

test下面创建index.js,1)将项目的依赖写入,避免后续mocha找不到依赖;2)引入断言case。

global.DEV_DEBUG = false; 
if (process.env.NODE_ENV == 'dev') { 
    global.DEV_DEBUG = true; 
}
const config = (global.config = require('../src/config/configration'));
const newConfig = (global.newConfig = require('../src/config/news.config')); 
const LoggerHandle = require('../src/lib/logger'); 
const path = require("path"); 
require("./render/f10research/index.test.js");
require("./render/newresearch/index.test.js");
require("./render/report/index.test.js");

三、写断言

1、创建断言文件

在test文件下创建断言文件(目录结构建议跟src保持一致,在入口index.js引入即可)

2、断言案例

断言case一般以.test.js命名,chai同时支持assert、should、expect三种库,这里用expect断言风格,它很接近自然语言

const expect = require("chai").expect;
const F10researchArticleDetailDo = require("../../../src/render/f10research/index.js");

describe("f10研报", function(){

    it("入参正常", function(){
        expect(F10researchArticleDetailDo('{"INFOCODE":"AP202306171591054563"}')).to.be.ok;
    });

    it("入参为空", function(){
        expect(F10researchArticleDetailDo('')).to.a("undefined");
    });

    it("入参转json失败", function(){
        expect(F10researchArticleDetailDo(**null**)).to.a("undefined");
    });
})

3、断言常用写法

参考文档:

zhuanlan.zhihu.com/p/72575435   

www.jianshu.com/p/a44d689b6…

// 相等或不相等
expect(4 + 5).to.be.equal(9);
expect(4 + 5).to.be.not.equal(10);
expect(foo).to.be.deep.equal({ bar: 'baz' });

// 布尔值为true
expect('everthing').to.be.ok;
expect(false).to.not.be.ok;

// typeof
expect('test').to.be.a('string');
expect({ foo: 'bar' }).to.be.an('object');
expect(foo).to.be.an.instanceof(Foo);

// include
expect([1,2,3]).to.include(2);
expect('foobar').to.contain('foo');
expect({ foo: 'bar', hello: 'universe' }).to.include.keys('foo');

// empty
expect([]).to.be.empty;
expect('').to.be.empty;
expect({}).to.be.empty;

// match
expect('foobar').to.match(/^foo/);

四、启动test

1、启动目录

在项目package.json同级目录下启动,node-pcjob项目是在src下面启动的,大部分项目应该是在src同级目录下执行,即根目录

是项目package.json不是test文件夹的package.json,为确保报告包含所有文件,建议在此目录下执行istanbul运行命令

在哪个目录下运行,coverage报告就会在哪个目录下生成

//mac命令
istanbul cover _mocha ../test/idnex.js

//window命令
istanbul cover test/node_modules/mocha/bin/_mocha ../test/idnex.js

2、配置启动命令

也可以在项目的package.json里scripts里配置启动命令

{
   "name": "",
   "version": "",
   "description": "",
   "author": "",
   "scripts": {
        "test": "istanbul cover test/node_modules/mocha/bin/_mocha ../test/idnex.js"
    },
    "dependencies": {
        ...
    }
    ...
}

//运行
npm run test

五、生成报告

1、打印报告

终端会打印mocha报告和istanbul报告

2、html格式报告

运行目录下会生成一个coverage文件夹,里面有html格式报告,可以在浏览器运行

statement:语句覆盖率;branch:分支覆盖率;function:函数覆盖率;line:行覆盖率

3、case覆盖情况

查看代码case覆盖情况,红色表示未覆盖

六、ES6解决方案

1、使用instanbul升级版nyc;

2、test依赖下载mocha和chai,不要安装instanbul,也无需下载nyc;

3、在src下的package.json运行命令使用nyc即可,一定要加–exit 才会输出报告。

{
   "name": "",
   "version": "",
   "description": "",
   "author": "",
   "scripts": {
        "test": "npx nyc --reporter lcov ../test/node_modules/mocha/bin/_mocha ../test/index.js --exit"
    },
    "dependencies": {
        ...
    }
    ...
}

4、如果运行依赖报错,全局安装nyc(npm install nyc -g),运行命令修改如下:

{
   "name": "",
   "version": "",
   "description": "",
   "author": "",
   "scripts": {
        "test": "nyc --reporter lcov ../test/node_modules/mocha/bin/_mocha ../test/index.js --exit"
    },
    "dependencies": {
        ...
    }
    ...
}

5、nyc.config.js配置

在src下面新建nyc.config.js文件,可以配置包含目录、排除的文件、输出的报告路径等

module.exports = {
    "all": true, //插入所有文件
    "include": [ //覆盖文件
        "worker/**.js"
    ],
    "exclude": [ //排除文件
        "worker/demo.js",
        "worker/f10research.js",
        "worker/research.js"
    ],
    "report-dir": "../test", //报告输出路径
    "temp-dir": "../test/nyc_output" //原始覆盖率信息输出路径
}

6、--exit解释

运行命令为啥要加–exit,不加的话,运行异步代码mocha一直在等待,不会结束,加了mocha不会等待结果返回,不会一直pending。

7、关于异步请求处理

可以在xxx.test.js里重写异步相关的function,如下图,业务代码里用到了comm.request,request有个success回调,是接口请求的回调,mocha执行时,不会等着回调,所以在test/index.js里面重写了comm.request。

参考文献:

www.ruanyifeng.com/blog/2015/1…

www.ruanyifeng.com/blog/2015/0…