1. Aest
項(xiàng)目地址:https://github.com/wangduandu...
功能強(qiáng)大的REST接口測(cè)試工具, Power By Jest, axios, superstruct, mustache, lodash
2. 特點(diǎn)非常簡(jiǎn)單: 大部分工作量在于寫(xiě)配置文件
請(qǐng)求模板: 可以在配置文件中加入運(yùn)行時(shí)變量,如/users/{{id}}
響應(yīng)體結(jié)構(gòu)驗(yàn)證: 支持對(duì)響應(yīng)體的字段類(lèi)型進(jìn)行嚴(yán)格校驗(yàn),多字段、少字段、字段類(lèi)型不符合預(yù)期都會(huì)報(bào)錯(cuò)
非常詳細(xì)的報(bào)錯(cuò)提示: 參見(jiàn)截圖
3. 安裝yarn add aester npm i aester -S4. 使用 4.1. 編寫(xiě)測(cè)試用例
// filename 必須以 test.js結(jié)尾 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 () => { // 對(duì)于符合預(yù)期的正向測(cè)試,不需要使用expect, 如果響應(yīng)狀態(tài)碼是400以上,或者響應(yīng)體結(jié)構(gòu)不符合預(yù)期, // 該測(cè)試用例會(huì)自動(dòng)失敗 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") }) })4.2. 接口配置文件
// 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, 在請(qǐng)求發(fā)送時(shí),會(huì)自動(dòng)將{{sessionId}}替換成真正的值,否則會(huì)被替換成空字符串 } }, 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: "獲取用戶(hù)信息接口", req: { method: "delete", path: "/users/{{id}}", headers: { "sessionId": "{{sessionId}}" } } } }4.3. 運(yùn)行測(cè)試用例
在package.json加入
"scripts": { "test": "jest" }
然后運(yùn)行npm test
4.4. 生成html測(cè)試報(bào)告yarn add jest-html-reporter -D4.4.1. 方法1
然后在package.json中加入如下字段
"test:report": "jest --reporters="jest-html-reporter""
然后運(yùn)行
npm run test:report4.4.2. 方法2
創(chuàng)建jest.config.js在項(xiàng)目根目錄
module.exports = { verbose: true, testEnvironment: "node", reporters: [ "default", ["./node_modules/jest-html-reporter", { pageTitle: `operation api test ${process.env.testConfigEnv}`, includeFailureMsg: true // 詳細(xì)錯(cuò)誤提示 }] ] }
然后運(yùn)行
npm test5. 參看測(cè)試結(jié)果 5.1. 正常測(cè)試結(jié)果
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.864s5.2. 接口報(bào)錯(cuò)測(cè)試結(jié)果
"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.5.3. 接口返回響應(yīng)體不符合預(yù)期測(cè)試結(jié)果(test/index.test.js:20:1)
例如,resBodyStruct配置sessionId為number格式,但是返回的格式是字符串,將會(huì)如下格式的報(bào)錯(cuò)
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:296. Api 6.1. Aest.init(apiConfs)
初始化配置文件
const Ae = require("aester") ... var conf = Ae.init(apiConfs)6.2. Aest.send(apiConf, options)
發(fā)送請(qǐng)求。
options會(huì)與share合并,然后將對(duì)應(yīng)變量渲染到請(qǐng)求模板中。
const Ae = require("aester") ... Ae.send(testData.getOneUser, {id: "1"}6.3. Aest.share(key, value)
設(shè)置共享變量
const Ae = require("aester") ... var conf = Ae.share("token", "123123")6.4. Aest.getShare()
獲取所有共享變量
const Ae = require("aester") ... var conf = Ae.getShare() // {token: "123123"}7. 配置文件說(shuō)明
key | 必須? | 說(shuō)明 |
---|---|---|
$baseUrl | 是 | 請(qǐng)求baseUrl |
desc | 否 | 接口說(shuō)明
req | 是 | 請(qǐng)求對(duì)象
req.method | 否 | 請(qǐng)求方法,默認(rèn)get
req.path | 是 | 請(qǐng)求路徑
req.headers | 是 | 默認(rèn)為空對(duì)象,默認(rèn)設(shè)置"content-type": "application/json; charset=UTF-8"
resBodyStruct | 否 | 響應(yīng)體格式校驗(yàn)對(duì)象
resBodyStruct字段說(shuō)明
{ key: keyType }
字段類(lèi)型支持如下
any: 任意
number: 數(shù)字
array: 數(shù)組
string: 字符串
boolean: 布爾值
null: null
undefined: undefined
object: 對(duì)象類(lèi)型
在字段類(lèi)型后加上?表示字段是否可選
如:
{ sessionId: "string?" //sessionId是字符串,但是可以沒(méi)有這個(gè)字段 }
更多字段類(lèi)型驗(yàn)證參考:https://github.com/ianstormta...
8. 測(cè)試Aesternpm test
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/96817.html
摘要:想做自動(dòng)化接口測(cè)試時(shí),我也按照打包鏡像的套路走,感覺(jué)走到死胡同。終于自己走通了一遍。點(diǎn)擊進(jìn)去可以發(fā)現(xiàn)測(cè)試報(bào)告。注意測(cè)試報(bào)告并不是生成的。我的項(xiàng)目目錄如下最后如果你也需要自動(dòng)化接口測(cè)試工具可以試試我最近寫(xiě)的一個(gè)工具。 關(guān)于jest和jenkins集成,我走了一些彎路。之前一直用jenkins打包nodejs鏡像。想做nodejs自動(dòng)化接口測(cè)試時(shí),我也按照打包鏡像的套路走,感覺(jué)走到死胡同。...
摘要:采用前后端分離模式可以減后臺(tái)負(fù)擔(dān),加快研發(fā)效率,當(dāng)然,前提是前端能做好的話。還是基礎(chǔ)不夠?qū)е碌暮蠖耸欠耧L(fēng)格很多公司采用了前后端分離模式后,后端仍然采用以往的傳統(tǒng)風(fēng)格,這是不合理的,風(fēng)格的應(yīng)該是前后端分離的最佳實(shí)踐。 showImg(https://segmentfault.com/img/bVFC8f?w=690&h=360);早期的web開(kāi)發(fā)是不分前端后端的。互聯(lián)網(wǎng)進(jìn)入Web2.0時(shí)...
摘要:采用前后端分離模式可以減后臺(tái)負(fù)擔(dān),加快研發(fā)效率,當(dāng)然,前提是前端能做好的話。還是基礎(chǔ)不夠?qū)е碌暮蠖耸欠耧L(fēng)格很多公司采用了前后端分離模式后,后端仍然采用以往的傳統(tǒng)風(fēng)格,這是不合理的,風(fēng)格的應(yīng)該是前后端分離的最佳實(shí)踐。 showImg(https://segmentfault.com/img/bVFC8f?w=690&h=360);早期的web開(kāi)發(fā)是不分前端后端的?;ヂ?lián)網(wǎng)進(jìn)入Web2.0時(shí)...
摘要:采用前后端分離模式可以減后臺(tái)負(fù)擔(dān),加快研發(fā)效率,當(dāng)然,前提是前端能做好的話。還是基礎(chǔ)不夠?qū)е碌暮蠖耸欠耧L(fēng)格很多公司采用了前后端分離模式后,后端仍然采用以往的傳統(tǒng)風(fēng)格,這是不合理的,風(fēng)格的應(yīng)該是前后端分離的最佳實(shí)踐。 showImg(https://segmentfault.com/img/bVFC8f?w=690&h=360);早期的web開(kāi)發(fā)是不分前端后端的。互聯(lián)網(wǎng)進(jìn)入Web2.0時(shí)...
摘要:路由設(shè)計(jì)路由設(shè)計(jì)以用戶(hù)注冊(cè)為例介紹如何閉環(huán)用戶(hù)注冊(cè)開(kāi)發(fā)注意點(diǎn)使用郵箱注冊(cè)驗(yàn)證郵箱是否注冊(cè)目前真實(shí)開(kāi)發(fā)業(yè)務(wù)大部分都是手機(jī)號(hào)注冊(cè),這塊由于沒(méi)有購(gòu)買(mǎi)短信服務(wù)首先,在文件夾下新建上圖中對(duì)應(yīng)真實(shí)業(yè)務(wù)邏輯現(xiàn)附上業(yè)務(wù)實(shí)現(xiàn)代碼加密?chē)?guó)際化工具類(lèi)用戶(hù)服務(wù) 路由設(shè)計(jì) 路由設(shè)計(jì) 以用戶(hù)注冊(cè)為例介紹如何閉環(huán)用戶(hù)注冊(cè)開(kāi)發(fā)注意點(diǎn):(1)使用郵箱注冊(cè)(2)驗(yàn)證郵箱是否注冊(cè) 【目前真實(shí)開(kāi)發(fā)業(yè)務(wù)大部分都是手機(jī)號(hào)注冊(cè),這塊...
閱讀 3275·2021-10-14 09:42
閱讀 3592·2019-08-26 13:56
閱讀 3560·2019-08-26 11:59
閱讀 973·2019-08-23 18:00
閱讀 2242·2019-08-23 17:51
閱讀 3563·2019-08-23 17:17
閱讀 1504·2019-08-23 15:11
閱讀 5340·2019-08-23 15:05