Postman 測試腳本示例

2023-04-04 10:31 更新

使用您的請求、文件夾和集合中的“測試”選項(xiàng)卡編寫測試,當(dāng) Postman 收到您向其發(fā)送請求的 API 的響應(yīng)時(shí),這些測試將執(zhí)行。為每個(gè)請求添加您需要的許多測試。當(dāng)您將測試添加到文件夾或集合時(shí),它們將在其中的每個(gè)請求之后執(zhí)行。

開始測試

要編寫您的第一個(gè)測試腳本,請?jiān)?Postman 中打開一個(gè)請求,然后選擇“測試”選項(xiàng)卡。輸入以下 JavaScript 代碼:

pm.test("Status code is 200", function () {
  pm.response.to.have.status(200);
});

此代碼使用pm庫來運(yùn)行該test方法。文本字符串將出現(xiàn)在測試輸出中。測試中的函數(shù)代表一個(gè)斷言。Postman 測試可以使用Chai Assertion Library BDD語法,它提供選項(xiàng)來優(yōu)化測試對您和您的合作者的可讀性。在這種情況下,代碼使用 BDD 鏈to.have來表達(dá)斷言。

此測試檢查 API 返回的響應(yīng)代碼。如果響應(yīng)代碼是200,則測試將通過,否則將失敗。選擇發(fā)送并轉(zhuǎn)到響應(yīng)區(qū)域中的測試結(jié)果選項(xiàng)卡。

測試輸出

要了解測試結(jié)果在通過或失敗時(shí)的樣子,請更改斷言代碼中的狀態(tài)代碼并再次發(fā)送請求。

以多種方式構(gòu)建您的測試斷言,以適應(yīng)您對結(jié)果輸出方式的邏輯和偏好。以下代碼是使用語法實(shí)現(xiàn)與上述代碼相同測試的另一種方法expect:

pm.test("Status code is 200", () => {
  pm.expect(pm.response.code).to.eql(200);
});
有關(guān)斷言語法選項(xiàng)的完整概述,請參閱Chai 斷言庫文檔。

使用多個(gè)斷言

您的測試可以包含多個(gè)斷言作為單個(gè)測試的一部分。使用它來將相關(guān)的斷言組合在一起:

pm.test("The response has all properties", () => {
    //parse the response JSON and test three properties
    const responseJson = pm.response.json();
    pm.expect(responseJson.type).to.eql('vip');
    pm.expect(responseJson.name).to.be.a('string');
    pm.expect(responseJson.id).to.have.lengthOf(1);
});

如果包含的任何斷言失敗,則整個(gè)測試將失敗。所有斷言都必須成功才能使測試通過。

解析響應(yīng)體數(shù)據(jù)

要對您的響應(yīng)執(zhí)行斷言,您首先需要將數(shù)據(jù)解析為您的斷言可以使用的 JavaScript 對象。

要解析 JSON 數(shù)據(jù),請使用以下語法:

const responseJson = pm.response.json();

要解析 XML,請使用以下內(nèi)容:

const responseJson = xml2Json(pm.response.text());
如果您正在處理復(fù)雜的 XML 響應(yīng),您可能會(huì)發(fā)現(xiàn)控制臺(tái)日志記錄很有用。

要解析 CSV,請使用CSV 解析實(shí)用程序:

const parse = require('csv-parse/lib/sync');
const responseJson = parse(pm.response.text());

要解析 HTML,請使用cheerio

const $ = cheerio.load(pm.response.text());
//output the html for testing
console.log($.html());

處理不解析的響應(yīng)

如果您無法將響應(yīng)正文解析為 JavaScript,因?yàn)樗母袷讲皇?JSON、XML、HTML、CSV 或任何其他可解析的數(shù)據(jù)格式,您仍然可以對數(shù)據(jù)進(jìn)行斷言。

測試響應(yīng)主體是否包含字符串:

pm.test("Body contains string",() => {
  pm.expect(pm.response.text()).to.include("customer_id");
});

這不會(huì)告訴您遇到字符串的位置,因?yàn)樗菍φ麄€(gè)響應(yīng)主體進(jìn)行測試。測試響應(yīng)是否與字符串匹配(通常只對短響應(yīng)有效):

pm.test("Body is string", function () {
  pm.response.to.have.body("whole-body-text");
});

對 HTTP 響應(yīng)進(jìn)行斷言

您的測試可以檢查請求響應(yīng)的各個(gè)方面,包括body、status codes、headerscookies、response times等等。

測試響應(yīng)體

檢查響應(yīng)正文中的特定值:

