[聚合文章] 有心无力,适合小项目的 Nodejs 单元测试

JavaScript 2017-11-27 11 阅读

像我这样优秀的猿,本该代码敲一生,怎么我的 Github 上,还是没有一个好项目:sob:。

像我这样的人,遇见不爽,一言不合就要造轮子,开了好多的坑,很多临时的项目,为了 A 而诞生 B,所以也就只能保正在相关项目中可用,如果有另一个项目要调用时,都是提心吊胆的,生怕越写越不好收场。

最近决定,把自己的代码都好好整理一下,能发布的也别让它就安息了,怎么说它也是我思想逻辑的延续,亲生的啊。

这篇也算是我 blog 的第一篇文章了,为什么写了这个题目,因为这是我遇到的第一个问题,参观了一些知名项目的单元测试,看的我泪流满面的,这工作量可是感人啊,还有简单看了现在比较流行的单元测试库,API 也太丰富了吧,并且也太不好用了吧,所以我这脾气怎么能忍,当时就决定造新轮子。

我理解的单元测试功能,小项目友好的,能让你知道修改了代码后,是否还能正常运行就可以了,仅此而已,没有更多,那就开始介绍我的新坑吧, hi-test 单元测试库。

安装

 $ npm install hi-test

项目 github 地址: github.com/wl879/hi-te…

API 我就不在这理堆列了,也没什么功能,直接介绍使用。

使用

0. 查看项目的API

 $ hi-test scan <path>

这条命令会扫描目录中所有 js 文件的 exports, 并列出来,算是一个辅助功能

1. 开始写测试代码

var test = require('hi-test');
test('No.1', (t) => {
    setTimeout(() => {
        t.log('Hello, Iam No.1');
    }, 1000);
});
test('No.2', (t) => {
    t.log('Hello, Iam No.2');
});
输出:
[Test 7956]    No.1     at example/test_sync.js line 3:1
[Test log.]    "Hello, Iam No.1"
[Test DONE]    No.1 (c13171)
[Test d038]    No.2     at example/test_sync.js line 9:1
[Test log.]    "Hello, Iam No.2"
[Test DONE]    No.2 (e893ed)

这里的工作逻辑是,输出你想要测试的结果, t.log 不同于 console.log 输出,会更详细,还有 t.logp 会更详细一点,包括变量的类型也会有标注,所以代码的变化,例如类名称的改变也会影响输出结果,提示:如果变量中包含随机数或时间戳,会有点麻烦,原因请往下看。

这里还要特殊的说明一点,test 间是阻塞执行的,只有上一个 done 之后,后面的才会执行,而 t.done() 是可以自动调用的,是通过监听 process.on('beforeExit') 来实现,所以一般情况下可以不用手动调用,这样它会在对的时间点被调用。

还有一种情况,如果调用的 func 是 aync function , 这将会在 func 结束时自动调用 t.done() , 这种情况适用于以下例子:

var test = require('../')//.enable().enableGC();

let timing = setInterval(()=>{
    console.log('Hi, See you again!');
}, 1000);

test('start', 'e893ed', async (t) => {
    t.log('Hello, Start');
});

test('end', 'd41d8c', (t) => {
    clearInterval(timing);
      t.log('Hello, End');
starr);t}

例子中,如果不手动调用 t.done ,或用 async function 隐式调用,程序会一直的输出 See you again

如果你需要并行执行测试,可以这样写:

var test = require('hi-test');
test('No.1').run((t) => {
    setTimeout(() => {
        t.log('Hello, Iam No.1');
    }, 1000);
});
test('No.2').run((t) => {
    t.log('Hello, Iam No.2');
});
输出:
[Test 7956]    No.1     at example/test_async.js line 3:1
[Test d038]    No.2     at example/test_async.js line 9:1
[Test log.]    "Hello, Iam No.2"
[Test log.]    "Hello, Iam No.1"
[Test DONE]    No.1 (c13171)
[Test DONE]    No.2 (e893ed)

2. 如果输出是对的,还须要把 hash 码还给我

到这里,测试所写的代码以完成 99% 了,是不是没有那些 equal / deepEqual 的API,感觉不像测试的正确用法,是不是上当了,这不就是普通调试时写的代码吗,对与错,基本靠瞅。

是的,很可惜,还不够智能,第一次的输出只能靠瞅来判断对错,好在你只需要瞅一次,如果输出结果是对的,你还须要这样做。

var test = require('hi-test').enable();
再执行输出:
[Test OK]  No.1 (da9f9e)    at example/test_sync.js line 3:1
[Test OK]  No.2 (67319d)    at example/test_sync.js line 9:1

开启 hi-test 后会有以下改变, 1.屏蔽掉无用的输出2.自动添加 hash 码 。What?? 什么是 hash 码。

查看一下,上面的示例中的输出,在 [Test Done]... 那一行中,在 Title 后面会跟着一串 hash 码,这是由捕获到的输出生成的 md5 值, hi-test 也就是通过它来判断测试是否正确的。

如果程序正确,它的每次输出应该是一致的,所以反过来,通过判断两次输出是否一致,也就可以判断程序是否正确。当然这不能适用所有场景,但对于简单的测试还是基本靠谱的(相较于感人的测试代码量)。

手动添加 hash 码

var test = require('hi-test')

test('No.1', 'da9f9e', (t)=>{
  ....
})

只需要将 hash 码做为第二个参数加到 test 函数中即可

筛选输出

每一个 test 的输出中,都会有一个标识,看这里

[Test 7956]    No.1     at example/test_sync.js line 3:1

其中 7956 就是标识,它是由 md5(title) 得来的,所以当你只想查看某一项测试输出时,你可以用它来筛选,像这样

$ node ./test.js | grep '7956'
$ hi-test ./tset.js -df 'No.1'

3. 测试垃圾回收

这里有一个实用的小功能,可以测试某一个变量是否被回收

var test = require('hi-test').enableGC();
var num = [1, 2, 3];

test('CG', (t)=>{
    t.gc(num, 'num');
    // num = null;
});

test('Next', (t) => {
    console.log(num);
});

如果变量 num 被回收则输出

[Test GC  ]    [Yes] >> num

未被回收的话

[Test GC  ]    [No] >> num

4. 开始测试吧

最后介绍一下 hi-test 的命令行,直接看帮助

Usage:
    hi-test <files> [-d] [-a] [-f <title>]
Options:
    +scan <path>            Scan module exports
    -f, --filter <title>    Filter the output
    -d, --debug             Display all output
    -a, --auto              Automation
    -v, --version           Display version
    -h, --help              Display help

在 package.json 中添加上这些一段

"scripts": {
    "test": "hi-test tests/test-*.js -a",
}

收工!!

注:本文内容来自互联网,旨在为开发者提供分享、交流的平台。如有涉及文章版权等事宜,请你联系站长进行处理。