测试

目前主流的就bdd和tdd,自己查一下差异

推荐

  • mocha和tape

另外Jasmine也挺有名,angularjs用它,不过挺麻烦的,还有一个选择是qunit,最初是为jquery测试写的,在nodejs里用还是觉得怪怪的。

如果想简单可以tap,它和tape很像,下文会有详细说明

mocha

mocha是tj写的

https://github.com/mochajs/mocha

varassert=require("assert")
describe('truth',function(){
it('should find the truth',function(){assert.equal(1,1);})})

断言风格,这里默认是assert,推荐使用chaijs这个模块,它提供3种风格

  • Should
  • Expect
  • Assert

rspec里推荐用expect,其实看个人习惯

比较典型一个mocha例子

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

describe('Test',function(){
before(function(){// runs before all tests in this block})
after(function(){// runs after all tests in this block})
beforeEach(function(){// runs before each test in this block})
afterEach(function(){// runs after each test in this block}) describe('#test()',function(){
it('should return ok when test finished',function(done){assert.equal('sang_test2','sang_test2');var foo ='bar';
expect(foo).to.equal('bar');done()})})})

说明

  • 理解测试生命周期
  • 理解bdd测试写法

单元测试需要的各个模块说明

  • mocha(Mocha is a feature-rich JavaScript test framework running on node.js and the browser, making asynchronous testing simple and fun.)
  • chai(Chai is a BDD / TDD assertion library for node and the browser that can be delightfully paired with any javascript testing framework.)
  • sinon(Standalone test spies, stubs and mocks for JavaScript.)
  • zombie (页面事件模拟Zombie.js is a lightweight framework for testing client-side JavaScript code in a simulated environment. No browser required.)
  • supertest(接口测试 Super-agent driven library for testing node.js HTTP servers using a fluent API)

更多的看 http://nodeonly.com/2014/11/24/mongoose-test.html

如果你想真正的玩敏捷,从用户故事开始,那么下面这2个库非常必要

啊,黄瓜。。。。

tape:像代码一样跑测试

tape是substack写的测试框架

https://github.com/substack/tape

var test =require('tape').test;
test('equivalence',function(t){
t.equal(1,1,'these two numbers are equal');
t.end();});

tape是非常简单的测试框架,核心价值观是”Tests are code”,所以你可以像代码一样跑测试,

比如

node test/test.js

写个脚本就无比简单了。当然如果你想加’test runner’ 库也有现成的。

The Test Anything Protocol

TAP全称是Test Anything Protocol

它是可靠性测试的一种(tried & true)实现

从1987就有了,有很多语言都实现了。

它说白点就是用贼简单的方式来格式化测试结果,比如

TAP version 13# equivalence
ok 1 these two numbers are equal 1..1# tests 1# pass 1# ok

比如node里的实现https://github.com/isaacs/node-tap

var tap =require('tap')// you can test stuff just using the top level object.// no suites or subtests required.

tap.equal(1,1,'check if numbers still work')
tap.notEqual(1,2,'1 should not equal 2')// also you can group things into sub-tests.// Sub-tests will be run in sequential order always,// so they're great for async things. tap.test('first stuff',function(t){
t.ok(true,'true is ok')
t.similar({a:[1,2,3]},{a:[1,2,3]})// call t.end() when you're done
t.end()})

一定要区分tap和tape,不要弄混了

科普一下什么是CI

科普一下,CI = Continuous integration 持续集成

Martin Fowler对持续集成是这样定义的:

持续集成是一种软件开发实践,即团队开发成员经常集成他们的工作,通常每个成员每天至少集成一次,也就意味着每天可能会发生多次集成。每次集成都通过自动化的构建(包括编译,发布,自动化测试)来验证,从而尽快地发现集成错误。许多团队发现这个过程可以大大减少集成的问题,让团队能够更快的开发内聚的软件。

它可以

  • 减少风险
  • 减少重复过程
  • 任何时间、任何地点生成可部署的软件
  • 增强项目的可见性
  • 建立团队对开发产品的信心

要素

1.统一的代码库 2.自动构建 3.自动测试 4.每个人每天都要向代码库主干提交代码 5.每次代码递交后都会在持续集成服务器上触发一次构建 6.保证快速构建 7.模拟生产环境的自动测试 8.每个人都可以很容易的获取最新可执行的应用程序 9.每个人都清楚正在发生的状况 10.自动化的部署

也就是说,测试不通过不能部署,只有提交到服务器上,就可以自动跑测试,测试通过后,就可以部署到服务器上了(注意是"staging", 而非"production")。

一般最常的ci软件是jenkins

举个大家熟悉的例子iojs开发中的持续集成就是用的jenkins

https://jenkins-iojs.nodesource.com/

jenkins是自建环境下用的比较多,如果是开源项目,推荐travis-ci

https://travis-ci.org/

对开源项目做持续集成是免费的(非开源的好贵),所以在github集成的基本是最多的。

对nodejs支持的也非常好。

举2个例子

测试报告

近年随着tdd/bdd,开源项目,和敏捷开发的火热,程序员们不再满足说,我贡献了一个开源项目

要有高要求,我要加测试

要有更高要求,我要把每一个函数都测试到,让别人相信我的代码没有任何问题

上一小节讲的ci,实际上解决了反复测试的自动化问题。但是如何看我的程序里的每一个函数都测试了呢?

答案是测试覆盖率

在nodejs里,推荐istanbul

Istanbul - 官方介绍 a JS code coverage tool written in JS

它可以通过3种途径生成覆盖报告

  • cli
  • 代码
  • gulp插件

安装

$ npm install -g istanbul

执行

$ istanbul cover my-test-script.js --my test args

它会生成./coverage目录,这里面就是测试报告

比如我的项目里

./node_modules/.bin/istanbul cover ./node_modules/mocha/bin/_mocha --report lcovonly
#MongooseDao()✓ should return ok when record create
✓ should return ok when record delete fixture-user
✓ should return ok when record deleteById
✓ should return ok when record removeById
✓ should return ok when record getById
✓ should return ok when record getAll
✓ should return ok when record all
✓ should return ok when record query 8 passing (50ms)=============================================================================Writing coverage object[/Users/sang/workspace/moa/mongoosedao/coverage/coverage.json]Writing coverage reports at [/Users/sang/workspace/moa/mongoosedao/coverage]============================================================================================================Coverage summary ===============================Statements:47.27%(26/55)Branches:8.33%(1/12)Functions:60%(9/15)Lines:47.27%(26/55)================================================================================

默认,它会生成coverage.json和Icov.info,如果你想生成html也可以的。

比如说,上面的结果47.27%是我测试覆盖的占比,即55个函数,我的测试里只覆盖了26个。

那么我需要有地方能够展示出来啊

实践

我们以mongoosedao项目为例,介绍一下如何集成测试,ci和测试覆盖率

最终效果如图

npm run

package.json里定义自定义执行脚本

"scripts":{"start":"npm publish .","test":"./node_modules/.bin/gulp","mocha":"./node_modules/.bin/mocha -u bdd","cov":"./node_modules/.bin/istanbul cover ./node_modules/mocha/bin/_mocha --report lcovonly -- -R spec && cat ./coverage/lcov.info | ./node_modules/coveralls/bin/coveralls.js && rm -rf ./coverage"},

除了start和test外,都是自定义任务,其他都要加run命令

npm run mocha
npm run cov

更多见npm-run-test教程

gulp watch

var gulp =require('gulp');var watch =require('gulp-watch');var path ='test/**/*.js';

gulp.task('watch',function(){
gulp.watch(['test/**/*.js','lib/*.js'],['mocha']);});var mocha =require('gulp-mocha'); gulp.task('mocha',function(){return gulp.src(path ,{read:false})// gulp-mocha needs filepaths so you can't have any plugins before it .pipe(mocha({reporter:'spec'}));}); gulp.task('default',['mocha','watch']);

这样就可以执行gulp的时候,当文件变动,会自动触发mocha测试,简化每次都输入npm test这样的操作。

当然你可以玩更多的gulp,如果不熟悉,参考

创建.travis.yml

项目根目录下,和package.json平级

language: node_js
repo_token: COVERALLS.IO_TOKEN
services: mongodb
node_js:-"0.12"-"0.11"-"0.10"
script: npm run mocha
after_script:
npm run cov

说明

  • 如果依赖mongo等数据库,一定要写services
  • 把测试覆盖率放到执行测试之后,避免报402错误

在travis-ci.org上,github授权,添加repo都比较简单

添加之后,就可以看到,比如

https://travis-ci.org/moajs/mongoosedao

travis-ci实际上根据github的代码变动进行自动持续构建,但是有的时候它不一定更新,或者说,你需要手动选一下:

点击# 10 passed,这样就可以强制它手动集成了。

其他都很简单,注意替换COVERALLS.IO_TOKEN即可。

创建 .coveralls.yml

https://coveralls.io/是一个代码测试覆盖率的网站,

nodejs下面的代码测试覆盖率,原理是通过istanbul生成测试数据,上传到coveralls网站上,然后以badge的形式展示出来

比如

具体实践和travis-ci类似,用github账号登陆,然后添加repo,然后在项目根目录下,和package.json平级,增加.coveralls.yml

service_name: travis-pro
repo_token:99UNur6O7ksBqiwgg1NG1sSFhmu78A0t7

在上,第一次添加repo,显示的是“SET UP COVERALLS”,里面有token,需要放到.coveralls.yml里,

如果成功提交了,就可以看到数据了

在readme.md里增加badge

[![BuildStatus](https://travis-ci.org/moajs/mongoosedao.png?branch=master)](https://travis-ci.org/moajs/mongoosedao)[![CoverageStatus](https://coveralls.io/repos/moajs/mongoosedao/badge.png)](https://coveralls.io/r/moajs/mongoosedao)

它就会显示如下

另外一种用Makefile的玩法实践

举例:https://github.com/node-webot/wechat-api/blob/master/Makefile

TESTS = test/*.js
REPORTER = spec
TIMEOUT = 20000
ISTANBUL = ./node_modules/.bin/istanbul
MOCHA = ./node_modules/mocha/bin/_mocha
COVERALLS = ./node_modules/coveralls/bin/coveralls.js test:
@NODE_ENV=test $(MOCHA) -R $(REPORTER) -t $(TIMEOUT) \
$(MOCHA_OPTS) \
$(TESTS) test-cov:
@$(ISTANBUL) cover --report html $(MOCHA) -- -t $(TIMEOUT) -R spec $(TESTS) test-coveralls:
@$(ISTANBUL) cover --report lcovonly $(MOCHA) -- -t $(TIMEOUT) -R spec $(TESTS)
@echo TRAVIS_JOB_ID $(TRAVIS_JOB_ID)
@cat ./coverage/lcov.info | $(COVERALLS) && rm -rf ./coverage test-all: test test-coveralls .PHONY: test

我个人更喜欢npm+gulp的写法,总是有一种make是c里古老的东东。。。

总结

本文讲了

  • nodejs里常用框架

    • mocha
    • tape
    • tap
    • 前沿技术:cucumber和vowsjs
  • 科普一下CI
  • 测试报告
    • istanbul
  • 实践
    • gulp + npm run
    • mocha
    • travis-ci
    • coveralls
  • 介绍了基于makefile的另一种玩法

全文完

Nodejs开源项目里怎么样写测试、CI和代码测试覆盖率的更多相关文章

  1. node.js 开发桌面程序, 10个令人惊讶的NodeJS开源项目

    用 node-webkit 开源框架. 做企业站,杠杠地 包括电子书和支付宝系统都是node开发的,. 接收传感器发送的数据再运算...对水泵.风机.空调这些硬件进行远程控制. 细数10个令人惊讶的N ...

  2. Nodejs开源项目推荐

    当我们学习一门新语言,不要用以前语言的习惯去使用新的语言,这样可能会导致走一些弯路.最好的办法就是去看一些写的比较好的开源项目,所以这里我推荐几个NodeJs的开源项目,花点时间去研究一下他们的实现, ...

  3. Selenium自动化:有代码测试与无代码测试。这些你都懂了吗?

    大多数测试人员认为 Selenium是满足其测试自动化需求的自动化框架.作为全球测试人员使用的开放源框架, Selenium 无疑是测试人员适应日趋敏捷的公司的一种好方法.实际上, Selenium仍 ...

  4. NodeJS无所不能:细数10个令人惊讶的NodeJS开源项目

    在几年的时间里,NodeJS逐渐发展成一个成熟的开发平台,吸引了许多开发者.有许多大型高流量网站都采用NodeJS进行开发,像PayPal,此外,开发人员还可以使用它来开发一些快速移动Web框架. 除 ...

  5. [转载] NodeJS无所不能:细数十个令人惊讶的NodeJS开源项目

    转载自http://www.searchsoa.com.cn/showcontent_79099.htm 在几年的时间里,Node.JS逐渐发展成一个成熟的开发平台,吸引了许多开发者.有许多大型高流量 ...

  6. 在zxing开源项目里,camera.setDisplayOrientation(90)出现错误

    [错误提示]  setDisplayOrientation(int)未定义 [错误原因]  sdk版本过低,这个方法在Android2.2之后才有 [解决方法]  直接在project.propert ...

  7. 第一个Asp.net小项目,主页写了下后台代码

    一个比较完善的登录模块,就目前的知识范围来说应该算是完美的. 涉及到:cookies,Session,验证码等知识面 Cookies存放一组值: HttpCookie cook = new HttpC ...

  8. Excel操作类库最常用到的4种开源项目与MS Excel类库写操作对比分析性能

    4种开源Excel读写类库与MS Excel类库写操作对比 软件开发过程中,经常需要将数据保存为.xls或.xlsx文件.之前发现微软提供的Microsoft.Office.Interop.Excel ...

  9. 如何参与开源项目 - 细说 GitHub 上的 PR 全过程

    目录 一.概述 二.为什么要参与开源项目 三.为什么我想介绍如何 PR 四.我想参与开源项目,怎么开始? 4.1.寻找一个合适的开源项目 4.2.寻找贡献点 五.我要提交 PR,怎么上手? 5.1.第 ...

随机推荐

  1. Mongodb 抛出异常:dbexit: really exiting now

    删除 数据库文件夹下,的 _tmp 和 mongodb.lock 文件 , 重启即可.我的数据文件在  /data/mongo/data/  下

  2. 不安装oracle客户端,如何运行sqlplus

    1.软件下载 http://www.oracle.com/technetwork/topics/linuxx86-64soft-092277.html 下载如下三个包: oracle-instantc ...

  3. CSS BFC(Block Formatting Context)

    BFC是 W3C CSS 2.1 规范中的一个概念Block Formatting Context的缩写即格式化上下文,它决定了元素如何对其内容进行定位,以及与其他元素的关系和相互作用.简单讲,它是提 ...

  4. java类的初始化

    转载:http://blog.csdn.net/moreevan/article/details/6968718 我们知道一个类(class)要被使用必须经过装载,连接,初始化这样的过程.下面先对这三 ...

  5. gets()

    C: #include <stdio.h>    //这个头文件包含gets()函数,这个函数在ISO/IEC 9899 2011(C11)标准中被移除 int main(void) { ...

  6. hdu_2665_Kth number(主席树)

    题目连接:http://acm.hdu.edu.cn/showproblem.php?pid=2665 题意:给你一个区间,让你找这个区间第K大的数 题解:主席树模版题,也可以用划分树 #includ ...

  7. hdu 1166 敌兵布阵(线段树详解)

    Problem Description C国的死对头A国这段时间正在进行军事演习,所以C国间谍头子Derek和他手下Tidy又开始忙乎了.A国在海岸线沿直线布置了N个工兵营地,Derek和Tidy的任 ...

  8. 第13章 Swing程序设计----JDialog窗体

    JDialog窗体是Swing组件中的对话框 JDialog窗体的功能是从一个窗体中弹出另一个窗体,就像是在使用IE浏览器时弹出的确定对话框一样. 在应用程序中创建JDialog窗体需要实例化JDia ...

  9. ip forward

    centos vi /proc/sys/net/ipv4/ip_forward ubuntu vi /etc/sysctl.conf sysctl -p

  10. KMP算法中的next数组求解示意图