上一小节讲解了如何用使用 VS Code 调试 Node.js 代码,但调试不只是打断点,比如:
moment().format('YYYY')
moment().format('yyyy')
本节将介绍 3 款实用的调试工具,分别解决以上 3 种情况,来提高我们的调试效率。
debug 是一个小巧却非常实用的日志模块,可以根据环境变量决定打印不同类型(或级别)的日志。代码如下:
app.js
const normalLog = require('debug')('log') const errorLowLog = require('debug')('error:low') const errorNormalLog = require('debug')('error:normal') const errorHighLog = require('debug')('error:high') setInterval(() => { const value = Math.random() switch (true) { case value < 0.5: normalLog(value); break case value >= 0.5 && value < 0.7: errorLowLog(value); break case value >= 0.7 && value < 0.9: errorNormalLog(value); break case value >= 0.9: errorHighLog(value); break default: normalLog(value) } }, 1000)
运行上面的代码,每一秒生成一个随机数,根据随机数的值模拟不同级别的日志输出:
运行:
$ DEBUG=* node app.js
打印如下:
可以看出,debug 模块打印的日志与 console.log 相比,有以下几个特点:
debug 模块支持以下用法:
下面演示一下第 4 种的用法,运行:
$ DEBUG=error:*,-error:low node app.js
我们在写代码时,有时可能记不清某个模块的某个方法的具体用法,比如:用 moment 格式化年份是用 moment().format('YYYY') 还是用 moment().format('yyyy') 还是两种写法都可以?lodash 的 _.pick 方法能否能接收数组作为参数?这个时候相对于翻阅官方文档,在 REPL 里试一下可能会更快,通常步骤是:
_.pick
$ npm i moment $ node > const moment = require('moment') > moment().format('YYYY') '2017' > moment().format('yyyy') 'yyyy'
一次还好,次数多了也略微烦琐。repl2 模块便是为了解决这个问题而生的。
repl2 顾名思义是 REPL 的增强版,repl2 会根据一个用户配置(~/.noderc),预先加载模块到 REPL 中,省下了我们手动在 REPL 中 require 模块的过程。
全局安装 repl2:
$ npm i repl2 -g
使用方式很简单:
$ npm i lodash validator moment -g
{ "lodash": "__", "moment": "moment", "validator": "validator" }
$ noder __ = lodash@4.17.4 -> local moment = moment@2.18.1 -> global validator = validator@7.0.0 -> global > moment().format('YYYY') '2017' > __.random(0, 5) 3 > validator.isEmail('foo@bar.com') true
需要讲解以下几点:
我们常用的断言库有:
但这类断言库都有一些通病:
先看一段代码:
test.js
const assert = require('assert') const should = require('should') const expect = require('expect.js') const tom = { id: 1, age: 18 } const bob = { id: 2, age: 20 } describe('app.js', () => { it('assert', () => { assert(tom.age > bob.age) }) it('should.js', () => { tom.age.should.be.above(bob.age) }) it('expect.js', () => { expect(tom.age).be.above(bob.age) }) })
$ mocha
结果如下:
app.js 1) assert 2) should.js 3) expect.js 0 passing (13ms) 3 failing 1) app.js assert: AssertionError [ERR_ASSERTION]: false == true + expected - actual -false +true at Context.it (test.js:10:5) 2) app.js should.js: AssertionError: expected 18 to be above 20 at Assertion.fail (node_modules/should/cjs/should.js:275:17) at Assertion.value (node_modules/should/cjs/should.js:356:19) at Context.it (test.js:13:23) 3) app.js expect.js: Error: expected 18 to be above 20 at Assertion.assert (node_modules/expect.js/index.js:96:13) at Assertion.greaterThan.Assertion.above (node_modules/expect.js/index.js:297:10) at Function.above (node_modules/expect.js/index.js:499:17) at Context.it (test.js:16:24)
可以看出,基本没有有用的信息。这时,power-assert 粉墨登场。
power-assert 使用起来很简单,理论上只用一个 assert 就可以了,而且可以无缝迁移。
注意:在使用 intelli-espower-loader 时,要求必须将测试文件放到 test/ 目录下,所以我们在 test 目录下创建 test/app.js,将原来的 test.js 代码粘贴过去。
安装 power-assert 和 intelli-espower-loader,然后运行测试:
$ npm i power-assert intelli-espower-loader --save-dev $ mocha -r intelli-espower-loader
app.js 1) assert 2) should.js 3) expect.js 0 passing (42ms) 3 failing 1) app.js assert: AssertionError [ERR_ASSERTION]: # test/app.js:10 assert(tom.age > bob.age) | | | | | | | | | 20 | | | Object{id:2,age:20} | 18 false Object{id:1,age:18} + expected - actual -false +true ...
错误信息非常直观,有以下两点需要说明:
require('assert')
"directories": { "test": "mytest/" }
如果没有 directories.test 配置,则默认是 test/。
test/
上一节:4.3 Visual Studio Code
下一节:4.5 supervisor-hot-reload
Copyright© 2013-2020
All Rights Reserved 京ICP备2023019179号-8