QA 11: API testing (2) — Test dizayn, negative testlar, JSON Schema, Auth, Mock va Contract testing
🧪 QA Engineer — Zero to Hero
QA 11: API testing (2) — Test dizayn, negative testlar, JSON Schema, Auth, Mock va Contract testing
Holat: 2026-yil oktabr. Bu darsda API'ni "chuqur" testlaymiz: javobni 7 qatlamda tekshirish, maydonlar bo'yicha negative test dizayn, JSON Schema, autentifikatsiya va avtorizatsiya matritsasi, mock va contract testing, GraphQL/WebSocket/gRPC xususiyatlari. Darsdagi barcha "real topilmalar" restful-booker, Toolshop API va ochiq GraphQL API'da
curl/Newman 6.2.3/Ajv 8.20 bilan haqiqatan ishga tushirib olingan natijalar.
Bu darsdan keyin siz: API uchun "faqat 200 qaytdimi?" darajasidan chiqib, ma'lumot buzilishi, xavfsizlik va shartnoma (contract) bug'larini topadigan test to'plamini loyihalay olasiz.
- javobni status'dan tortib yon ta'sirlargacha 7 qatlamda tekshirasiz;
- har bir maydon uchun negative test'larni tizimli chiqarasiz;
- JSON Schema yozasiz va uni Postman hamda Node.js'da ishlatasiz;
401/403, token muddati, rollar va IDOR bo'yicha test matritsasi tuzasiz;- mock, contract testing va GraphQL'ning "200 ichidagi xato"si kabi tuzoqlarni bilasiz.
Mundarija
- API javobini 7 qatlamda tekshirish
- API test dizayni: CRUD matritsasi
- Maydonlar bo'yicha negative test dizayn
- Real topilmalar: restful-booker
- Real topilmalar: Toolshop API
- Xato javoblari formati va izchilligi
- Idempotentlik, parallel so'rovlar, sahifalash va rate limiting
- JSON Schema bilan sxemani tekshirish
- Autentifikatsiya va avtorizatsiya testlari
- Mock'lash: back-end tayyor bo'lmaganda
- Contract testing
- GraphQL, WebSocket, SSE va gRPC — QA uchun farqlar
- API test checklisti
- Amaliy mashqlar
- Xulosa
- Manbalar
1. API javobini 7 qatlamda tekshirish {#layers}
Junior tester ko'pincha bitta narsani tekshiradi: "status 200 mi?". Lekin 200 ichida noto'g'ri narx, null bo'lib qolgan maydon yoki boshqa foydalanuvchining ma'lumoti bo'lishi mumkin. API javobini qatlam-qatlam tekshiring:
API javobini 7 qatlamda tekshirish va har qatlam uchun restful-booker'da topilgan real holatlar
| # | Qatlam | Savol | Postman'da qanday |
|---|---|---|---|
| 1 | Status kod | Kod holatga mosmi (201 yaratishda, 422 validatsiyada)? | pm.response.to.have.status(201) |
| 2 | Header'lar | Content-Type, Location, Allow, kesh va xavfsizlik header'lari to'g'rimi? | pm.response.headers.get(...) |
| 3 | Sxema va tiplar | Majburiy maydonlar bormi, tiplar to'g'rimi, ortiqcha maydon yo'qmi? | pm.response.to.have.jsonSchema(schema) |
| 4 | Qiymatlar | Yuborilgan qiymat aynan saqlandimi? Hisob-kitob to'g'rimi? | pm.expect(body.total).to.eql(479000) |
| 5 | Biznes qoidalar | Domen qoidalari bajarildimi (bepul yetkazish ≥ 300 000 so'm)? | Qoida bo'yicha assertion |
| 6 | Yon ta'sirlar | DB'ga yozildimi, ro'yxatda ko'rindimi, email/push ketdimi? | Qo'shimcha GET, SQL (QA 12) |
| 7 | Nofunksional | Xatolar to'g'ri ushlanadimi, vaqt, xavfsizlik, limitlar | responseTime, negative va auth testlar |
🧠 Esda tuting: 1–2 qatlam — "server javob berdimi", 3–5 — "to'g'ri javob berdimi", 6–7 — "tizim to'g'ri ishladimi". Yaxshi QA uchala savolga ham javob qidiradi.
2. API test dizayni: CRUD matritsasi {#crud-matrix}
Har bir resurs uchun CRUD matritsasi tuzing: qatorlarda amallar, ustunlarda tekshiruv turlari. DemoBozor'ning xayoliy cart/items resursi uchun:
| Amal | Positive | Negative (ma'lumot) | Chegaraviy | Auth/rol | Holat/yon ta'sir |
|---|---|---|---|---|---|
POST /cart/items | Mavjud mahsulot, quantity: 1 | productId yo'q, string, mavjud bo'lmagan | quantity 0, 1, 99, 100 | Token'siz → 401 | Savatcha summasi va yetkazish narxi qayta hisoblandi |
GET /cart | Bo'sh va to'la savatcha | — | 50 xil mahsulot (limit) | Boshqa foydalanuvchi savatchasi ko'rinmaydi | Narxlar joriy (keshdan eski emas) |
PATCH /cart/items/{id} | quantity: 3 | quantity: "3", null, -1 | 1 → 99, 99 → 100 | Begona id → 403/404 | Summa yangilandi |
DELETE /cart/items/{id} | Mavjud element | Mavjud bo'lmagan id | Oxirgi elementni o'chirish | Begona id | Ikkinchi DELETE nima qaytaradi (idempotentlik) |
Bu jadval keyin test case'larga aylanadi (QA 7) va avtomatlashtiriladi (QA 20).
3. Maydonlar bo'yicha negative test dizayn {#field-design}
Har bir maydonga QA 5 dagi EP/BVA texnikalarini qo'llang va quyidagi "universal" mutatsiyalarni sinab ko'ring:
| Kategoriya | Mutatsiyalar |
|---|---|
| Mavjudlik | Majburiy maydon yo'q; null; bo'sh qator ""; faqat probellar " " |
| Tip | Son o'rniga string ("450", "abc"), boolean o'rniga "yes", obyekt o'rniga massiv |
| Raqamlar | 0, manfiy, kasr (450.75), juda katta (9007199254740993), ilmiy yozuv (1e3) |
| Uzunlik | min−1, min, max, max+1; 10 000+ belgi |
| Matn tarkibi | Unicode (Gʻayrat, Ўрол), emoji, RTL matn, boshida/oxirida probel, yangi qator \n |
| Xavfsizlik zondlari | ' OR '1'='1, <script>alert(1)</script> — kutilgani: xavfsiz ishlov (rad etish yoki to'g'ri escape), hech qachon 500 yoki bajarilish emas (QA 24) |
| Sana | Noto'g'ri format, mavjud bo'lmagan sana (2026-02-30), kabisa kuni (2028-02-29), o'tmish/kelajak, teskari oraliq |
| Enum | Ro'yxatdan tashqari qiymat, kichik harf (paid vs PAID) |
| Massiv | Bo'sh [], bitta element, limitdan ortiq, dublikatlar |
| Ortiqcha maydonlar | Noma'lum maydon; "role": "admin", "isAdmin": true kabi "mass assignment" urinishi |
| Format | Buzilgan JSON; Content-Type yo'q yoki noto'g'ri; bo'sh body |
DemoBozor POST /api/v1/cart/items uchun namuna:
| # | Body | Kutilgan |
|---|---|---|
| 1 | {"productId": 1042, "quantity": 1} | 201 |
| 2 | {"productId": 1042, "quantity": 99} | 201 (yuqori chegara) |
| 3 | {"productId": 1042, "quantity": 100} | 422, xato quantity maydoniga bog'langan |
| 4 | {"productId": 1042, "quantity": 0} | 422 |
| 5 | {"productId": 1042, "quantity": "2"} | 422 (yoki hujjatda yozilgan bo'lsa — aniq konvertatsiya), lekin jimgina emas |
| 6 | {"productId": 1042, "quantity": 2.5} | 422 — kesib 2 qilish emas |
| 7 | {"quantity": 1} | 422, "productId majburiy" |
| 8 | {"productId": 999999999, "quantity": 1} | 404 yoki 422 (mahsulot yo'q) |
| 9 | {"productId": 1042, "quantity": 1, "price": 1} | 201, lekin narx serverdagi narx bo'lishi shart (client narxi e'tiborga olinmaydi) |
| 10 | Buzilgan JSON | 400 |
| 11 | To'g'ri JSON, Content-Type: text/plain | 415 |
| 12 | Token'siz | 401 |
💡 Maslahat: 9-qator — eng qimmat bug'lardan biri. Agar server client yuborgan narxga ishonsa, foydalanuvchi choynakni 1 so'mga sotib oladi. Narx, chegirma, rol kabi "server hal qiladigan" qiymatlarni har doim so'rovga qo'shib ko'ring.
4. Real topilmalar: restful-booker {#findings-rb}
Endi nazariyani haqiqiy API'da sinaymiz. Quyidagi so'rovlarning hammasi POST https://restful-booker.herokuapp.com/booking ga Content-Type: application/json bilan yuborilgan (2026-yil 9-oktabr):
| # | Yuborilgan | Javob | Saqlangan qiymat | Baho |
|---|---|---|---|---|
| 1 | firstname yo'q | 500 Internal Server Error | — | Bug: validatsiya o'rniga server xatosi |
| 2 | Bo'sh obyekt {} | 500 | — | Bug |
| 3 | "totalprice": "abc" | 200 | "totalprice": null | Bug: jim ma'lumot yo'qotilishi |
| 4 | "totalprice": -100 | 200 | -100 | Bug: manfiy narx |
| 5 | checkout < checkin | 200 | teskari sanalar | Bug: biznes qoida yo'q |
| 6 | "checkin": "2026-13-45" | 200 | "0NaN-aN-aN" | Bug: yaroqsiz sana "axlat"ga aylandi |
| 7 | "firstname": "" | 200 | "" | Bug: bo'sh ism |
| 8 | Buzilgan JSON | 400 Bad Request | — | ✅ To'g'ri |
| 9 | To'g'ri JSON, Content-Type: text/plain | 500 | — | Bug: 415 kutiladi |
| 10 | "Gʻayrat 😀", "Oʻrinboyev" + "isAdmin": true | 200 | Unicode to'g'ri; isAdmin e'tiborsiz qoldirildi | ✅ To'g'ri |
| 11 | "depositpaid": "yes" | 200 | true | Jim konvertatsiya (hujjatlanmagan) |
| 12 | "totalprice": 450.75 | 200 | 450 | Bug: summa jimgina kesildi |
| 13 | firstname — 100 000 ta A | 200 | 100 000 belgi | Bug: uzunlik cheklovi yo'q |
| 14 | GET /booking/abc | 404 | — | ✅ Qabul qilinadi |
| 15 | GET /booking?checkin=2026-13-99 | 500 | — | Bug: filtr parametri validatsiyasiz |
Qiziq tafsilot: PUT da firstname yo'q bo'lsa server 400 qaytaradi, POST da esa xuddi shu holat 500. Ya'ni bir API ichida validatsiya izchil emas — bu ham alohida topilma.
Takrorlash uchun buyruqlar:
BASE=https://restful-booker.herokuapp.com
# 3-holat: narx string bo'lsa
curl -s -X POST $BASE/booking -H 'Content-Type: application/json' -H 'Accept: application/json' \
-d '{"firstname":"Aziz","lastname":"Karimov","totalprice":"abc","depositpaid":true,
"bookingdates":{"checkin":"2026-11-01","checkout":"2026-11-05"}}'
# {"bookingid":529,"booking":{...,"totalprice":null,...}}
# 9-holat: noto'g'ri Content-Type
curl -s -o /dev/null -w "%{http_code}\n" -X POST $BASE/booking -H 'Content-Type: text/plain' \
-d '{"firstname":"Aziz","lastname":"Karimov","totalprice":450,"depositpaid":true,
"bookingdates":{"checkin":"2026-11-01","checkout":"2026-11-05"}}'
# 500
Topilmani bug report'ga aylantirish
Sarlavha: [API] POST /booking: totalprice'ga string yuborilsa 200 qaytadi va narx null bo'lib saqlanadi
Muhit: https://restful-booker.herokuapp.com (public), 2026-10-09
Qadamlar:
1. POST /booking, Content-Type: application/json
2. Body: {"firstname":"Aziz","lastname":"Karimov","totalprice":"abc","depositpaid":true,
"bookingdates":{"checkin":"2026-11-01","checkout":"2026-11-05"}}
Kutilgan: 400/422, xato totalprice maydoniga bog'langan; booking yaratilmaydi
Haqiqiy: 200, bookingid qaytadi, saqlangan booking'da "totalprice": null
Jiddiylik: Major — ma'lumot jimgina buziladi, keyin hisob-kitoblar noto'g'ri bo'ladi
Qo'shimcha: o'xshash jim konvertatsiyalar — 450.75 → 450, "yes" → true (alohida ticket'lar)
Ilova: curl buyrug'i (yuqorida)
Bug report yozish san'ati batafsil: QA 8.
5. Real topilmalar: Toolshop API {#findings-toolshop}
Toolshop (https://practicesoftwaretesting.com) — testlashni mashq qilish uchun yaratilgan internet-do'kon; API'si https://api.practicesoftwaretesting.com. Demo xaridor: customer@practicesoftwaretesting.com / welcome01. 2026-yil 9-oktabrdagi kuzatuvlar:
| So'rov | Javob | Baho |
|---|---|---|
GET /products?page=1 | 200, {"current_page":1,"per_page":9,"last_page":6,"total":50,"data":[...]} | ✅ |
GET /products?page=999 | 200, data: [], from: null | ✅ Mantiqiy |
GET /products?page=-1 va page=abc | 200, jimgina 1-sahifa | Munozarali: 400 yoki hujjatlangan xatti-harakat kerak |
GET /products?sort=price,asc | Eng arzondan boshlab | ✅ |
GET /products?between=price,1,10 | total: 9 | ✅ |
GET /products?sort=hacker,up | 500 {"message":"Something went wrong"} | Bug: noto'g'ri parametr serverni yiqitadi |
GET /products/NOTEXIST | 404 {"message":"Requested item not found"} | ✅ |
GET /products/search?q=<script>alert(1)</script> | 200, bo'sh natija | ✅ Xavfsiz ishlov |
POST /users/register faqat first_name bilan | 422 + maydonlar bo'yicha xatolar | ✅ Namunali validatsiya |
POST /users/login noto'g'ri parol | 401 {"error":"Unauthorized"} | ✅ kod, lekin pastga qarang |
GET /users/me token'siz | 401 {"message":"Unauthorized"} | ✅ kod |
Xaridor token'i bilan GET /users (admin) | 403 {"message":"Forbidden"} | ✅ To'g'ri avtorizatsiya |
GET /users/logout, so'ng shu token bilan GET /users/me | 200, keyin 401 | ✅ Logout token'ni bekor qiladi |
Namunali 422 javobi — maydonlar bo'yicha aniq xatolar:
{
"last_name": ["The last name field is required."],
"email": ["The email field is required."],
"password": ["The password field is required."]
}
Ikki nozik topilma:
- Xato formati izchil emas: login xatosida kalit
error, boshqa endpoint'lardamessage. Client dasturchisi har endpoint uchun alohida kod yozishga majbur. 401javoblaridaWWW-Authenticateheader'i yo'q — HTTP standarti (RFC 9110)401uchun bu header'ni talab qiladi. Kichik, lekin spec bo'yicha topilma.
6. Xato javoblari formati va izchilligi {#error-format}
Xato javobi foydalanuvchi va dasturchi uchun "yo'l ko'rsatkich". Yaxshi xato javobi:
- to'g'ri status kod;
- mashina o'qiy oladigan kod (
"code": "QUANTITY_OUT_OF_RANGE") va inson o'qiy oladigan xabar; 422da qaysi maydon va nima xato;X-Request-IDkabi kuzatish identifikatori;- ichki tafsilotlar yo'q: stack trace, SQL so'rov, fayl yo'llari, kutubxona versiyalari.
Standart format — RFC 9457 "Problem Details" (Content-Type: application/problem+json). DemoBozor uchun namuna (xayoliy):
{
"type": "https://api.demobozor.example/errors/quantity-out-of-range",
"title": "Miqdor ruxsat etilgan oraliqda emas",
"status": 422,
"detail": "quantity 1 dan 99 gacha bo'lishi kerak, yuborilgan: 120",
"instance": "/api/v1/cart/items",
"errors": [{ "field": "quantity", "code": "QUANTITY_OUT_OF_RANGE" }]
}
QA tekshiruvlari:
- barcha endpoint'larda xato tuzilishi bir xilmi (Toolshop'dagi
errorvsmessageholati); Accept-Language: uzyuborilganda xabar o'zbekchami (agar talab bo'lsa);500javobida ichki ma'lumot sizib chiqmayaptimi (QA 10 dagi PetstoreNumberFormatExceptionmisoli);- mobil ilova va web xato kodini to'g'ri tarjima qilib, foydalanuvchiga tushunarli xabar ko'rsatyaptimi.
7. Idempotentlik, parallel so'rovlar, sahifalash va rate limiting {#idempotency}
Dublikat va idempotentlik
Bir xil POST /booking ni ketma-ket ikki marta yuborganimizda restful-booker ikkita booking yaratdi (ikki xil bookingid). DemoBozor'da bu "bitta tugma — ikkita buyurtma" degani. Testlar:
- "Buyurtma berish"ni ikki marta tez bosish (UI) va bir xil so'rovni ikki marta yuborish (API);
- tarmoq uzilib, ilova so'rovni qayta yuborganda (Proxyman Repeat bilan simulyatsiya — QA 15);
- agar API
Idempotency-Keykabi mexanizmni qo'llasa — bir xil kalit bilan ikkinchi so'rov yangi buyurtma yaratmasligi.
Parallel so'rovlar (race condition)
Ikki so'rov bir vaqtda kelsa, natija tasodifiy bo'lib qolishi mumkin. Bash'da & va wait bilan oddiy tajriba:
#!/usr/bin/env bash
# Bir booking'ga ikki "foydalanuvchi" bir vaqtda PATCH yuboradi
BASE=https://restful-booker.herokuapp.com
AUTH='Authorization: Basic YWRtaW46cGFzc3dvcmQxMjM='
ID=$(curl -s -X POST $BASE/booking -H 'Content-Type: application/json' -H 'Accept: application/json' \
-d '{"firstname":"Aziz","lastname":"Karimov","totalprice":450,"depositpaid":true,
"bookingdates":{"checkin":"2026-11-01","checkout":"2026-11-05"}}' \
| python3 -c 'import sys, json; print(json.load(sys.stdin)["bookingid"])')
for price in 500 700; do
curl -s -o /dev/null -w "PATCH totalprice=$price → %{http_code}\n" -X PATCH $BASE/booking/$ID \
-H 'Content-Type: application/json' -H 'Accept: application/json' -H "$AUTH" \
-d "{\"totalprice\": $price}" &
done
wait
curl -s $BASE/booking/$ID -H 'Accept: application/json' \
| python3 -c 'import sys, json; print("Yakuniy narx:", json.load(sys.stdin)["totalprice"])'
Uch marta ishga tushirganimizda yakuniy narx 700, 700, 500 chiqdi — "oxirgi yozgan yutadi" va kim oxirgi bo'lishi tasodifiy. DemoBozor'da xuddi shu turdagi muhim testlar: bitta martalik promo-kodni ikki parallel buyurtmada ishlatish, omborda 1 dona qolgan mahsulotni ikki kishi bir vaqtda sotib olishi, ikki tabdan bir vaqtda to'lov.
⚠️ Diqqat: Parallel va ko'p so'rovli testlarni faqat o'z test muhitingizda yoki ruxsat berilgan amaliyot API'larida, kichik sonlar bilan qiling. Begona serverga yuzlab so'rov yuborish — hujum sifatida qabul qilinishi mumkin. Yuklama testlari: QA 23.
Sahifalash, saralash va filtr
Toolshop'da total: 50, per_page: 9 → last_page: 6. Kutilgan natijalar: 5-sahifa — 37–45, 6-sahifa — 46–50 (5 ta), 7-sahifa — bo'sh. Haqiqatan ham shunday chiqdi. Sahifalash uchun test g'oyalari:
- birinchi, oxirgi va oxirgidan keyingi sahifa;
totalva barcha sahifalardagi elementlar yig'indisi teng;- sahifalar orasida dublikat yoki tushib qolgan element yo'q (ayniqsa saralash barqaror bo'lmasa yoki ro'yxat test paytida o'zgarsa);
page=0, manfiy, harf;per_pagelimitidan katta qiymat;- saralash yo'nalishlari va teng qiymatlar (bir xil narxli mahsulotlar tartibi);
- filtrlar kombinatsiyasi va natija bo'sh bo'lganda javob formati.
Rate limiting
Server bir mijozdan keladigan so'rovlar sonini cheklashi mumkin: limitdan oshganda 429 Too Many Requests, ko'pincha Retry-After header'i bilan. Ba'zi API'lar limitni header'larda ko'rsatadi — masalan, jsonplaceholder javobida x-ratelimit-limit, x-ratelimit-remaining, x-ratelimit-reset bor. DemoBozor qoidasi bo'yicha test: 3 marta noto'g'ri SMS kod → 4-urinish bloklanadi, blok 15 daqiqa davom etadi, blok tugagach yana ishlaydi, boshqa telefon raqamiga ta'sir qilmaydi.
8. JSON Schema bilan sxemani tekshirish {#json-schema}
JSON Schema — JSON ma'lumotining tuzilishini tasvirlaydigan standart (joriy versiya — draft 2020-12). U "qanday maydonlar bo'lishi, qanday tipda, qanday chegaralarda" degan qoidalarni bir joyda yozish imkonini beradi.
| Kalit so'z | Ma'nosi | Misol |
|---|---|---|
type | Tip | "string", "integer", ["string", "null"] |
properties | Obyekt maydonlari | {"firstname": {...}} |
required | Majburiy maydonlar | ["firstname", "lastname"] |
additionalProperties | Ortiqcha maydonga ruxsat | false — kutilmagan maydon = xato |
enum | Ruxsat etilgan qiymatlar | ["CREATED", "PAID"] |
minimum, exclusiveMinimum, maximum | Son chegaralari | {"minimum": 0} |
minLength, maxLength, pattern | Matn cheklovlari | {"pattern": "^\\+998\\d{9}$"} |
format | Semantik format | "date", "email", "uuid" |
items, minItems | Massiv elementlari | {"items": {"$ref": "#/$defs/product"}} |
Node.js'da Ajv bilan (draft 2020-12)
Ataylab "yomon" booking yaratamiz va uni qat'iy sxema bilan tekshiramiz:
// validate-booking.mjs — restful-booker javobini JSON Schema (draft 2020-12) bilan tekshirish
// O'rnatish: npm i ajv ajv-formats
import Ajv2020 from "ajv/dist/2020.js";
import addFormats from "ajv-formats";
const bookingSchema = {
$schema: "https://json-schema.org/draft/2020-12/schema",
type: "object",
required: [
"firstname",
"lastname",
"totalprice",
"depositpaid",
"bookingdates",
],
properties: {
firstname: { type: "string", minLength: 1, maxLength: 50 },
lastname: { type: "string", minLength: 1, maxLength: 50 },
totalprice: { type: "integer", minimum: 0 },
depositpaid: { type: "boolean" },
bookingdates: {
type: "object",
required: ["checkin", "checkout"],
properties: {
checkin: { type: "string", format: "date" },
checkout: { type: "string", format: "date" },
},
},
additionalneeds: { type: "string" },
},
additionalProperties: false,
};
const ajv = new Ajv2020({ allErrors: true });
addFormats(ajv);
const validate = ajv.compile(bookingSchema);
const BASE = "https://restful-booker.herokuapp.com";
// 1) Ataylab "yomon" booking yaratamiz: bo'sh ism, manfiy narx, noto'g'ri sana
const created = await fetch(`${BASE}/booking`, {
method: "POST",
headers: { "Content-Type": "application/json", Accept: "application/json" },
body: JSON.stringify({
firstname: "",
lastname: "Karimov",
totalprice: -100,
depositpaid: true,
bookingdates: { checkin: "2026-13-45", checkout: "abc" },
}),
}).then((r) => r.json());
// 2) Serverda qanday saqlanganini o'qiymiz
const saved = await fetch(`${BASE}/booking/${created.bookingid}`, {
headers: { Accept: "application/json" },
}).then((r) => r.json());
// 3) Sxema bilan tekshiramiz
if (validate(saved)) {
console.log("✅ Javob sxemaga mos");
} else {
console.log("❌ Sxema xatolari:");
for (const err of validate.errors) {
console.log(` ${err.instancePath || "/"} ${err.message}`);
}
}
Haqiqiy natija (node validate-booking.mjs):
❌ Sxema xatolari:
/firstname must NOT have fewer than 1 characters
/totalprice must be >= 0
/bookingdates/checkin must match format "date"
/bookingdates/checkout must match format "date"
Bitta sxema to'rtta bug'ni birdaniga ushladi. Shuning uchun sxema tekshiruvi — API regression'ining arzon va kuchli qatlami.
Postman'da
const schema = {
type: "object",
required: ["bookingid", "booking"],
properties: {
bookingid: { type: "integer" },
booking: {
type: "object",
required: ["firstname", "totalprice", "bookingdates"],
properties: {
firstname: { type: "string" },
totalprice: { type: "integer" },
bookingdates: {
type: "object",
properties: {
checkin: { type: "string", format: "date" },
checkout: { type: "string", format: "date" },
},
},
},
},
},
};
pm.test("Javob JSON Schema'ga mos", () => {
pm.response.to.have.jsonSchema(schema);
});
Yaroqsiz sana bilan booking yaratilganda Newman 6.2.3 aynan shunday xato beradi:
AssertionError Javob JSON Schema'ga mos
expected data to satisfy schema but found following errors:
data.booking.bookingdates.checkin should match format "date"
⚠️ Diqqat: Newman 6.2.3 (Postman sandbox) bilan tekshirganimizda sxemaga
$schema: "https://json-schema.org/draft/2020-12/schema"qo'shilsa, testno schema with key or ref ...xatosi bilan yiqildi;$schemaumuman yozilmaganda yoki draft-07 ko'rsatilganda ishladi. Postman skriptlarida$schemani yozmang — ishlatayotgan versiyangizda alohida sinab ko'ring.
Sxemani qayerdan olamiz? Agar API OpenAPI hujjatiga ega bo'lsa, sxemalar uning components.schemas bo'limida tayyor turadi — ularni qo'lda qayta yozmang, hujjatdan oling. Shunda test hujjat va kod mosligini ham tekshiradi (11-bo'lim).
9. Autentifikatsiya va avtorizatsiya testlari {#auth-tests}
Token holatlari matritsasi
| Holat | Kutilgan | Toolshop'da tekshirildi |
|---|---|---|
| Token yo'q | 401 | ✅ 401 {"message":"Unauthorized"} |
| Buzilgan token (oxirgi belgi o'zgartirilgan) | 401 | ✅ 401 |
| Muddati o'tgan token (Toolshop'da 5 daqiqa) | 401 | Mashq sifatida o'zingiz tekshiring |
| Logout'dan keyingi token | 401 | ✅ 200 → logout → 401 |
| To'g'ri token, ruxsat yo'q rol | 403 | ✅ xaridor → GET /users → 403 |
| To'g'ri token, o'z resursi | 200 | ✅ GET /users/me → 200 |
| To'g'ri token, boshqa foydalanuvchining resursi | 403 yoki 404 | IDOR — pastga qarang |
Rollar matritsasi (DemoBozor, xayoliy)
| Endpoint | Mehmon | Xaridor A | Xaridor B | Sotuvchi | Admin |
|---|---|---|---|---|---|
GET /products | ✅ | ✅ | ✅ | ✅ | ✅ |
GET /orders/{A ning buyurtmasi} | 401 | ✅ | 403/404 | 403\* | ✅ |
POST /orders/{id}/cancel (A ning, PAID) | 401 | ✅ | 403/404 | 403 | ✅ |
PATCH /products/{id} (sotuvchining o'z mahsuloti) | 401 | 403 | 403 | ✅ | ✅ |
GET /admin/users | 401 | 403 | 403 | 403 | ✅ |
\* Talabga bog'liq: sotuvchi o'z mahsuloti bor buyurtmani ko'rishi mumkin bo'lsa — faqat o'sha qismini.
IDOR / BOLA — API'dagi eng xavfli bug turi
IDOR (Insecure Direct Object Reference), OWASP API Security Top 10 (2023) da API1: Broken Object Level Authorization (BOLA) — server "bu foydalanuvchi shu obyektga egami?" deb tekshirmaydi. Xaridor B o'z token'i bilan GET /api/v1/orders/58231 (A ning buyurtmasi) so'rasa va javob 200 bo'lsa — begona manzil, telefon va xaridlar ochilib qoladi.
Test usuli oddiy: ikki test foydalanuvchi, A ning resurs ID'sini B ning token'i bilan so'rash — har bir endpoint uchun. Batafsil va boshqa xavfsizlik testlari: QA 24.
🎯 Intervyuda: "API'da avtorizatsiyani qanday testlaysiz?" — Rollar × endpoint'lar matritsasi tuzaman; har bir rol uchun ruxsat etilgan va taqiqlangan amallarni tekshiraman; ikki foydalanuvchi bilan bir-birining resurslariga kirishga urinaman (IDOR/BOLA); token yo'q, buzilgan, muddati o'tgan va logout'dan keyingi holatlarni alohida tekshiraman.
10. Mock'lash: back-end tayyor bo'lmaganda {#mocking}
Mock — haqiqiy server o'rniga oldindan tayyorlangan javob qaytaradigan "soxta" server yoki qatlam. Qachon kerak:
- back-end hali tayyor emas, lekin front-end/mobil ilovani testlash kerak;
- qiyin takrorlanadigan holatlar:
500, timeout, bo'sh ro'yxat, 99 ta element,nullnarx; - uchinchi tomon xizmati (to'lov, SMS) test muhitida yo'q yoki pullik.
| Vosita | Qayerda ishlaydi | Qachon qulay |
|---|---|---|
| Postman Mock Servers | Postman bulutida | Collection'dagi saqlangan misollar asosida tez mock |
| Mockoon | Desktop ilova + CLI | Lokal, kod yozmasdan, jamoa bilan fayl orqali bo'lishish |
| WireMock | Java/standalone/Docker | Murakkab qoidalar, CI'da avtomatik testlar |
| Chrome Local overrides | Brauzer | Web'da bitta javobni tez almashtirish (QA 9) |
| Proxyman Map Local | Mac/iOS/Android trafigi | Mobil ilova javoblarini almashtirish (QA 15) |
Playwright page.route | Avtomatik UI testlar | Testning o'zida javobni mock qilish (QA 19) |
⚠️ Diqqat: Mock — haqiqatning nusxasi, haqiqatning o'zi emas. Back-end o'zgarib, mock eskicha qolsa, testlar yashil, production esa qizil bo'ladi. Buning davosi — contract testing.
11. Contract testing {#contract}
Contract (shartnoma) — client va server o'rtasida "qanday so'rovga qanday javob" kelishuvi. Contract testing shu kelishuv buzilmaganini avtomatik tekshiradi.
Ikki asosiy yondashuv:
- Consumer-driven contracts (Pact). Client (consumer) testlari Pact yaratgan mock provider'ga so'rov yuboradi; natijada pact fayli — shartnoma yoziladi. Keyin provider (server) tomonida Pact shu so'rovlarni haqiqiy serverga qayta yuboradi va javob shartnomada kutilgan minimal ma'lumotni o'z ichiga olishini tekshiradi. Pact Broker shartnomalarni jamoalar va CI o'rtasida bo'lishish uchun ishlatiladi.
- Schema-based (OpenAPI). Server javoblari OpenAPI hujjatidagi sxemaga mosligini tekshirish (yuqoridagi JSON Schema yondashuvining kengaytmasi).
Shartnoma buzilishiga real misollar (2026-yil oktabr):
- Toolshop: OpenAPI hujjatida
GET /usersuchun faqat200,400,401javoblari yozilgan, amalda esa xaridor token'i bilan403keladi.POST /users/loginuchun faqat200hujjatlangan, noto'g'ri parolda esa401qaytadi. Hujjat to'liq emas. - Swagger Petstore: hujjat noto'g'ri ID uchun
400deydi, server404qaytaradi (QA 10).
Bunday "drift" mobil ilovalar uchun ayniqsa xavfli: eski versiyadagi ilovalar foydalanuvchilarda oylab ishlaydi va server javobi o'zgarsa, ular qulashi mumkin.
Test piramidasida contract testlar unit va integration testlar orasida turadi: tez, lekin ikki tomon o'rtasidagi kelishuvni tekshiradi. Ularni odatda dasturchilar yoki SDET'lar yozadi; QA'ning vazifasi — qaysi endpoint'lar va maydonlar "shartnoma"ga kirishi kerakligini aniqlashda qatnashish va drift'larni bug sifatida ko'tarish.
12. GraphQL, WebSocket, SSE va gRPC — QA uchun farqlar {#other-apis}
GraphQL
GraphQL'da odatda bitta endpoint (POST /graphql) bo'ladi; client aynan qaysi maydonlar kerakligini so'rovda yozadi (query — o'qish, mutation — o'zgartirish).
QA uchun eng muhim tuzoq — xato ko'pincha HTTP 200 bilan qaytadi. Ochiq GraphQL API'da tekshirdik:
# To'g'ri so'rov
curl -s -X POST https://countries.trevorblades.com/graphql -H 'Content-Type: application/json' \
-d '{"query":"{ country(code: \"UZ\") { name capital currency } }"}'
# 200 {"data":{"country":{"capital":"Tashkent","currency":"UZS","name":"Uzbekistan"}}}
# Mavjud bo'lmagan maydon
curl -s -w "\n%{http_code}\n" -X POST https://countries.trevorblades.com/graphql -H 'Content-Type: application/json' \
-d '{"query":"{ country(code: \"UZ\") { name population } }"}'
# {"errors":[{"message":"Cannot query field \"population\" on type \"Country\".", ...}]}
# 200
# Mavjud bo'lmagan davlat kodi
curl -s -w "\n%{http_code}\n" -X POST https://countries.trevorblades.com/graphql -H 'Content-Type: application/json' \
-d '{"query":"{ country(code: \"XX\") { name } }"}'
# {"data":{"country":null}}
# 200
GraphQL-over-HTTP spetsifikatsiyasining yangi qoralamasi validatsiya xatolari uchun 422 ni tavsiya qiladi, lekin amalda serverlar har xil ishlaydi. Xulosa: GraphQL'da faqat statusga ishonmang — har doim errors massivini tekshiring:
const json = pm.response.json();
pm.test("HTTP 200", () => {
pm.response.to.have.status(200);
});
pm.test("GraphQL xatosi yo'q", () => {
pm.expect(json.errors, JSON.stringify(json.errors)).to.be.undefined;
});
pm.test("Davlat nomi to'g'ri", () => {
pm.expect(json.data.country.name).to.eql("Uzbekistan");
});
Noto'g'ri maydonli so'rovda bu skriptning birinchi testi o'tdi (status 200), ikkinchisi esa xatoni ushladi — aynan shu sababli errors tekshiruvi shart. GraphQL uchun qo'shimcha test g'oyalari: juda chuqur ichma-ich so'rovlar (server cheklaydimi), katta first: 100000 kabi limitlar, introspection'ning production'da yopiqligi, mutation'larda avtorizatsiya.
WebSocket va SSE
- WebSocket — client va server o'rtasida doimiy, ikki tomonlama ulanish (chat, jonli buyurtma holati). Ulanish
101 Switching Protocolsbilan ochiladi. Test: ulanishda autentifikatsiya, xabarlar tartibi, ulanish uzilib qayta tiklanishi (reconnect), bir vaqtda ko'p xabar. Chrome DevTools → Network →WSfiltri → Messages tab'i; Postman ham WebSocket so'rovlarini qo'llab-quvvatlaydi. - SSE (Server-Sent Events) — faqat serverdan client'ga oqim (
Content-Type: text/event-stream), masalan, "buyurtmangiz yo'lda" bildirishnomalari. Test: ulanish uzilganda qayta ulanish va o'tkazib yuborilgan hodisalar.
gRPC
gRPC — Protocol Buffers (binary format) va HTTP/2 ustida ishlaydi; mikroservislar orasida ko'p uchraydi. O'z status kodlari bor (OK, INVALID_ARGUMENT, NOT_FOUND, PERMISSION_DENIED, UNAUTHENTICATED va boshqalar). Testlash uchun Postman'ning gRPC client'i yoki grpcurl kabi CLI vositalar ishlatiladi; .proto fayl — gRPC'ning "shartnomasi".
13. API test checklisti {#api-checklist}
| Soha | Tekshiruv |
|---|---|
| Hujjat | Har endpoint hujjatlangan; misollar ishlaydi; javob kodlari to'liq |
| Status | Har holat uchun to'g'ri kod; 500 faqat haqiqiy kutilmagan holatda |
| Header'lar | Content-Type; 201 da Location; 405 da Allow; 401 da WWW-Authenticate; keshlash; x-powered-by kabi ortiqcha ma'lumot yo'q |
| Sxema | Majburiy maydonlar, tiplar, null siyosati, ortiqcha maydonlar |
| Qiymatlar | Yuborilgan = saqlangan; hisob-kitoblar (summa, chegirma, yetkazish) |
| Validatsiya | Har maydon uchun EP/BVA, tiplar, uzunlik, format; jim konvertatsiya yo'q |
| Biznes qoidalar | DemoBozor qoidalari (OTP, promo, savatcha limitlari, holat o'tishlari) |
| Auth | Token yo'q/buzilgan/muddati o'tgan/logout'dan keyin; rollar; IDOR |
| Idempotentlik | Takroriy so'rovlar, Idempotency-Key, ikki marta bosish |
| Parallel | Race condition: oxirgi mahsulot, bir martalik promo |
| Sahifalash | Chegaralar, total mosligi, dublikat/tushib qolish, saralash barqarorligi |
| Rate limit | 429, Retry-After, blokdan chiqish |
| Xato formati | Izchil tuzilma, maydon darajasidagi xatolar, ichki ma'lumot yo'q |
| Yon ta'sirlar | DB, keyingi GET, email/SMS/push, audit log |
| Performance | Asosiy endpoint'lar javob vaqti kelishilgan chegarada (QA 23) |
| Contract | Javob OpenAPI/pact bilan mos; eski mobil versiyalar buzilmaydi |
14. Amaliy mashqlar {#mashqlar}
Mashq 1: DemoBozor promo-kod endpoint'i uchun negative testlar
Xayoliy POST /api/v1/orders body'sida ixtiyoriy promoCode maydoni bor. Qoidalar: 6–12 belgi, A–Z va 0–9, bitta buyurtmaga bitta, minimal summa, muddat, har foydalanuvchi bir marta. Kamida 10 ta negative/chegaraviy test yozing (body'dagi qiymat va kutilgan natija).
<details> <summary>💡 Javobni ko'rish</summary>
| # | promoCode / holat | Kutilgan |
|---|---|---|
| 1 | "ABC12" (5 belgi) | 422, format xatosi |
| 2 | "ABC123" (6) | ✅ qo'llanadi (agar kod mavjud va amal qilsa) |
| 3 | "ABCDEFGH1234" (12) | ✅ |
| 4 | "ABCDEFGH12345" (13) | 422 |
| 5 | "abc123" | 422 (yoki hujjatda "katta harfga o'tkaziladi" deyilgan bo'lsa — aynan shu xatti-harakat) |
| 6 | "ABC 123", "ABC-123" | 422 |
| 7 | null va maydon yo'q | ✅ promo'siz buyurtma |
| 8 | "" | 422 yoki promo'siz — hujjatga ko'ra, lekin 500 emas |
| 9 | Muddati o'tgan kod | 422, aniq xabar ("muddati tugagan") |
| 10 | Minimal summadan kam savatcha | 422, "minimal summa ..." |
| 11 | Bir foydalanuvchi ikkinchi marta | 409 yoki 422 |
| 12 | Ikki parallel buyurtmada bir xil bir martalik kod | Faqat bittasi muvaffaqiyatli |
| 13 | "promoCode": ["ABC123", "XYZ789"] (massiv) | 422 — bitta buyurtmaga bitta kod |
| 14 | Mavjud kod + ataylab "discount": 100 maydoni | Chegirma faqat serverda hisoblanadi |
</details>
Mashq 2: Topilmalarni tasniflang
Restful-booker kuzatuvlarini bug / hujjatga mos, lekin odatga zid / to'g'ri deb tasniflang va bug'larga jiddiylik bering: (a) DELETE → 201; (b) totalprice: 450.75 → 450; (c) buzilgan JSON → 400; (d) mavjud bo'lmagan ID'ga DELETE → 405; (e) "isAdmin": true e'tiborsiz qoldirildi; (f) GET /booking?checkin=2026-13-99 → 500.
<details> <summary>💡 Javobni ko'rish</summary>
| Tasnif | Izoh | |
|---|---|---|
| a | Hujjatga mos, odatga zid | API dizayni masalasi, past ustuvorlik |
| b | Bug, Major | Pul summasi jimgina o'zgaradi — ma'lumot buzilishi |
| c | To'g'ri | Kutilgan xatti-harakat |
| d | Bug, Minor | 404 kutiladi; 405 uchun Allow header'i ham yo'q |
| e | To'g'ri | Mass assignment'ga qarshi to'g'ri xatti-harakat (yaxshi belgi) |
| f | Bug, Major | Foydalanuvchi kiritgan filtr serverni yiqitadi; 400 kutiladi |
</details>
Mashq 3: Toolshop mahsuloti uchun JSON Schema
GET https://api.practicesoftwaretesting.com/products?page=1 javobidagi bitta mahsulot uchun sxema yozing: id va name — bo'sh bo'lmagan string, price — musbat son, in_stock — boolean, category va brand — id, name maydonli obyektlar. So'ng barcha sahifalardagi mahsulotlarni tekshiring.
<details> <summary>💡 Javobni ko'rish</summary>
// validate-products.mjs — Toolshop mahsulotlar ro'yxatini sxema bilan tekshirish
import Ajv2020 from "ajv/dist/2020.js";
const productSchema = {
type: "object",
required: ["id", "name", "price", "in_stock", "category", "brand"],
properties: {
id: { type: "string", minLength: 1 },
name: { type: "string", minLength: 1, maxLength: 120 },
price: { type: "number", exclusiveMinimum: 0 },
in_stock: { type: "boolean" },
is_rental: { type: "boolean" },
category: {
type: "object",
required: ["id", "name"],
properties: { id: { type: "string" }, name: { type: "string" } },
},
brand: {
type: "object",
required: ["id", "name"],
properties: { id: { type: "string" }, name: { type: "string" } },
},
},
};
const pageSchema = {
type: "object",
required: ["current_page", "data", "last_page", "per_page", "total"],
properties: {
current_page: { type: "integer", minimum: 1 },
per_page: { type: "integer", minimum: 1 },
total: { type: "integer", minimum: 0 },
data: { type: "array", items: { $ref: "#/$defs/product" } },
},
$defs: { product: productSchema },
};
const ajv = new Ajv2020({ allErrors: true });
const validate = ajv.compile(pageSchema);
let checked = 0;
for (let page = 1; page <= 6; page++) {
const body = await fetch(
`https://api.practicesoftwaretesting.com/products?page=${page}`,
).then((r) => r.json());
checked += body.data.length;
if (!validate(body)) {
console.log(
`❌ ${page}-sahifa:`,
validate.errors.map((e) => `${e.instancePath} ${e.message}`),
);
}
}
console.log(`Tekshirilgan mahsulotlar: ${checked}`);
2026-yil oktabrda natija: Tekshirilgan mahsulotlar: 50, sxema xatolari yo'q. Keyingi qadam: sxemani OpenAPI hujjatidagi components.schemas bilan solishtiring — farq bo'lsa, bu ham topilma.
</details>
Mashq 4: Avtorizatsiya matritsasi
DemoBozor'ning GET /api/v1/orders/{id} va POST /api/v1/orders/{id}/cancel endpoint'lari uchun test matritsasi tuzing: mehmon, buyurtma egasi, boshqa xaridor, sotuvchi, admin, muddati o'tgan token. cancel uchun holat qoidalarini ham hisobga oling.
<details> <summary>💡 Javobni ko'rish</summary>
| Kim | GET /orders/{id} | POST /orders/{id}/cancel |
|---|---|---|
| Mehmon (token yo'q) | 401 | 401 |
| Muddati o'tgan token | 401 | 401 |
| Buyurtma egasi | 200 | CREATED/PENDING_PAYMENT/PAID/PACKING da 200 (PAID'da pul qaytarish boshlanadi); SHIPPED/DELIVERED da 409/422 |
| Boshqa xaridor | 403 yoki 404 (ID mavjudligini oshkor qilmaslik uchun 404 afzal) | 403/404, buyurtma holati o'zgarmaydi |
| Sotuvchi | Talabga ko'ra (faqat o'z mahsulotlari qismi) | 403 |
| Admin | 200 | Talabga ko'ra, audit log yoziladi |
Qo'shimcha: har bir rad etilgan urinishdan keyin GET bilan buyurtma holati o'zgarmaganini tekshiring (yon ta'sir!).
</details>
Mashq 5: GraphQL'da "yashil" yolg'on
Nega GraphQL API uchun faqat pm.response.to.have.status(200) testi yetarli emas? Countries API misolida qaysi so'rovlar 200 qaytarib, aslida muammoli? Ularni ushlaydigan testni yozing.
<details> <summary>💡 Javobni ko'rish</summary>
Countries API'da: mavjud bo'lmagan maydon → 200 + errors; mavjud bo'lmagan davlat kodi → 200 + "country": null. Ikkalasi ham faqat status bo'yicha "yashil".
const json = pm.response.json();
pm.test("GraphQL xatosi yo'q", () => {
pm.expect(json.errors, JSON.stringify(json.errors)).to.be.undefined;
});
pm.test("Davlat topildi", () => {
// .to.exist — null ham, undefined ham bo'lmasligi kerak
pm.expect(json.data && json.data.country, "data.country").to.exist;
});
</details>
Mashq 6: Sahifalash test rejasi
Toolshop'da GET /products uchun total: 50, per_page: 9. Har sahifada nechta element bo'lishi kerak? Kamida 6 ta test case yozing (kutilgan natija bilan).
<details> <summary>💡 Javobni ko'rish</summary>
ceil(50 / 9) = 6 sahifa: 1–5-sahifalarda 9 tadan (45 ta), 6-sahifada 5 ta (46–50), 7-sahifa bo'sh.
| # | So'rov | Kutilgan |
|---|---|---|
| 1 | page=1 | 9 element, from=1, to=9 |
| 2 | page=6 | 5 element, from=46, to=50 |
| 3 | page=7 | data: [], 200 (2026-yil oktabrda shunday) |
| 4 | Barcha sahifalar ID'lari | 50 ta noyob ID, dublikat yo'q |
| 5 | page=0, page=-1, page=abc | Hujjatlangan xatti-harakat; amalda jimgina 1-sahifa — talab bilan solishtiring |
| 6 | sort=price,asc bilan 1→6 sahifalar | Barcha 50 ta narx o'sish tartibida, sahifa chegaralarida ham (N-sahifaning oxirgisi ≤ N+1-sahifaning birinchisi) — 2026-yil oktabrda shunday |
| 7 | sort=noto'g'ri,qiymat | 400 kutiladi; amalda 500 — bug |
</details>
Xulosa {#xulosa}
- "Status 200" — testning boshlanishi, oxiri emas: sxema, qiymatlar, biznes qoidalar va yon ta'sirlarni ham tekshiring.
- Har maydon uchun mavjudlik, tip, chegara, format, Unicode va "server hal qiladigan" qiymatlar (narx, rol) — tizimli negative test manbai.
- Eng xavfli API bug'lari jim bo'ladi:
"abc"→null,450.75→450, yaroqsiz sana →"0NaN-aN-aN". Ularni sxema va qiymat tekshiruvlari ushlaydi. - JSON Schema bitta testda bir nechta bug'ni ushlaydi; Postman'da
$schemani yozmang, Node'da Ajv 2020 bilan draft 2020-12 ishlating. 401= autentifikatsiya,403= avtorizatsiya; rollar matritsasi va IDOR/BOLA testlari majburiy.- Mock'lar tezlik beradi, contract testing esa mock va haqiqat ajralib ketmasligini kafolatlaydi.
- GraphQL'da xato ko'pincha
200ichida keladi —errorsmassivini tekshiring.
Keyingi dars: QA 12: SQL va ma'lumotlar bazasi — QA uchun SELECT, JOIN, GROUP BY va data tekshiruvi
Manbalar {#manbalar}
- RFC 9110 — HTTP Semantics
- RFC 9457 — Problem Details for HTTP APIs
- MDN — 422 Unprocessable Content
- MDN — 429 Too Many Requests
- MDN — Retry-After
- MDN — 405 Method Not Allowed
- MDN — WWW-Authenticate
- JSON Schema — Understanding JSON Schema
- JSON Schema — Draft 2020-12
- JSON Schema — type keyword
- Ajv JSON schema validator
- Ajv — JSON Schema drafts support
- Postman Docs — Test script examples
- Postman Docs — Set up mock servers
- Postman Docs — WebSocket requests
- Postman Docs — gRPC client
- OWASP API Security Top 10 (2023)
- OWASP — API1:2023 Broken Object Level Authorization
- OWASP — API3:2023 Broken Object Property Level Authorization
- OWASP — API4:2023 Unrestricted Resource Consumption
- Pact — How Pact works
- Pact — What is Pact good for?
- OpenAPI Specification (latest)
- Mockoon va Mockoon CLI
- WireMock — Documentation
- Proxyman — Map Local
- Playwright — Mock APIs
- GraphQL — Learn
- GraphQL Specification (October 2021) — Errors
- GraphQL over HTTP (draft)
- Countries GraphQL API — GitHub
- MDN — WebSockets API
- MDN — Server-sent events
- gRPC va gRPC status codes
- Restful-booker API hujjati
- Toolshop (Practice Software Testing) — GitHub
- Toolshop API hujjati