文档章节

AVA实践:面向未来的Node.js测试运行器

i5ting
 i5ting
发布于 2016/05/26 14:47
字数 1417
阅读 464
收藏 4

ava-practice

img

ava 是什么?

面向未来的测试运行器

https://github.com/avajs/ava

简单的说ava是mocha的替代品,

  • es6语法支持更好,对aysnc/await有支持
  • 执行效率更高,使用io并发,就必须保证测试的原子性
  • 语义上更简单,集众家之长

虽然 JavaScript 是单线程,但在 Node.js 里由于其异步的特性使得 IO 可以并行。AVA 利用这个优点让你的测试可以并发执行,这对于 IO 繁重的测试特别有用。另外,测试文件可以在不同的进程里并行运行,让每一个测试文件可以获得更好的性能和独立的环境。在 Pageres 项目中从 Mocha切换 到 AVA 让测试时间从 31 秒下降到 11 秒。测试并发执行强制你写原子测试,意味着测试不需要依赖全局状态或者其他测试的状态,这是一件非常好的事情。

为什么要用 AVA?

  • 轻量和高效
  • 简单的测试语法
  • 并发运行测试
  • 强制编写原子测试
  • 没有隐藏的全局变量
  • 为每个测试文件隔离环境
  • 用 ES2015 编写测试
  • 支持 Promise
  • 支持 Generator
  • 支持 Async
  • 支持 Observable
  • 强化断言信息
  • 可选的 TAP 输出显示
  • 简明的堆栈跟踪

AVS VS Mocha

ava-vs-mocha.png

origin

断言

ava支持的断言都比较简单,总体来说是抄自tap和tape,除了plan方法外。

  • .pass([message])

Passing assertion.

  • .fail([message])

Failing assertion.

  • .truthy(value, [message])

Assert that value is truthy.

  • .falsy(value, [message])

Assert that value is falsy.

  • .true(value, [message])

Assert that value is true.

  • .false(value, [message])

Assert that value is false.

  • .is(value, expected, [message])

Assert that value is equal to expected.

  • .not(value, expected, [message])

Assert that value is not equal to expected.

  • .deepEqual(value, expected, [message])

Assert that value is deep equal to expected.

  • .notDeepEqual(value, expected, [message])

Assert that value is not deep equal to expected.

  • .throws(function|promise, [error, [message]])

Assert that function throws an error, or promise rejects with an error.

error can be a constructor, regex, error message or validation function.

Returns the error thrown by function or the rejection reason of promise.

  • .notThrows(function|promise, [message])

Assert that function doesn't throw an error or promise resolves.

  • .regex(contents, regex, [message])

Assert that contents matches regex.

  • .ifError(error, [message])

Assert that error is falsy.

自定义断言

使用node.js sdk里默认的assert

import assert from 'assert';

test(t => {
    assert(true);
});

使用chai断言库,支持3种风格

import test from 'ava';

var assert = require('chai').assert;
var expect = require('chai').expect;
var should = require('chai').should();

test('expect with chai', t => {
  // typeof
  expect('test').to.be.a('string');
  expect({ foo: 'bar' }).to.be.an('object');
  expect(null).to.be.a('null');
  expect(undefined).to.be.an('undefined');
  expect(new Error).to.be.an('error');
  expect(new Float32Array()).to.be.a('float32array');
  expect(Symbol()).to.be.a('symbol');
});

test('should with chai', t => {
  var foo = 'bar'
  var tea = {
    flavors:[1,2,2]
  }
  foo.should.be.a('string');
  foo.should.equal('bar');
  foo.should.have.length(3);
  tea.should.have.property('flavors')
    .with.length(3);
});

test('assert with chai', t => {
  var foo = 'bar'
  var tea = {
    flavors:[1,2,2]
  }
  assert.typeOf(foo, 'string');
  assert.equal(foo, 'bar');
  assert.lengthOf(foo, 3)
  assert.property(tea, 'flavors');
  assert.lengthOf(tea.flavors, 3);
});

hook

test方法默认是顺序执行,如果里面是顺序执行的,那么它是正常的。如果里面是异步方法呢?结果是test执行完了,而异步方法还在跑,这样的结果是,这个测试怎么跑都是正确的,因为没有走断言。。。。

演示代码如下

test('#register()', t => {
  // 此方法是异步的,保存需要时间
  user.save((err, u) => {
    console.log(err)
    console.log('u=' + u)
    t.true(u.password.length > 50)
  })
});

当test完成,user.save还没完成,结果0断言,测试结果显示成功。。。这是非常典型的例子。

最简单的回调,注意写法,test.cb意味着这是需要调用t.end()才能结束,对于测试异步方法非常好用

test.cb('#register()', t => {
  // 此方法是异步的,保存需要时间
  user.save((err, u) => {
    console.log(err)
    console.log('u=' + u)
    t.true(u.password.length > 50)
    t.end()
  })
});
  • t.end() 结束异步调用,仅仅在test.cb()方法里有效

下面例子中,保证在测试save方法之前,执行完成before。也就是说,执行before等待2秒,然后再开始跑其他测试。

test.before.cb((t) => {
  setTimeout(() => {
    t.end();
  }, 2000);
});

test('#save()', t => {
  let user = new User({
    username: 'i5ting',
    password: '0123456789'
  });

  user.save((err, u) => {
    if (err) log(err)
    t.is(u.username, 'i5ting');
  });
});

其他cb方法可依此类推

Control flow

  • Promise
  • Generator
  • Async/await

Promise 支持

If you return a promise in the test you don't need to explicitly end the test as it will end when the promise resolves.

test(t => {
    return somePromise().then(result => {
        t.is(result, 'unicorn');
    });
});

Generator 函数支持

AVA comes with built-in support for generator functions.