pm.test("Person is Jane", () => {
  const responseJson = pm.response.json();
  pm.expect(responseJson.name).to.eql("Jane");
  pm.expect(responseJson.age).to.eql(23);
});

測試狀態(tài)碼

測試響應(yīng)狀態(tài)碼:

pm.test("Status code is 201", () => {
  pm.response.to.have.status(201);
});

如果你想測試狀態(tài)代碼是否是一組中的一個(gè),請將它們?nèi)堪谝粋€(gè)數(shù)組中并使用oneOf:

pm.test("Successful POST request", () => {
  pm.expect(pm.response.code).to.be.oneOf([201,202]);
});

查看狀態(tài)碼文本:

pm.test("Status code name has string", () => {
  pm.response.to.have.status("Created");
});

測試標(biāo)頭

檢查是否存在響應(yīng)標(biāo)頭:

pm.test("Content-Type header is present", () => {
  pm.response.to.have.header("Content-Type");
});

測試具有特定值的響應(yīng)標(biāo)頭:

pm.test("Content-Type header is application/json", () => {
  pm.expect(pm.response.headers.get('Content-Type')).to.eql('application/json');
});

測試 cookie

測試響應(yīng)中是否存在 cookie:

pm.test("Cookie JSESSIONID is present", () => {
  pm.expect(pm.cookies.has('JSESSIONID')).to.be.true;
});

測試特定的 cookie 值:

pm.test("Cookie isLoggedIn has value 1", () => {
  pm.expect(pm.cookies.get('isLoggedIn')).to.eql('1');
});

測試響應(yīng)時(shí)間

測試響應(yīng)時(shí)間是否在指定范圍內(nèi):

pm.test("Response time is less than 200ms", () => {
  pm.expect(pm.response.responseTime).to.be.below(200);
});

常見斷言示例

繼續(xù)閱讀您可能會(huì)發(fā)現(xiàn)在您的腳本中有用的一些常見斷言示例,這些示例如下所述,或者通過編輯細(xì)節(jié)以滿足您自己的需要。

有關(guān)斷言中可以包含的內(nèi)容的更全面概述,請參閱Chai 斷言庫文檔。

針對變量斷言響應(yīng)值

檢查響應(yīng)屬性是否與變量(在本例中為環(huán)境變量)具有相同的值:

pm.test("Response property matches environment variable", function () {
  pm.expect(pm.response.json().name).to.eql(pm.environment.get("name"));
});
有關(guān)可用于在腳本中操縱變量的操作的概述,請參閱使用變量。

斷言值類型

測試響應(yīng)任何部分的類型:

/* response has this structure:
{
  "name": "Jane",
  "age": 29,
  "hobbies": [
    "skating",
    "painting"
  ],
  "email": null
}
*/
const jsonData = pm.response.json();
pm.test("Test data type of the response", () => {
  pm.expect(jsonData).to.be.an("object");
  pm.expect(jsonData.name).to.be.a("string");
  pm.expect(jsonData.age).to.be.a("number");
  pm.expect(jsonData.hobbies).to.be.an("array");
  pm.expect(jsonData.website).to.be.undefined;
  pm.expect(jsonData.email).to.be.null;
});

斷言數(shù)組屬性

檢查數(shù)組是否為空,以及它是否包含特定項(xiàng):

/*
response has this structure:
{
  "errors": [],
  "areas": [ "goods", "services" ],
  "settings": [
    {
      "type": "notification",
      "detail": [ "email", "sms" ]
    },
    {
      "type": "visual",
      "detail": [ "light", "large" ]
    }
  ]
}
*/

const jsonData = pm.response.json();
pm.test("Test array properties", () => {
    //errors array is empty
  pm.expect(jsonData.errors).to.be.empty;
    //areas includes "goods"
  pm.expect(jsonData.areas).to.include("goods");
    //get the notification settings object
  const notificationSettings = jsonData.settings.find
      (m => m.type === "notification");
  pm.expect(notificationSettings)
    .to.be.an("object", "Could not find the setting");
    //detail array must include "sms"
  pm.expect(notificationSettings.detail).to.include("sms");
    //detail array must include all listed
  pm.expect(notificationSettings.detail)
    .to.have.members(["email", "sms"]);
});
輸入的順序.members不影響測試。

斷言對象屬性

斷言對象包含鍵或?qū)傩裕?/p>

pm.expect({a: 1, b: 2}).to.have.all.keys('a', 'b');
pm.expect({a: 1, b: 2}).to.have.any.keys('a', 'b');
pm.expect({a: 1, b: 2}).to.not.have.any.keys('c', 'd');
pm.expect({a: 1}).to.have.property('a');
pm.expect({a: 1, b: 2}).to.be.an('object')
  .that.has.all.keys('a', 'b');
