我们为了做黑盒测试经常会需要做一些数据来模拟输入,NodeJS有丰富的第三方模块可以实现类似的功能。模拟输入可以用Sinon,它可以模拟包括ajax调用的各类程序调用来进行测试。但本文着重介绍的是如何做数据,也就是用Faker.js来生成软件测试时所需要的各式各样的数据。
### Installation
$ git clone https://github.com/Marak/Faker.js.git
$ cd Faker.js/
$ npm install
### Faker.js 的基本目录结构
.
├── BUILD // 用于自动生成文档,一般可无视
├── examples/ // Examples 目录
├── Faker.js // Faker.js 主文件
├── index.js // 入口文件
├── lib
│ ├── address.js // 用于生成地址
│ ├── company.js // 用于生成公司信息
│ ├── definitions.js // 信息生成来源的定义文件
│ ├── helpers.js // 一些在Faker数据时常用的函数
│ ├── internet.js // 用于生成Internet相关信息
│ ├── lorem.js // 用于生成随机文本
│ ├── name.js // 用于生成人名
│ ├── phone_number.js // 用于生成电话号码
│ ├── random.js // 随机实现,包括随机函数,正态分布函数等
│ └── version.js // 空文件,可用于生成版本信息
├── logo.png
├── Makefile
├── MinFaker.js // Lite版Faker,已包含了lib里的功能,最小化最基本的Faker实现。
├── MIT-LICENSE.txt
├── package.json
├── Readme.md
└── test // 单元测试代码文件夹
├── address.unit.js
├── all.functional.js // 测试Faker.js 功能是否正常
├── browser.unit.html
├── company.unit.js
├── helpers.unit.js
├── internet.unit.js
├── lorem.unit.js
├── mocha.opt // Mocha 配置
├── name.unit.js
├── phone_number.unit.js
├── run.js // test 主文件
└── support
├── chai.js
├── sinon-1.5.2.js
└── walk_dir.js
### Faker.js API使用 那么Faker.js怎么用呢?我们在其github的README里看到,可以调用API。比如 Faker.Internet.email() 就可以随机生成一个合法的email。调用API谁都会,只要参照我上面目录结构lib下js文件里的源码,用jsdoc把结构导出来阅读函数接口就好了。
var Faker = require('./Faker');
var randomName = Faker.Name.findName(); // Rowan Nikolaus
var randomEmail = Faker.Internet.email(); // Kassandra.Haley[@erich](/user/erich).biz
var randomCard = Faker.Helpers.createCard(); // random contact card containing many properties
Browser里理所当然也可以类似的使用,只不过require改成用script标签引入,此处不赘述。
### Faker.js 源码自定义 但是我们知道,现实生活中的输入数据形式是多种多样的,就比如这个是英语国家程序员开发的Faker,他很难去考虑到中文人名,日文人名,中文文本等这些因素。如果真的只能调用API,Faker就会具有极大的局限性。
实际上,作者Marak实际也不打算去考虑别的国家的习惯,源码是开放的,你完全可以通过修改lib里的代码来实现自己的特殊目的。
举例如下:
/**
* [[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[@author](/user/author)](/user/author)](/user/author)](/user/author)](/user/author)](/user/author)](/user/author)](/user/author)](/user/author)](/user/author)](/user/author)](/user/author)](/user/author)](/user/author)](/user/author)](/user/author)](/user/author)](/user/author)](/user/author)](/user/author)](/user/author)](/user/author)](/user/author)](/user/author)](/user/author)](/user/author)](/user/author)](/user/author)](/user/author)](/user/author)](/user/author)](/user/author)](/user/author)](/user/author)](/user/author)](/user/author)](/user/author)](/user/author)](/user/author)](/user/author)](/user/author)](/user/author)](/user/author)](/user/author)](/user/author)](/user/author)](/user/author)](/user/author)](/user/author)](/user/author)](/user/author): Marak
* [[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[@file](/user/file)](/user/file)](/user/file)](/user/file)](/user/file)](/user/file)](/user/file)](/user/file)](/user/file)](/user/file)](/user/file)](/user/file)](/user/file)](/user/file)](/user/file)](/user/file)](/user/file)](/user/file)](/user/file)](/user/file)](/user/file)](/user/file)](/user/file)](/user/file)](/user/file)](/user/file)](/user/file)](/user/file)](/user/file)](/user/file)](/user/file)](/user/file)](/user/file)](/user/file)](/user/file)](/user/file)](/user/file)](/user/file)](/user/file)](/user/file)](/user/file)](/user/file)](/user/file)](/user/file)](/user/file)](/user/file)](/user/file)](/user/file)](/user/file)](/user/file)](/user/file)](/user/file)](/user/file)](/user/file)](/user/file): lib/phone_number.js
*/
var phone = {
phoneNumber: function () {
return Helpers.replaceSymbolWithNumber(Faker.random.phone_formats());
},
// FIXME: this is strange passing in an array index.
phoneNumberFormat: function (phoneFormatsArrayIndex) {
return Helpers.replaceSymbolWithNumber(definitions.phone_formats[phoneFormatsArrayIndex]);
}
};
你可以按照需要修改函数或者添加函数:
/**
* [[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[@author](/user/author)](/user/author)](/user/author)](/user/author)](/user/author)](/user/author)](/user/author)](/user/author)](/user/author)](/user/author)](/user/author)](/user/author)](/user/author)](/user/author)](/user/author)](/user/author)](/user/author)](/user/author)](/user/author)](/user/author)](/user/author)](/user/author)](/user/author)](/user/author)](/user/author)](/user/author)](/user/author)](/user/author)](/user/author)](/user/author)](/user/author)](/user/author)](/user/author)](/user/author)](/user/author)](/user/author)](/user/author)](/user/author)](/user/author)](/user/author)](/user/author)](/user/author)](/user/author)](/user/author)](/user/author)](/user/author)](/user/author)](/user/author)](/user/author)](/user/author)](/user/author): Marak
* [[[[[[[[[[[[[[[[[[[[[[[[[[[[@modifier](/user/modifier)](/user/modifier)](/user/modifier)](/user/modifier)](/user/modifier)](/user/modifier)](/user/modifier)](/user/modifier)](/user/modifier)](/user/modifier)](/user/modifier)](/user/modifier)](/user/modifier)](/user/modifier)](/user/modifier)](/user/modifier)](/user/modifier)](/user/modifier)](/user/modifier)](/user/modifier)](/user/modifier)](/user/modifier)](/user/modifier)](/user/modifier)](/user/modifier)](/user/modifier)](/user/modifier)](/user/modifier): Lhfcws
* [[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[@file](/user/file)](/user/file)](/user/file)](/user/file)](/user/file)](/user/file)](/user/file)](/user/file)](/user/file)](/user/file)](/user/file)](/user/file)](/user/file)](/user/file)](/user/file)](/user/file)](/user/file)](/user/file)](/user/file)](/user/file)](/user/file)](/user/file)](/user/file)](/user/file)](/user/file)](/user/file)](/user/file)](/user/file)](/user/file)](/user/file)](/user/file)](/user/file)](/user/file)](/user/file)](/user/file)](/user/file)](/user/file)](/user/file)](/user/file)](/user/file)](/user/file)](/user/file)](/user/file)](/user/file)](/user/file)](/user/file)](/user/file)](/user/file)](/user/file)](/user/file)](/user/file)](/user/file)](/user/file)](/user/file)](/user/file): lib/phone_number.js
*/
var phone = {
phoneNumber: function () {
// return Helpers.replaceSymbolWithNumber(Faker.random.phone_formats());
return Helpers.replaceSymbolWithNumber('13#########');
},
// FIXME: this is strange passing in an array index.
phoneNumberFormat: function (phoneFormatsArrayIndex) {
return Helpers.replaceSymbolWithNumber(definitions.phone_formats[phoneFormatsArrayIndex]);
},
// Just a demo, added by Lhfcws
teleNumber: function () {
return Helpers.replaceSymbolWithNumber('020-########');
}
};
### Faker.js 源码测试 在目录结构中我们见到test/ 里的代码都是单元测试代码,是用来测试Faker.js源码的。而Marak提供的Makefile让你只需要执行 make test 就可以跑一遍mocha的单元测试。
在自定义源码一节前可能还会有人有疑问为什么需要测试Faker.js源码,现在大家应该毫无疑问了。
比如上一节中我们添加的teleNumber 函数,我们可以在test/phone_number.unit.js中添加一个describe。
describe("teleNumber()",function () {
it("return random telephone number with format (020-########)", function () {
var tele_number = Faker.PhoneNumber.teleNumber();
assert.ok(tele_number.match(/020-\d\d\d\d\d\d\d\d/));
})
})
跑一次 make test就可以得到测试结果。
因此当修改了lib下的源码后,对应的也要注意修改test下的测试代码,这样才保证Faker的数据与预期相符。