概述

  • 为什么开发npm包?
  • 如何开发?
  • 如何写单元测试?
  • package.json
  • 如何发布模块?
  • 如何使用?

为什么开发npm模块?

NPM的全称是Node Package Manager,是一个NodeJS包管理和分发工具,已经成为了非官方的发布Node模块(包)的标准。

npm官网

如何开发?

接下来由带领大家完成一个简单的npm包,功能:读写文件

是不是很复杂呢???

npm init

创建基础目录或文件

  • mkdir tests lib
  • touch index.js README.md
.
├── README.md //说明文档
├── index.js //主入口
├── lib //功能文件
├── package.json //包信息
└── tests //测试用例

开发功能

  • cd lib/
  • touch file.js utils.js

utils.js文件内容

var Promise = require("es6-promise").Promise;

/**
* 提供各种工具方法
* @type {{*}}
*/
module.exports = {
/**
* 获取Defer对象
* @return {[type]} [description]
*/
getDefer: function (){
var deferred = {};
deferred.promise = new Promise(function(resolve, reject){
deferred.resolve = resolve;
deferred.reject = reject;
});
return deferred;
},
/**
* promise when方法
* @param promises promise数组
* @returns {[type]} [description]
*/
when: function(promises) {
var deffered = this.getDefer();
Promise.all(promises).then(function(data) {
deffered.resolve(data);
}, function(err) {
deffered.reject(err);
});
return deffered.promise;
}
}

注:npm install es6-promise --save --verbos

file.js内容

var fs = require('fs');
var path = require('path');
var utils = require('./utils.js'); module.exports = {
/**
* 写文件
* @param file 文件路径
* @param data 数据
*/
writeFile: function(file, data) {
var deferred = utils.getDefer();
file = path.resolve(file); fs.writeFile(file, data, 'utf-8', function(err) {
if(err){
deferred.reject(err);
}else {
deferred.resolve(true);
}
});
return deferred.promise;
},
/**
* 读文件
* @param file 文件路径
*/
readFile: function(file) {
var deferred = utils.getDefer();
file = path.resolve(file); fs.readFile(file, 'utf-8', function(err, data) {
if(err){
deferred.reject(err);
}else {
deferred.resolve(data);
}
});
return deferred.promise;
}
};

主函数index.js内容

var file = require('./lib/file.js');

module.exports = {
writeFile: file.writeFile,
readFile: file.readFile
}

注:主要是在被使用时暴露的接口

功能开发基本完毕

此时我们并不知道我们实现的功能是否可行、可用

我们需要进行单元测试

如何写单元测试?

单元测试原则

  • 对全新的代码或修改过的代码进行单元测试
  • 单元测试根据单元测试计划和方案进行,排除测试的随意性
  • 必须保证单元测试计划、单元测试方案、单元测试用例等经过评婶
  • 当测试用例的测试结果与预期结果不一致时,单元测试的执行人员需如实记录实际的测试结果
  • 只有当测试计划中的结束标准达到时,单元测试才能结束
  • 对被测试单元需达到的一定的代码覆盖率要求

书写测试用例

前提条件

测试库mocha  教程

npm install -g mocha --verbos
npm install --save-dev chai --verbos

测试utils.js

var utils = require('../lib/utils.js');
var expect = require('chai').expect; describe('utils:工具方法测试', function() {
//defer对象测试
describe('utils.getDefer', function() {
var deferred = utils.getDefer(); it('defer成功', function() {
deferred.resolve(true);
return deferred.promise.then(function(data) {
expect(data).to.be.equal(true);
});
}); it('defer失败', function() {
deferred.reject(true);
return deferred.promise.then(function() {}, function(data) {
expect(data).to.be.equal(true);
});
});
});
//when测试
describe('utils.when', function() {
var deferred1 = utils.getDefer();
var deferred2 = utils.getDefer();
var deferred3 = utils.getDefer();
var deferred4 = utils.getDefer(); it('when成功', function() {
deferred1.resolve(true);
deferred2.resolve(true);
return utils.when([deferred1.promise, deferred2.promise]).then(function(data) {
expect(data).to.be.deep.equal([true, true]);
});
}); it('when失败', function() {
deferred3.resolve(true);
deferred4.reject(false);
return utils.when([deferred3.promise, deferred4.promise]).then(function() {},function(data) {
expect(data).to.be.equal(false);
});
});
});
});

注:mocha tests/utils.js

测试file.js

var file = require('../lib/file.js');
var expect = require('chai').expect; describe('file:功能测试', function() { //writeFile功能测试
describe('file.writeFile', function() { it('写文件:成功', function() {
var path = 'README.md';
var data = '说明文档';
return file.writeFile(path, data).then(function(flag) {
expect(flag).to.be.equal(true);
});
}); it('写文件:失败', function() {
var path = 'write-test.txt';
var data = '我是写入的数据';
return file.writeFile(path, data).then(function(){}, function(err) {
expect(true).to.be.equal(true);
});
});
}); //readFile功能测试
describe('file.readFile功能测试', function() { it('读文件:成功', function() {
var path = 'README.md';
return file.readFile(path).then(function(data) {
expect(data).to.be.equal('说明文档');
});
}); it('读文件:失败', function() {
var path = 'write-test.txt';
return file.readFile(path).then(function(){}, function(err) {
expect(true).to.be.equal(true);
});
});
});
});

