json格式校验并显示错误_使用postman做自动化接口校验
要想實現(xiàn)接口的自動化測試,需要以下幾個步驟:
自動登錄
首先點擊postman左上角的new按鈕,創(chuàng)建一個collection,在pre-request-scripts標(biāo)簽下,給整個collection創(chuàng)建一個公用規(guī)則
編寫登錄腳本
pre-request-scripts在請求發(fā)送前執(zhí)行的腳本,在整個集合期間只會執(zhí)行一次;
在集合變量(參考上圖)中添加對應(yīng)的用戶名和密碼
//獲取集合 const { host, username, password } = pm.collectionVariables.toObject();使用pm.sendRequest方法發(fā)送一個ajax請求,將請求成功的結(jié)果的token值存到環(huán)境變量中。
const data = res.json(); pm.environment.set("token", data.data["X-Access-Token"]);完整代碼如下:
const {// host,yapiToken,yapiHost,variable_key,token,catid,CooperationPlatformId } = pm.variables.toObject();const { host, username, password } = pm.collectionVariables.toObject(); const echoPostRequest = {url: `${host}/api/login`,method: 'POST',header: 'Content-Type: application/json;charset=UTF-8',body: {mode: 'raw',raw: JSON.stringify({ username, password})} }; //使用pm.sendRequest方法發(fā)送一個ajax請求, if(!token){pm.sendRequest(echoPostRequest, function (err, res) {console.log(err ? err : res.json());const data = res.json();pm.environment.set("token", data.data["X-Access-Token"]); }); }yapi,去哪網(wǎng)出的開源的可視化接口管理平臺,推薦部署到公司服務(wù)器,也可以直接使用官方的。
YApi-高效、易用、功能強(qiáng)大的可視化接口管理平臺?yapi.demo.qunar.comschema格式的約束文件,值得推薦的地方就是對mockjs語法支持的很好。
{"type": "object","title": "empty object","properties": {"data": {"type": "object","properties": {"name": {"type": "string","mock": {"mock": "@string"}}},"required": ["name"]},"code": {"type": "string","mock": {"mock": "@natural"}},"msg": {"type": "string","mock": {"mock": "@string"}}},"required": ["data","code","msg"] }開放Api?hellosean1025.github.io獲取接口的schema文件
yapi的開發(fā)api很方便的獲取接口相關(guān)的信息。
//生成分類下接口列表的map對象 const genCatInterfaceListMap = function (catid) {return new Promise(function (resolve, reject) {const url = `${yapiHost}/api/interface/list_cat?token=${yapiToken}&catid=${catid}&limit=100`;pm.sendRequest(url, function(err, res){if(err){console.log("err: ", err)}else{var data = res.json();var list = data.data.list;var catInterfaceListMap = list.reduce((acc, item) => {var key = item.path.slice(1).split("/").join("_");acc[key] = item._id;return acc;}, {})resolve(catInterfaceListMap);}})}); };獲取指定分類下的接口列表,并存到集合變量中。
genCatInterfaceListMap(catid).then((newMap) => {let catInterfaceListMap = pm.collectionVariables.get("catInterfaceListMap") || {};pm.collectionVariables.set("catInterfaceListMap", Object.assign({}, catInterfaceListMap, newMap)); });genCatInterfaceListMap(CooperationPlatformId).then((newMap) => {let catInterfaceListMap = pm.collectionVariables.get("catInterfaceListMap") || {};pm.collectionVariables.set("catInterfaceListMap", Object.assign({}, catInterfaceListMap, newMap)); })關(guān)鍵環(huán)節(jié)來了從yapi獲取接口的schema,并驗證格式
//驗證數(shù)據(jù)格式測試用例。 pm.test("數(shù)據(jù)格式正確", () => {var valid = validate(pm.response.json());if(!valid){console.log("validate.errors", validate)validate.errors.forEach(function(item){console.log(item.dataPath, ":", item.message);})}pm.expect(valid).to.be.true })使用avj來做校驗;
var Ajv = require('ajv'); var ajv = new Ajv(); // options can be passed, e.g. {allErrors: true} var validate = ajv.compile(schema); var valid = validate(data); if (!valid) console.log(validate.errors);完整代碼
在collection的Tests tab下,編寫下面代碼
//從yapi 服務(wù)上獲取到了對應(yīng)的schema,檢驗接口返回值是否匹配schema var Ajv = require("ajv"); var ajv = new Ajv({logger: console, allErrors: true}); const { path } = pm.request.url; const yapiToken = pm.variables.get("yapiToken") const pathKey = path.slice(-3).join("_"); const catid293 = pm.variables.get("catid293"); const interfaceId = catid293[pathKey];console.log("path:Test", pathKey, catid293, interfaceId); const url = `http://yapi.ops.tst-weiboyi.com/api/interface/get?token=${yapiToken}&id=${interfaceId}`;//從yapi接口中獲取當(dāng)前接口的schema pm.sendRequest(url, function(err, res){if(err){console.log("err: ", err)}else{var data = res.json();var schema = JSON.parse(data.data.res_body);delete schema["$schema"];var validate = ajv.compile(schema);pm.test("數(shù)據(jù)格式正確", () => {var valid = validate(pm.response.json());if(!valid){console.log("validate.errors", validate)validate.errors.forEach(function(item){console.log(item.dataPath, ":", item.message);})}pm.expect(valid).to.be.true}) } })輸出錯誤信息
還有其他方法和參數(shù),默認(rèn)validate.errors雖然是個數(shù)組,但里面默認(rèn)只包含了第一條錯誤。具體能否輸出所有不匹配字段,還待研究?
補(bǔ)充:
//allErrors 默認(rèn)為false,只能顯示一條信息 var ajv = new Ajv({logger: console, allErrors: true}); 編寫測試入門-帶有示例?documenter.getpostman.com使用變量作為請求參數(shù)
(function(){const data = pm.response.json();const list = data.data.list;//獲取滿足指定操作條件的idconst okIds = list.filter(item => item.type == 1).map(item => item.id);const passIds = list.filter(item => item.type == 2).map(item => item.id);const [ okId ] = okIds;const [ passId ] = passIdspm.collectionVariables.set("customId", okId);pm.collectionVariables.set("passId", passId); })()可以在下個請求中使用上個請求存儲的變量
{"type":"2", "remark":"1111", "id": {{okId}} }在body里面獲取變量注意事項
pm.collectionVariables.set("ids", [1,2,3]); //在body里面需要這樣寫 {"ids":{{ids}} }自動化批量測試
查看格式報錯
在postman的控制臺,可以顯示所有格式錯誤的log
其他的集合測試用例
在編輯集合的彈窗里面,Tests標(biāo)簽下,可以編寫公共測試用例,集合下的每個請求都會執(zhí)行
pm.test("Status code is 200", function () {pm.response.to.have.status(200); });pm.test('狀態(tài)碼為1000', () => {var d = pm.response.json();pm.expect(d.code).to.equal("1000") })pm.test("Response time is less than 200ms", function () {pm.expect(pm.response.responseTime).to.be.below(200); });//清除全局變量 pm.globals.unset("variable_key");pm.test("Content-Type is present", function () {pm.response.to.have.header("Content-Type"); });編寫單個請求的測試用例
在每個請求的Tests標(biāo)簽下,可以編寫腳本,這個是請求成功后執(zhí)行的代碼
//獲取變量 const aId = pm.collectionVariables.get("accountId");console.log("aId", aId) //編寫測試用例 pm.test(`上架成功, id: ${aId}`, () => {//將返回值轉(zhuǎn)換為json對象var d = pm.response.json();//驗證返回值的code值是否是1000pm.expect(d.code).to.equal("1000") })相關(guān)文檔
pm.expect語法相關(guān)文檔 chaijs BDD(想弄明白,就仔細(xì)看一遍這個文檔)
BDD
The BDD styles are expect and should. Both use the same chainable language to construct assertions, but they differ in the way an assertion is initially constructed. Check out the Style Guide for a comparison.
API Reference
Language Chains
The following are provided as chainable getters to improve the readability of your assertions.Chains
- to
- be
- been
- is
- that
- which
- and
- has
- have
- with
- at
- of
- same
- but
- does
- still
.not
Negates all assertions that follow in the chain.
expect(function () {}).to.not.throw(); expect({a: 1}).to.not.have.property('b'); expect([1, 2]).to.be.an('array').that.does.not.include(3);以下是文檔相關(guān)內(nèi)容,postman-sanbox-api-reference;(pm對象的相關(guān)屬性)
在postman的沙箱內(nèi)有幾個作用域
優(yōu)先順序是Iteration Data<Environment<Collection<Global。四個作用域分別對應(yīng)下面四個變量。
pm.variables,在 pre-request scripts中pm.variables.set("path", "/api/xxx"),在Test中可以通過pm.variables.get("path")獲取到
pm.variables
pm.variables: 閱讀有關(guān)VariableScope的更多信息
在Postman中,所有變量都符合特定的層次結(jié)構(gòu)。當(dāng)前迭代中定義的所有變量優(yōu)先于當(dāng)前環(huán)境中定義的變量,當(dāng)前環(huán)境中的變量將覆蓋全局范圍中定義的變量。優(yōu)先順序是Iteration Data< Environment< Collection< Global。
- pm.variables.has(variableName:String):function → Boolean:檢查當(dāng)前作用域中是否存在局部變量。
- pm.variables.get(variableName:String):function → *:獲取具有指定名稱的局部變量的值。
- pm.variables.toObject():function → Object:返回包含本地范圍內(nèi)所有變量的對象。
- pm.variables.set(variableName:String, variableValue:String"):function → void:使用給定值設(shè)置局部變量。
還可通過pm.environment環(huán)境范圍和pm.globals全局范圍訪問在各個范圍中定義的變量。
pm.environment
pm.environment: 閱讀有關(guān)VariableScope的更多信息
- pm.environment.name:String:包含當(dāng)前環(huán)境的名稱。
- pm.environment.has(variableName:String):function → Boolean:檢查環(huán)境是否具有具有給定名稱的變量。
- pm.environment.get(variableName:String):function → *:獲取具有給定名稱的環(huán)境變量。
- pm.environment.set(variableName:String, variableValue:String):function:使用給定的名稱和值設(shè)置環(huán)境變量。
- pm.environment.unset(variableName:String):function:刪除具有指定名稱的環(huán)境變量。
- pm.environment.clear():function:清除所有當(dāng)前環(huán)境變量。
- pm.environment.toObject():function → Object:以單個對象的形式返回所有環(huán)境變量。
pm.collectionVariables
pm.collectionVariables: 閱讀有關(guān)VariableScope的更多信息
- pm.collectionVariables.has(variableName:String):function → Boolean:檢查是否存在具有給定名稱的集合變量。
- pm.collectionVariables.get(variableName:String):function → *:返回具有給定名稱的collection變量的值。
- pm.collectionVariables.set(variableName:String, variableValue:String):function:設(shè)置具有給定值的集合變量。
- pm.collectionVariables.unset(variableName:String):function:清除指定的集合變量。
- pm.collectionVariables.clear():function:清除所有集合變量。
- pm.collectionVariables.toObject():function → Object:以對象的形式返回變量及其值的列表。
pm.globals
pm.globals: 閱讀有關(guān)VariableScope的更多信息
- pm.globals.has(variableName:String):function → Boolean:檢查是否存在具有給定名稱的全局變量。
- pm.globals.get(variableName:String):function → *:返回具有給定名稱的全局變量的值。
- pm.globals.set(variableName:String, variableValue:String):function:設(shè)置具有給定值的全局變量。
- pm.globals.unset(variableName:String):function:清除指定的全局變量。
- pm.globals.clear():function:清除所有全局變量。
- pm.globals.toObject():function → Object:以對象的形式返回變量及其值的列表。
pm.request
pm.request: 閱讀有關(guān)VariableScope的更多信息
request內(nèi)部的對象pm表示正在為此腳本運行的請求。對于請求前腳本,這是將要發(fā)送的請求,在測試腳本中時,這是已發(fā)送請求的表示。
request 包含以以下結(jié)構(gòu)存儲的信息:
- pm.request.url:Url:包含發(fā)出請求的URL。
- pm.request.headers:HeaderList:包含當(dāng)前請求的標(biāo)頭列表。
- pm.request.headers.add(headerName:String):function:為當(dāng)前請求添加具有指定名稱的標(biāo)頭。
- pm.request.headers.delete(headerName:String):function:刪除具有當(dāng)前請求的指定名稱的標(biāo)頭。
- pm.request.headers.upsert({ key: headerName:String, value: headerValue:String}):function):插入給定當(dāng)前請求的標(biāo)題列表的標(biāo)題名稱和標(biāo)題值(如果標(biāo)題不存在,否則將已存在的標(biāo)題更新為新值)。
pm.response
pm.response: 閱讀有關(guān)響應(yīng)的更多信息
在測試腳本中,該pm.response對象包含與收到的響應(yīng)有關(guān)的所有信息。
響應(yīng)詳細(xì)信息以以下格式存儲:
- pm.response.code:Number
- pm.response.reason():Function → String
- pm.response.headers:HeaderList
- pm.response.responseTime:Number
- pm.response.text():Function → String
- pm.response.json():Function → Object
pm.iterationData
pm.iterationData: 閱讀有關(guān)VariableScope的更多信息
該iterationData對象包含在收集運行期間提供的數(shù)據(jù)文件中的數(shù)據(jù)。
- pm.iterationData.get(variableName:String):function → *:從迭代數(shù)據(jù)中返回具有指定名稱的變量。
- pm.iterationData.toObject():function → Object:將迭代數(shù)據(jù)作為對象返回。
- pm.iterationData.addLayer(list: VariableList):function → void:將變量列表添加到迭代數(shù)據(jù)。
- pm.iterationData.clear():function → void:清除所有數(shù)據(jù)。
- pm.iterationData.has(variableName: string):function → boolean:檢查迭代數(shù)據(jù)中是否存在具有指定名稱的變量。
- pm.iterationData.set(key: string, value: any, type: string):function → void:設(shè)置變量,為其指定值和類型。
- pm.iterationData.syncVariablesFrom(object: {[key: string]: VariableDefinition}, track?: boolean, prune?: boolean):function → Object | Undefined:從具有指定名稱的對象獲取變量。
- pm.iterationData.syncVariablesTo(object?: {[key: string]: VariableDefinition}):function → Object:將變量保存到具有指定名稱的對象。
- pm.iterationData.toJSON():function → *:將迭代數(shù)據(jù)對象轉(zhuǎn)換為JSON格式。
- pm.iterationData.unset(key: string):function → void:取消分配給指定變量的值。
- pm.iterationData.variables():function → Object:從erationData對象返回所有變量。
- static pm.iterationData.isVariableScope(object: any):function → boolean:檢查特定變量是否在范圍內(nèi)。
pm.cookies
pm.cookies: 閱讀有關(guān)CookieList的更多信息
該cookies對象包含與請求域相關(guān)聯(lián)的cookie列表。
- pm.cookies.has(cookieName:String):Function → Boolean
檢查請求的域是否存在特定的cookie(以其名稱尋址)。 - pm.cookies.get(cookieName:String):Function → String
獲取特定cookie的值。 - pm.cookies.toObject:Function → Object
以對象的形式獲取所有cookie及其值的副本。返回的cookie是為請求的域和路徑定義的cookie。
pm.cookies.jar
- pm.cookies.jar():Function → Object
訪問Cookie罐對象。 - jar.set(URL:String, cookie name:String, cookie value:String, callback(error, cookie)):Function → Object
使用Cookie名稱和值設(shè)置Cookie。也可以通過在此函數(shù)中將cookie值與cookie名稱相關(guān)聯(lián)來直接設(shè)置cookie。 - jar.set(URL:String, { name:String, value:String, httpOnly:Bool }, callback(error, cookie)):Function → Object
使用PostmanCookie或其兼容對象設(shè)置cookie。 - jar.get(URL:String, token:String, callback (error, value)):Function → Object
從Cookie罐獲取Cookie。 - jar.getAll(URL:String, callback (error, cookies)):Function → Object
從cookie罐中獲取所有cookie。 - jar.unset(URL:String, token:String, callback(error)):Function → Object
取消設(shè)置Cookie。 - jar.clear(URL:String, callback (error)):Function → Object
清除餅干罐中的所有餅干。
pm.test
pm.test(testName:String, specFunction:Function):Function
您可以使用此功能在Pre-request Script或Tests沙箱中編寫測試規(guī)范。在此函數(shù)中編寫測試可以使您準(zhǔn)確地命名測試,并且即使該函數(shù)內(nèi)部存在錯誤,該函數(shù)也可以確保腳本的其余部分不會被阻塞。
在下面的示例測試中,我們正在檢查關(guān)于響應(yīng)的所有內(nèi)容對我們來說都是有效的。
pm.test("response should be okay to process", function () {pm.response.to.not.be.error;pm.response.to.have.jsonBody('');pm.response.to.not.have.jsonBody('error');});done可以將 可選的回調(diào)添加到中pm.test,以測試異步功能。
pm.test('async test', function (done) {setTimeout(() => {pm.expect(pm.response.code).to.equal(200);done();}, 1500);});- pm.test.index():Function → Number
從特定位置獲取總數(shù)測試。
期望值
pm.expect(assertion:*):Function → Assertion
pm.expect是一個通用的斷言函數(shù)。這是ChaiJS期望的BDD庫的基礎(chǔ)。使用該庫,可以很容易地編寫語法易讀的測試。
此功能對于處理來自response或的數(shù)據(jù)斷言很有用variables。有關(guān)使用的斷言測試示例pm.expect,請查看斷言庫示例
測試腳本中可用的響應(yīng)聲明API
- pm.response.to.have.status(code:Number)
- pm.response.to.have.status(reason:String)
- pm.response.to.have.header(key:String)
- pm.response.to.have.header(key:String, optionalValue:String)
- pm.response.to.have.body()
- pm.response.to.have.body(optionalValue:String)
- pm.response.to.have.body(optionalValue:RegExp)
- pm.response.to.have.jsonBody()
- pm.response.to.have.jsonBody(optionalExpectEqual:Object)
- pm.response.to.have.jsonBody(optionalExpectPath:String)
- pm.response.to.have.jsonBody(optionalExpectPath:String, optionalValue:*)
- pm.response.to.have.jsonSchema(schema:Object)
- pm.response.to.have.jsonSchema(schema:Object, ajvOptions:Object)
pm.to.be. *
通過pm.response.to.be對象內(nèi)部的屬性,您可以輕松地聲明一組預(yù)定義規(guī)則。
- pm.response.to.be.info
檢查1XX狀態(tài)碼 - pm.response.to.be.success
檢查2XX狀態(tài)碼 - pm.response.to.be.redirection
檢查3XX狀態(tài)碼 - pm.response.to.be.clientError
檢查4XX狀態(tài)碼 - pm.response.to.be.serverError
檢查5XX - pm.response.to.be.error
檢查4XX或5XX - pm.response.to.be.ok
狀態(tài)碼必須為200 - pm.response.to.be.accepted
狀態(tài)碼必須為202 - pm.response.to.be.badRequest
狀態(tài)碼必須為400 - pm.response.to.be.unauthorized
狀態(tài)碼必須為401 - pm.response.to.be.forbidden
狀態(tài)碼403 - pm.response.to.be.notFound
檢查響應(yīng)的狀態(tài)碼為404 - pm.response.to.be.rateLimited
檢查響應(yīng)狀態(tài)碼是否為429
總結(jié)
以上是生活随笔為你收集整理的json格式校验并显示错误_使用postman做自动化接口校验的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 最佳75个安全工具介绍及其下载地址
- 下一篇: 在电脑上怎么做报表新手_在电脑上如何制作