test(function * (t) {
    const value = yield generatorFn();
    t.true(value);
});

具体在mongoose里的generator里使用

test('#save()', function * (t) {
  var u = yield User.create(user)
  t.is(u.username, 'i5ting');
});

测试console.log或者其他终端输出内容,推荐使用co-exec,然后将结果正则匹配就好了

import test from 'ava';

var exec = require('co-exec');

test('exec()', function * (t) {
    var commit = yield exec('ls -alt|grep .gitignore|wc -l');
    console.log(commit)
    t.true(commit == 1);
});

test('exec2()', function * (t) {
  var result = yield exec('ls -alt')

  console.log(result.trim().match(/(gitignore)/))

  t.true(result.trim().match(/(gitignore)/).length > 1);
  t.regex(result, /(gitignore)/);
});

还有一个断言t.regex,不过不太容易判断

Async/await支持

AVA comes with built-in support for async functions (async/await).

test(async function (t) {
    const value = await promiseFn();
    t.true(value);
});

// async arrow function
test(async t => {
    const value = await promiseFn();
    t.true(value);
});

db

每次连接数据库成功后,最好是dropDatabase

var mongoose = require("mongoose");

// 核心代码,是否开启测试
mongoose.set('debug', false);

var db = mongoose.connect("mongodb://127.0.0.1:27017/db_helloworld"); 

db.connection.on("error", function (error) {  
  console.log("数据库连接失败:" + error); 
}); 

db.connection.on("open", function () {  
  console.log("数据库连接成功");
  mongoose.connection.db.dropDatabase();
});

测试覆盖率

https://github.com/bcoe/nyc

Just install both:

$ npm install --save-dev nyc ava

They you can add this to package.json:

"scripts": {
  "test": "nyc ava"
}

集成其他badge也很简单,看它的文档即可

使用ava的开源项目推荐

找这类的项目最好是从ava开始,找贡献的相关作者,从这些作者的项目里找,基本上是十有八九。

文档地址

Screen Shot 2016-05-26 at 9.10.10 AM.png

欢迎反馈,pr、star

全文完

© 著作权归作者所有

i5ting
粉丝 196
博文 68
码字总数 98509
作品 3
东城
私信 提问
基于 Babel 的 npm 包的最小化设置

翻译:疯狂的技术宅 原文:http://2ality.com/2017/07/npm-packages-via-babel.html 本文描述了通过 Babel 生成 npm 包的最小设置。你可以在 GitHub 中看到案例 的设置。 GitHub:https://g...

疯狂的技术宅
03/06
0
0
三个分享——异步流程控制 / Modern Node.js/Java项目如何与Node.js共存

分享1《深入浅出js(Node.js)异步流程控制》 StuQ分享专题《深入浅出js(Node.js)异步流程控制》 InfoQ 前端之巅分享 精简版 摘要 目前在js流程控制领域越来越乱,各种派系。。。比如promi...

i5ting
2016/07/18
1K
6
全面认识 Node.js

1. 了解 Node.js 从 Java 开发人员的视角了解什么是 Node.js(什么不是 Node.js),以及其工作原理和益处。然后,看看使用 Node 开发的 Web 应用程序是什么样的。 阅读: 面向 Java 开发人员的...

IBMdW
2012/09/17
2.6K
1
Node.js最新Web技术栈(2016年4月)

Node.js最新Web技术栈(2016年4月) 上一次的发布的是精华 Node.js最新Web技术栈(2015年5月),感谢大家喜爱,值此koa2.0发布后,决定再次升级技术栈 Node.js是比较简单的,只有你有前端js基...

i5ting
2016/04/01
6K
10
甲骨文发布新版MySQL Cluster 7.3

  【IT168 资讯】甲骨文近日宣布推出MySQL Cluster 7.3 GA版。MySQL开发副总裁Tomas Ulin 表示:“最新MySQL Cluster 7.3 GA版融合了网络、移动和新兴应用工作量所需的灵活性、性能和扩展性...

it168网站
2013/06/21
0
0

没有更多内容

加载失败,请刷新页面

加载更多

计算机实现原理专题--二进制减法器(二)

在计算机实现原理专题--二进制减法器(一)中说明了基本原理,现准备说明如何来实现。 首先第一步255-b运算相当于对b进行按位取反,因此可将8个非门组成如下图的形式: 由于每次做减法时,我...

FAT_mt
昨天
6
0
好程序员大数据学习路线分享函数+map映射+元祖

好程序员大数据学习路线分享函数+map映射+元祖,大数据各个平台上的语言实现 hadoop 由java实现,2003年至今,三大块:数据处理,数据存储,数据计算 存储: hbase --> 数据成表 处理: hive --> 数...

好程序员官方
昨天
7
0
tabel 中含有复选框的列 数据理解

1、el-ui中实现某一列为复选框 实现多选非常简单: 手动添加一个el-table-column,设type属性为selction即可; 2、@selection-change事件:选项发生勾选状态变化时触发该事件 <el-table @sel...

everthing
昨天
6
0
【技术分享】TestFlight测试的流程文档

上架基本需求资料 1、苹果开发者账号(如还没账号先申请-苹果开发者账号申请教程) 2、开发好的APP 通过本篇教程,可以学习到ios证书申请和打包ipa上传到appstoreconnect.apple.com进行TestF...

qtb999
昨天
10
0
再见 Spring Boot 1.X,Spring Boot 2.X 走向舞台中心

2019年8月6日,Spring 官方在其博客宣布,Spring Boot 1.x 停止维护,Spring Boot 1.x 生命周期正式结束。 其实早在2018年7月30号,Spring 官方就已经在博客进行过预告,Spring Boot 1.X 将维...

Java技术剑
昨天
18
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部