注:mocha tests/file.js

持续测试...

一遍遍测试,查看测试结果,都要输入命令很无语~~

新技能:mocha --watch tests

还能做什么?

通过上面测试感觉好了不少,有没有更好的展现形式呢?

  • 测试结果生成html报表(mocha --reporter mochawesome tests)
  • 能不能看看测试覆盖率呢?(istanbul cover ./node_modules/mocha/bin/_mocha -- -t 2000 --recursive -R spec tests/)

注:

npm install --save-dev mochawesome --verbos

npm install --save-dev mocha --verbos

sudo npm install -g istanbul --verbos

package.json

经过上述操作之后我们发现,package.json发生了变化

{
"name": "read-write-file",
"version": "1.0.0",
"description": "简单的读写文件",
"main": "index.js",
"scripts": {
"test": "mocha --reporter spec --timeout 2000 --recursive tests/"
},
"keywords": [
"read",
"write"
],
"author": "黑MAO",
"license": "MIT",
"dependencies": {
"es6-promise": "^3.0.2"
},
"devDependencies": {
"chai": "^3.4.1",
"istanbul": "^0.4.1",
"mocha": "^2.3.4",
"mochawesome": "^1.2.1"
}
}

回顾

发现不爽的地方,要执行一对命令,还有一些参数特别长,不容易记忆

该怎么办呢?

scripts脚本

npm 提供简单的执行脚本,可以通过npm run * 执行scripts写的简单脚本

于是乎~~

常用脚本

    "scripts": {
"watch": "mocha --watch tests/",
"test": "mocha --reporter spec --timeout 2000 --recursive tests/",
"test-cov": "istanbul cover ./node_modules/mocha/bin/_mocha -- -t 2000 --recursive -R spec tests/",
"test-html": "mocha --reporter mochawesome tests/"
},

命令行

命令行模式又是怎么做的呢?

    "bin": {
"writeFile": "./bin/writeFile.js",
"readFile": "./bin/readFile.js"
},

注:

开发模式可以使用:

sudo npm link(添加命令行模式)

sudo npm unlink(取消命令行模式)


截至现在,我们的一个npm包就开发完成了~

是不是也没有想想中那么复杂呢?

如何发布?

  • npm adduser(用户名、密码、邮箱)-- 注册帐号
  • npm whoami(查看当前帐号)
  • sudo npm publish(发布到npmjs.org)-- 注意:sudo权限

如何使用?

npm install read-write-file

var file = require('read-write-file');

var path = 'test.txt';
var data = '我是测试文本'; file.writeFile(path, data).then(function() {
return file.readFile(path);
}).then(function(txt) {
console.log('测试结果:'+txt);
});

注:sudo install -g read-write-file可以使用命令行形式

到目前为止,一个npm包就开发完成了~

参考资料:

最新文章

  1. 机器学习caffe环境搭建——redhat7.1和caffe的python接口编译
  2. 验证mongodb副本集并实现自动切换primary~记录过程
  3. 通过跳板机建立信任,对多个tomcat服务统一安装部署(shell编写)
  4. mysql数据库默认存放位置修改
  5. const 和宏的区别
  6. Thinking in Java——笔记(8)
  7. C#限制程序只能运行一個实例 (防多开)
  8. Windows Server 2008 R2 配置Exchange 2010邮件服务器
  9. CMS垃圾回收与G1垃圾回收
  10. Linux进程笔记
  11. SQL Server 823,824 错误
  12. Javascipt数组去重的几种方式
  13. php编程 之 php基础一
  14. JDBC的使用和SQL注入问题
  15. Linux下的Mongodb部署应用梳理
  16. adb调试android设备 说的比较清楚的一篇文章
  17. source insight之quicker.em宏的使用
  18. Python自动化面试必备 之 你真明白装饰器么?
  19. [C++基础] tips
  20. poj 1422 Air Raid (二分匹配)

热门文章

  1. [Angular 2] A Simple Form in Angular 2
  2. JuiceSSh破解分析
  3. sae storage 使用uploadify插件进行文件批量上传
  4. 【移动开发】Android中WIFI开发总结(二)
  5. ASP.NET-FineUI开发实践-1
  6. 请帮我看看这个页面,红色部份如何改才能保存到ACCess数据库中
  7. innodb的innodb_buffer_pool_size和MyISAM的key_buffer_size
  8. (转)linux下导入、导出mysql数据库命令
  9. starting Intent from ProcessRecord with revoked permission android.permission.CALL_PHONE 的错误
  10. Jenkins学习之——(4)Email Extension Plugin插件的配置与使用