目標(biāo)可以是object、set或array。map如果在沒有or.keys的情況下運(yùn)行,則表達(dá)式默認(rèn)為. 由于行為因目標(biāo)而異,建議在使用with之前檢查。.all.any.all.keystypetype.keys.a

斷言一個(gè)值在一個(gè)集合中

根據(jù)有效選項(xiàng)列表檢查響應(yīng)值:

pm.test("Value is in valid list", () => {
  pm.expect(pm.response.json().type)
    .to.be.oneOf(["Subscriber", "Customer", "User"]);
});

斷言包含一個(gè)對象

檢查對象是否是父對象的一部分:

/*
response has the following structure:
{
  "id": "d8893057-3e91-4cdd-a36f-a0af460b6373",
  "created": true,
  "errors": []
}
*/

pm.test("Object is contained", () => {
  const expectedObject = {
    "created": true,
    "errors": []
  };
  pm.expect(pm.response.json()).to.deep.include(expectedObject);
});

Using.deep導(dǎo)致鏈中的所有.equal, .include, .members,.keys和.property斷言使用深度相等(松散相等)而不是嚴(yán)格 ( ===) 相等。雖然.eql也比較松散,.deep.equal但會(huì)導(dǎo)致深度相等比較也用于鏈中后面的任何其他斷言,而.eql不會(huì)。

斷言當(dāng)前環(huán)境

檢查 Postman 中的活動(dòng)(當(dāng)前選擇的)環(huán)境:

pm.test("Check the active environment", () => {
  pm.expect(pm.environment.name).to.eql("Production");
});

排除常見測試錯(cuò)誤

當(dāng)您在測試腳本中遇到錯(cuò)誤或意外行為時(shí),Postman控制臺(tái)可以幫助您識別來源。通過將console.log()、console.info()和debug 語句與您的測試斷言相結(jié)合,您可以檢查 HTTP 請求和響應(yīng)的內(nèi)容console.warn(),console.error()以及變量等 Postman 數(shù)據(jù)項(xiàng)。您也可以使用該console.clear()方法清除控制臺(tái)中的信息。從 Postman 頁腳中選擇 控制臺(tái)圖標(biāo) 控制臺(tái)以將其打開。

控制臺(tái)信息

記錄變量或響應(yīng)屬性的值:

console.log(pm.collectionVariables.get("name"));
console.log(pm.response.json().name);

記錄變量或響應(yīng)屬性的類型:

console.log(typeof pm.response.json().id);

使用控制臺(tái)日志來標(biāo)記代碼執(zhí)行,有時(shí)稱為“跟蹤語句”:

if (pm.response.json().id) {
  console.log("id was found!");
  // do something
} else {
  console.log("no id ...");
  //do something else
}

斷言深度相等錯(cuò)誤

您可能會(huì)遇到AssertionError: expected <value> to deeply equal '<value>'. 例如,這會(huì)出現(xiàn)在以下代碼中:

pm.expect(1).to.eql("1");

發(fā)生這種情況是因?yàn)闇y試正在將數(shù)字與字符串值進(jìn)行比較。只有當(dāng)類型和值都相等時(shí),測試才會(huì)返回 true。

JSON 未定義錯(cuò)誤

您可能會(huì)遇到此ReferenceError: jsonData is not defined問題。當(dāng)您嘗試引用尚未聲明或超出測試代碼范圍的 JSON 對象時(shí),通常會(huì)發(fā)生這種情況。

pm.test("Test 1", () => {
  const jsonData = pm.response.json();
  pm.expect(jsonData.name).to.eql("John");
});

pm.test("Test 2", () => {
  pm.expect(jsonData.age).to.eql(29); // jsonData is not defined
});

確保所有測試代碼都可以訪問將響應(yīng)數(shù)據(jù)設(shè)置為變量的任何代碼,例如,在這種情況下,在const jsonData = pm.response.json();第一個(gè)之前移動(dòng)pm.test將使它對兩個(gè)測試函數(shù)都可用。

斷言未定義錯(cuò)誤

您可能會(huì)遇到此AssertionError: expected undefined to deeply equal..問題。當(dāng)您引用不存在或超出范圍的屬性時(shí),通常會(huì)發(fā)生這種情況。

pm.expect(jsonData.name).to.eql("John");

在此示例中,如果出現(xiàn)錯(cuò)誤AssertionError: expected undefined to deeply equal 'John',則表示該name屬性未在jsonData對象中定義。

