fanix 2019-06-28
项目地址:https://github.com/wangduandu...
功能强大的REST接口测试工具, Power By Jest, axios, superstruct, mustache, lodash
非常简单
: 大部分工作量在于写配置文件请求模板
: 可以在配置文件中加入运行时变量,如/users/{{id}}
响应体结构验证
: 支持对响应体的字段类型进行严格校验,多字段、少字段、字段类型不符合预期都会报错非常详细的报错提示
: 参见截图yarn add aester npm i aester -S
// filename 必须以 test.js结尾 const Ae = require('aester') var testData = require('./test-data.js') // 初始化配置文件 testData = Ae.init(testData) describe('4XX 5XX error response test', () => { test('Get User Info without sessionId', async () => { await expect(Ae.send(testData.getOneUser, {id: '1'})).rejects.toHaveProperty('status', 403) }) test('loginByEmail Fail Test', async () => { await expect(Ae.send(testData.loginByEmail, {password: '111'})).rejects.toHaveProperty('status', 401) }) }) describe('2XX success response test', () => { test('loginByEmail Success Test', async () => { // 对于符合预期的正向测试,不需要使用expect, 如果响应状态码是400以上,或者响应体结构不符合预期, // 该测试用例会自动失败 const data = await Ae.send(testData.loginByEmail, {password: '000'}) Ae.share('sessionId', data.sessionId) }) test('Get User Info', async () => { await Ae.send(testData.getOneUser, {id: '1'}) }) }) describe('2XX success response with error body struct', () => { test('StructError test', async () => { var data = _.cloneDeep(testData.getOneUser) data.resBodyStruct.test = 'number' // set a error struct await expect(Ae.send(data, {id: '1'})).rejects.toHaveProperty('type', 'StructError') }) })
// test-data.js module.exports = { $baseUrl: 'http://localhost:3000', loginByEmail: { desc: 'login', req: { method: 'post', path: '/login', headers: { 'content-type': 'application/x-www-form-urlencoded' }, data: '[email protected]&password={{password}}', params: { _test: 1 } }, resBodyStruct: { sessionId: 'string' } }, getOneUser: { desc: 'get user info', req: { path: '/users/{{id}}', headers: { 'sessionId': '{{sessionId}}' // 如果share中有sessionId, 在请求发送时,会自动将{{sessionId}}替换成真正的值,否则会被替换成空字符串 } }, resBodyStruct: { id: 'string', email: 'string', password: 'string', userName: 'string', likes: 'array', isAdmin: 'boolean' } }, createOneUser: { desc: 'create user', req: { method: 'post', path: '/users', headers: { 'sessionId': '{{sessionId}}' } } }, updateOneUser: { desc: 'update user', req: { method: 'put', path: '/users/{{id}}', headers: { 'sessionId': '{{sessionId}}' } } }, deleteOneUser: { desc: '获取用户信息接口', req: { method: 'delete', path: '/users/{{id}}', headers: { 'sessionId': '{{sessionId}}' } } } }
在package.json加入
"scripts": { "test": "jest" }
然后运行npm test
yarn add jest-html-reporter -D
然后在package.json中加入如下字段
"test:report": "jest --reporters='jest-html-reporter'"
然后运行
npm run test:report
创建jest.config.js在项目根目录
module.exports = { verbose: true, testEnvironment: 'node', reporters: [ 'default', ['./node_modules/jest-html-reporter', { pageTitle: `operation api test ${process.env.testConfigEnv}`, includeFailureMsg: true // 详细错误提示 }] ] }
然后运行
npm test
PASS test/unit.test.js PASS test/index.test.js Test Suites: 2 passed, 2 total Tests: 8 passed, 8 total Snapshots: 0 total Time: 1.864s
"origin": "null", "readyState": 4, "requestBuffer": null, "requestCache": null, "responseBuffer": [Buffer], "responseCache": null, "responseHeaders": [Object], "responseTextCache": "Forbidden", "responseURL": "http://localhost:3000/users/1", "responseXMLCache": null, "send": true, "status": 403, "statusText": "Forbidden", "timeoutFn": null, "timeoutId": 0, "timeoutStart": 0, "totalReceivedChunkSize": 9, "uploadComplete": true, "uploadListener": false, }, }, "status": 403, "statusText": "Forbidden", } 18 | }) 19 | > 20 | test('Get User Info', async () => { | ^ 21 | await Ae.send(testData.getOneUser, {id: '1'}) 22 | }) 23 | at Env.it (node_modules/jest-jasmine2/build/jasmine_async.js:102:24) at Object.<anonymous> (test/index.test.js:20:1)
例如,resBodyStruct配置sessionId为number格式,但是返回的格式是字符串,将会如下格式的报错
TypeError: Expected a value of type `number` for `sessionId` but received `"123456"`. 60 | if (conf.resBodyStruct) { 61 | let Scheme = struct(conf.resBodyStruct) > 62 | let result = Scheme.validate(res.data) | ^ 63 | if (result.length === 1) { 64 | reject(result[0]) 65 | } at Function.Struct.validate.value [as validate] (node_modules/superstruct/src/superstruct.js:78:17) at src/index.js:62:29
初始化配置文件
const Ae = require('aester') ... var conf = Ae.init(apiConfs)
发送请求。
options会与share合并,然后将对应变量渲染到请求模板中。
const Ae = require('aester') ... Ae.send(testData.getOneUser, {id: '1'}
设置共享变量
const Ae = require('aester') ... var conf = Ae.share('token', '123123')
获取所有共享变量
const Ae = require('aester') ... var conf = Ae.getShare() // {token: '123123'}
key | 必须? | 说明 |
---|---|---|
$baseUrl | 是 | 请求baseUrl |
desc | 否 | 接口说明
req | 是 | 请求对象
req.method | 否 | 请求方法,默认get
req.path | 是 | 请求路径
req.headers | 是 | 默认为空对象,默认设置'content-type': 'application/json; charset=UTF-8'
resBodyStruct | 否 | 响应体格式校验对象
resBodyStruct字段说明
{ key: keyType }
字段类型支持如下
在字段类型后加上?
表示字段是否可选
如:
{ sessionId: 'string?' //sessionId是字符串,但是可以没有这个字段 }
更多字段类型验证参考:https://github.com/ianstormta...
npm test