API測試:Postman/Newman
1)為什麼Postman/Newman
Postman是用於腳本和查詢集合的方便IDE。Newman是CLI引擎,可在CI/CD中運行相同的沒有GUI的集合。他們一起給出:- 可重復的倒退和快速的煙霧;
- 環境/秘密參數化;
- 質量指標和機器可讀報告。
2)基本模型
集合-具有常見腳本的查詢和文件夾樹。
環境-dev/stage/prod (URL, keys)的'{vars}集合。
預請求腳本-準備:簽名,令牌,數據共振。
測試-批準和保存變量/工件。
數據文件-用於數據驅動運行的CSV/JSON。
Mock/Monitor-穩定和定期檢查。
<API v1>
├─ _bootstrap (auth, health, seeds)
├─ Public
├─ Authenticated
│ ├─ Accounts
│ ├─ Payments
│ └─ Reports
└─ _teardown (cleanup)
3)變量和秘密
將變量命名為顯式前綴:「baseUrl」、「tenant」、「clientId」。
保存CI環境變量中的秘密(密碼、client_secret、HMAC密鑰),不要向存儲庫發送。
使用scope: local → collection → environment → globals(最小可能)。
json
{
"name": "stage-eu",
"values": [
{"key":"baseUrl","value":"https://api. stage. example. com","type":"text","enabled":true},
{"key":"tenant","value":"eu-1","type":"text","enabled":true}
]
}
4)身份驗證: 模板
4.1 OAuth2/OIDC (Client Credentials)
Pre-request:
js if (!pm.environment. get("access_token") Date. now() > pm. environment. get("token_exp")) {
pm. sendRequest({
url: pm. environment. get("authUrl"),
method: 'POST',
header: {'Content-Type':'application/x-www-form-urlencoded'},
body: { mode:'urlencoded', urlencoded:[
{key:'grant_type',value:'client_credentials'},
{key:'client_id',value:pm. environment. get('clientId')},
{key:'client_secret',value:pm. environment. get('clientSecret')},
{key:'scope',value:'payments:read payments:write'}
]}
}, (err, res) => {
pm. environment. set("access_token", res. json(). access_token);
pm. environment. set("token_exp", Date. now()+ (res. json(). expires_in-30)1000);
});
}
在查詢中: 「授權:Bearer {{access_token}}」.
4.2個HMAC(webhooks/合作夥伴)
Pre-request:
js const body = pm. request. body? pm. request. body. raw '': '';
const ts = Math. floor(Date. now()/1000);
const msg = `${ts}.${body}`;
const sig = CryptoJS. HmacSHA256(msg, pm. environment. get('hmacSecret')). toString();
pm. variables. set('ts', ts);
pm. variables. set('sig', sig);
標題:"X-Timestamp:{ts}},"X-Signature:{sig}"。
5)測試: 斷言和擴張
使用'pm。expect(...)` и `pm.test("...", fn)`.
通過'pm保存後續步驟的ID。collectionVariables.set`.
示例:js pm. test("HTTP 200", () => pm. response. to. have. status(200));
pm. test ("Scheme is valid," () => {
const schema = pm. collectionVariables. get("schema_wallet");
pm. expect(tv4. validate(pm. response. json(), JSON. parse(schema))). to. be. true;
});
pm. test ("Contains id," () => {
const id = pm. response. json(). id;
pm. expect(id). to. be. a('string');
pm. collectionVariables. set("wallet_id", id);
});
6)方案驗證(OpenAPI/JSON方案)
將JSON Schema存儲在集合變量或單獨的文件中。
對於OpenAPI:在pre-request/test (ajv, tv4)-通過'pm.sendRequest"到原始文件或JSON inline。
js pm. collectionVariables. set("schema_wallet", JSON. stringify({
"type":"object",
"required":["id","currency","balance"],
"properties":{
"id":{"type":"string"},
"currency":{"type":"string","pattern":"^[A-Z]{3}$"},
"balance":{"type":"number","minimum":0}
}
}));
7)數據驅動腳本
CSV:
email, password, currency u1@example. com, P@ss1, EUR u2@example. com, P@ss2, USD
查詢使用"{email}",{{currency}"。
啟動:
newman run collection. json -e stage-eu. json -d users. csv
JSON(對象數組)-適用於復雜的案例/結構。
8)負面案例和可持續性
覆蓋:- 401/403(無令牌/不正確的scope/角色)。
- 400/422(方案驗證、強制性字段、限制)。
- 404(BOLA/其他資源)。
- 409(沖突,等效密鑰)。
- 429(限制)-檢查「Retry-After」。
- 5xx-正確的客戶降級和恢復。
js pm. test ("There is Retry-After at 429," () => {
if (pm. response. code === 429) pm. expect(pm. response. headers. has('Retry-After')). to. be. true;
});
9)異位性,復古,分離
傳送「Idempotency-Key」並確保重播產生相同的「id/status」。
測試分頁:「limit/offset」/「cursor」,復制和跳過細節。
模擬測試腳本中的轉發:使用相同鍵連續調用。
js pm. test ("Idempotent repetition," () => {
pm. sendRequest(pm. request, (err, res2) => {
pm. expect(res2. code). to. eql(pm. response. code);
pm. expect(res2. json(). id). to. eql(pm. response. json(). id);
});
});
10) Newman в CI/CD
10.1啟動
newman run collection. json \
-e stage-eu. json \
-d data. csv \
--timeout-request 30000 \
--reporters cli,htmlextra,junit \
--reporter-htmlextra-export./reports/report. html \
--reporter-junit-export./reports/junit. xml
10.2 GitHub行動(片段)
yaml
- uses: actions/setup-node@v4 with: { node-version: '20' }
- run: npm i -g newman newman-reporter-htmlextra
- run: newman run collection. json -e stage-eu. json --reporters cli,junit --reporter-junit-export reports/junit. xml
- uses: actions/upload-artifact@v4 with: { name: newman-reports, path: reports }
10.3 Jenkins/GitLab CI
導出JUnit(「--reporter-junit-export」)進行本機可視化。
在pipline中,分開jobs: smoke(快速)、regression(完整)、security(否定/邊界)。
10.4 Docker
docker run --rm -v $PWD:/etc/newman postman/newman \
run collection. json -e stage-eu. json
11)洗滌和監測
Mock servers Postman是前線和合同的快速穩定。
監視器是從雲中定期運行的smokes(latency,5xx,SSL)。
在存儲庫中保留確定性濕疹的示例響應文件。
12)測試數據和清潔
創建/刪除實體(_bootstrap/_teardown)。
用「e2e_」和TTL前綴標記測試對象。
js pm. collectionVariables. set("uniq", Date. now()+"_"+Math. floor(Math. random()1e6));
13)「跪下」表演"
Postman不是負載工具,但是:- 測量'pm。response.responseTime`;
- 運行5-10次叠代並固定p95/閾值;
- 重型性能運行-在JMeter/k6/Gatling(本文之外)。
14)本地化和多範圍
變量「tenant」,「region」,「lang」;在周圍切換。
測試應驗證數據不被intertenant「流動」(BOLA讀數、交叉值禁令)。
針對區域特征(限值、貨幣)的單個集合/文件夾。
15)報告和文物
保存CI工件:HTML報告,"junit。xml',無響應響應的邏輯(響應對象)。
插入Slack/Teams滑塊下降通知。
16)質量和覆蓋範圍
塗層矩陣:- CRUD按資源(200/201/204+負值)。
- 授權:角色/漏鬥/多角色。
- 分離/過濾器/排序。
- 相同性和retrai。
- 限制:413/414/431/429。
- 格式和模式(JSON Schema/OpenAPI)。
- 集成(帶有HMAC/mTLS的webhooks)-反復制。
17)反模式
一個沒有負面測試的「快樂之路」。
集合/存儲庫中的長壽令牌。
將測試數據與prod數據混合。
沒有明顯共振的測試順序的隱性依賴性。
沒有采樣的巨型數據文件。
缺少JUnit/HTML報告→ CI中沒有可見性。
18)準備就緒支票清單
- 集合按域分列,有'_bootstrap /_teardown'。
- dev/stage/prod的環境;來自CI秘密存儲的秘密。
[] Pre-request для auth (OAuth2/HMAC);令牌被緩存和輪換。
- 測試:正面+負面,電路(JSON Schema),分位,429/Retry-After。
- 等效性:檢查「Idempotency-Key」,雙調用等效。
- 數據驅動的CSV/JSON,用於唯一性的隨機後綴。
- Newman in CI: JUnit/HTML報告,工件作為構建外包。
- 主要路線的洗滌器/監視器;Smokes的SLA。
- 變量、標記和啟動順序文檔。
19) TL;DR
將測試邏輯存儲在Postman集合中,將參數存儲在環境中,並通過Newman在CI中運行JUnit/HTML報告。覆蓋底片,電路,冪等,分期和限制。將步驟與變量相關聯,使用數據驅動輸入和洗滌器/監視器。秘密-僅來自CI,報告-法案文物。