測試不失敗

在某些情況下,您可能希望測試失敗,但實(shí)際上并沒有。

//test function not properly defined - missing second parameter
pm.test("Not failing", function () {
    pm.expect(true).to.eql(false);
});

請確保您的測試代碼在句法上是正確的,然后再次發(fā)送您的請求。

驗(yàn)證響應(yīng)結(jié)構(gòu)

使用 Tiny Validator V4 (tv4) 執(zhí)行 JSON 模式驗(yàn)證:

const schema = {
 "items": {
 "type": "boolean"
 }
};
const data1 = [true, false];
const data2 = [true, 123];

pm.test('Schema is valid', function() {
  pm.expect(tv4.validate(data1, schema)).to.be.true;
  pm.expect(tv4.validate(data2, schema)).to.be.true;
});

使用 Ajv JSON 模式驗(yàn)證器驗(yàn)證 JSON 模式:

const schema = {
  "properties": {
    "alpha": {
      "type": "boolean"
    }
  }
};
pm.test('Schema is valid', function() {
  pm.response.to.have.jsonSchema(schema);
});

發(fā)送異步請求

從您的測試代碼發(fā)送請求并記錄響應(yīng)。

pm.sendRequest("https://postman-echo.com/get", function (err, response) {
    console.log(response.json());
});

以前編寫 Postman 測試的風(fēng)格(已棄用)

本節(jié)涉及以前版本的 Postman 中使用的已棄用的腳本語法。如果您正在編寫新腳本,請使用當(dāng)前語法。

以前編寫 Postman 測試的風(fēng)格依賴于為tests對象設(shè)置值。為對象中的元素設(shè)置一個(gè)描述性鍵,然后斷言它是真還是假。例如,以下將檢查響應(yīng)正文是否包含字符串user_id:

tests["Body contains user_id"] = responsebody.has("user_id");

根據(jù)需要添加盡可能多的鍵,具體取決于您要測試的內(nèi)容的數(shù)量。在“測試”選項(xiàng)卡下的響應(yīng)查看器中查看您的測試結(jié)果。選項(xiàng)卡標(biāo)題顯示通過了多少測試,您在測試變量中設(shè)置的鍵也列在那里。如果該值評估為真,則測試通過。

//set an environment variable
postman.setEnvironmentVariable("key", "value");

//set a nested object as an environment variable
const array = [1, 2, 3, 4];
postman.setEnvironmentVariable("array", JSON.stringify(array, null, 2));
const obj = { a: [1, 2, 3, 4], b: { c: 'val' } };
postman.setEnvironmentVariable("obj", JSON.stringify(obj));

//get an environment variable
postman.getEnvironmentVariable("key");

//get an environment variable whose value is a stringified object
//(wrap in a try-catch block if the data is coming from an unknown source)
const array = JSON.parse(postman.getEnvironmentVariable("array"));
const obj = JSON.parse(postman.getEnvironmentVariable("obj"));

//clear an environment variable
postman.clearEnvironmentVariable("key");

//set a global variable
postman.setGlobalVariable("key", "value");

//get a global variable
postman.getGlobalVariable("key");

//clear a global variable
postman.clearGlobalVariable("key");

//check if response body contains a string
tests["Body matches string"] = responseBody.has("string_you_want_to_search");

//check if response body is equal to a string
tests["Body is correct"] = responseBody === "response_body_string";

//check for a JSON value
const data = JSON.parse(responseBody);
tests["Your test name"] = data.value === 100;

//Content-Type is present (Case-insensitive checking)
tests["Content-Type is present"] = postman.getResponseHeader("Content-Type");
tests["Content-Type is present"] = postman.getResponseHeader("Content-Type");
//getResponseHeader() method returns the header value, if it exists

//Content-Type is present (Case-sensitive)
tests["Content-Type is present"] = responseHeaders.hasOwnProperty("Content-Type");

//response time is less than 200ms
tests["Response time is less than 200ms"] = responseTime < 200;

//response time is within a specific range
//(lower bound inclusive, upper bound exclusive)
tests["Response time is acceptable"] = _.inRange(responseTime, 100, 1001);

//status code is 200
tests["Status code is 200"] = responseCode.code === 200;

//code name contains a string
tests["Status code name has string"] = responseCode.name.has("Created");

//successful POST request status code
tests["Successful POST request"] = responseCode.code === 201 || responseCode.code === 202;

下一步

既然您已經(jīng)看到了各種場景的測試腳本示例,您可能會(huì)對擴(kuò)展自己的測試感興趣:


以上內(nèi)容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號