Azimjon Abdurasulov

QA 29: Amaliyot — Capstone loyiha va 30 ta topshiriq (Zero to Hero Challenge)

🧪 QA Engineer — Zero to Hero

QA 29: Amaliyot — Capstone loyiha va 30 ta topshiriq (Zero to Hero Challenge)

Holat: 2026-yil oktabr. Kursning yakuniy amaliy darsi: real amaliyot ilovasi (Toolshop) ustida 3 haftalik capstone loyiha va butun kursni qamraydigan 30 ta topshiriq. Kod yechimlari Playwright 1.64 (Chromium), Zod 4.6 va @axe-core/playwright 4.13 bilan, SQL yechimlari SQLite 3.51 da, Postman kolleksiyasi Newman 6.2 bilan ishga tushirib tekshirilgan; API misollari restful-booker va Toolshop'ning 2026-yil oktabrdagi haqiqiy javoblariga asoslangan.

Bu darsdan keyin siz: ishga topshirishda ko'rsatadigan to'liq QA portfolio'ga va 1–28-darslardagi har bir ko'nikmani amalda sinab ko'rgan tajribaga ega bo'lasiz.

  • real ilova uchun strategiyadan CI'gacha bo'lgan butun QA siklini o'zingiz bajarasiz;
  • 30 ta topshiriq orqali test dizayn, hujjatlar, API, SQL, mobil, avtomatlashtirish va "hero" ko'nikmalarini mustahkamlaysiz;
  • har bir yechimni tekshirilgan namuna bilan solishtirib, o'z xatolaringizni topasiz.

Mundarija

  1. Bu dars qanday ishlaydi
  2. Capstone loyiha: Toolshop'ni to'liq QA qilish
  3. Topshiriqlar xaritasi
  4. Test dizayn: 1–8
  5. Hujjatlar va bug'lar: 9–13
  6. Web, API va SQL: 14–19
  7. Mobil va Proxyman: 20–22
  8. Avtomatlashtirish: 23–27
  9. Hero darajasi: 28–30
  10. Zero → Hero: bosib o'tgan yo'lingiz
  11. Xulosa
  12. Manbalar

1. Bu dars qanday ishlaydi {#qanday}

Dars ikki qismdan iborat:

  1. Capstone loyiha — 2–3 haftalik katta ish, natijasi GitHub'dagi portfolio (QA 28'da nega muhimligini ko'rdik);
  2. 30 ta topshiriq — har biri 15 daqiqadan 2 soatgacha; capstone'dan oldin "isinish" yoki keyin takrorlash uchun.
BelgiDarajaTaxminiy vaqt
🟢Oson15–30 daqiqa
🟡O'rta30–60 daqiqa
🔴Qiyin1–2 soat

Qoidalar:

  • Avval o'zingiz yeching, keyin yechimni oching. Yechim — to'g'ri variantlardan biri, yagona to'g'ri javob emas.
  • Kod yechimlari biz tekshirgan muhitda ishlaydi: Node.js 24, @playwright/test 1.64.0 (Chromium), zod 4.6.5, @axe-core/playwright 4.13.0, newman 6.2.3, SQLite 3.51. Boshqa versiyada kichik farqlar bo'lishi mumkin.
  • Amaliyot saytlari — umumiy ommaviy resurs. Ularga yuklama (load) testi, xavfsizlik skanerlari yoki yuzlab akkaunt yaratish bilan zarar yetkazmang.
  • DemoBozor — kursdagi xayoliy mahsulot; uning qoidalari (QA 5 va boshqa darslarda) topshiriqlarda ham amal qiladi.

2. Capstone loyiha: Toolshop'ni to'liq QA qilish {#capstone}

Capstone: Toolshop'ni 3 haftada to'liq QA qilish — haftalar va natijalar

2.1. Nega aynan Toolshop

Practice Software Testing — "Toolshop" — testlashni o'rganish uchun maxsus yaratilgan ochiq loyiha: Angular'da yozilgan do'kon interfeysi, Laravel'dagi REST API va Swagger hujjati. Eng qimmatli tomoni — ataylab bug'lar qo'shilgan versiyasi bor: haqiqiy bug hunting mashqi uchun ideal.

NimaManzil
UI (asosiy, v5)https://practicesoftwaretesting.com
UI (ataylab bug'li)https://with-bugs.practicesoftwaretesting.com
APIhttps://api.practicesoftwaretesting.com
Swagger hujjatihttps://api.practicesoftwaretesting.com/api/documentation
API (bug'li versiya)https://api-with-bugs.practicesoftwaretesting.com
Manba kodhttps://github.com/testsmith-io/practice-software-testing

Demo akkauntlar (loyiha README'sidan; customer va admin login'lari API orqali 2026-yil oktabrda tekshirildi):

RolEmailParol
adminadmin@practicesoftwaretesting.comwelcome01
customercustomer@practicesoftwaretesting.comwelcome01
customercustomer2@practicesoftwaretesting.comwelcome01

Nimalarni testlash mumkin: katalog (kategoriyalar, brendlar, eco-friendly filtri, saralash, qidiruv), mahsulot sahifasi, savatcha, checkout, kirish/ro'yxatdan o'tish/parolni tiklash, shaxsiy kabinet, aloqa formasi, ijara (rentals) bo'limi; v5'da 7 tilga o'tish (DE, EL, EN, ES, FR, NL, TR).

Texnik faktlar (2026-yil oktabrda tekshirilgan):

  • UI elementlarida data-test atributlari bor (email, password, login-submit, search-query, sort, product-name, product-price ...) → Playwright'da testIdAttribute: 'data-test';
  • v5 oddiy yo'llardan foydalanadi (/auth/login, /category/hand-tools), bug'li versiya esa hash yo'llardan (/#/auth/login);
  • POST /users/login → { "access_token": "..." }; GET /products?page=1 → sahifalangan javob (current_page, data, per_page, total, last_page).

💡 Maslahat: Soddaroq yo'l kerak bo'lsa — capstone'ni saucedemo + restful-booker juftligida bajaring. QA 18–QA 21dagi kod deyarli o'zgarishsiz ishlaydi. Lekin Toolshop real mahsulotga yaqinroq va bug'li versiyasi bug report'lar uchun haqiqiy material beradi.

2.2. Deliverable'lar va ball taqsimoti

#DeliverableFormat / joyiDarslarBall
11 sahifali test strategiyadocs/test-strategy.mdQA 275
2Risk matritsasi (kamida 8 funksiya)docs/risk-matrix.mdQA 275
3Smoke va regression checklistdocs/checklist.mdQA 75
430 ta test case (EP, BVA, decision table, state)docs/test-cases.csvQA 5–715
5Bug'li versiyadan 10 ta bug reportdocs/bugs/BUG-001.md ...QA 815
6API kolleksiya (Postman yoki Bruno) + newman runpostman/ yoki bruno/QA 10–1110
7Playwright framework: POM + fixtures + UI testlarpages/, fixtures/, tests/ui/QA 18–1915
8API testlar (Zod sxemalari bilan)tests/api/, schemas/QA 2010
9a11y (axe) va visual testtests/a11y/, tests/visual/QA 255
10GitHub Actions CI + HTML report artifact.github/workflows/QA 2110
11README + 2–3 daqiqalik demo videoREADME.mdQA 285
Jami100

2.3. Repo tuzilmasi

toolshop-qa-portfolio/
├── README.md
├── .env.example               # BASE_URL, API_BASE_URL, TOOLSHOP_EMAIL, TOOLSHOP_PASSWORD
├── docs/
│   ├── test-strategy.md
│   ├── risk-matrix.md
│   ├── checklist.md
│   ├── test-cases.csv
│   ├── exploratory-sessions.md
│   └── bugs/                  # BUG-001.md ... BUG-010.md + skrinshotlar
├── postman/                   # yoki bruno/
├── pages/                     # LoginPage.ts, CatalogPage.ts, ProductPage.ts, CartPage.ts
├── fixtures/test.ts
├── schemas/product.ts         # Zod sxemalari
├── tests/
│   ├── ui/
│   ├── api/
│   ├── a11y/
│   └── visual/
├── playwright.config.ts
├── package.json
└── .github/workflows/playwright.yml

2.4. Boshlang'ich kod (tekshirilgan)

playwright.config.ts:

import { defineConfig, devices } from "@playwright/test";

export default defineConfig({
  testDir: "./tests",
  fullyParallel: true,
  retries: process.env.CI ? 1 : 0,
  reporter: [["list"], ["html", { open: "never" }]],
  use: {
    baseURL: process.env.BASE_URL ?? "https://practicesoftwaretesting.com",
    testIdAttribute: "data-test",
    trace: "on-first-retry",
  },
  projects: [{ name: "chromium", use: { ...devices["Desktop Chrome"] } }],
});

Birinchi UI testi — tests/ui/login.spec.ts:

import { test, expect } from "@playwright/test";

test('customer tizimga kiradi va "My account" sahifasini ko\'radi @smoke', async ({ page }) => {
  await page.goto("/auth/login");
  await page
    .getByTestId("email")
    .fill(process.env.TOOLSHOP_EMAIL ?? "customer@practicesoftwaretesting.com");
  await page.getByTestId("password").fill(process.env.TOOLSHOP_PASSWORD ?? "welcome01");
  await page.getByTestId("login-submit").click();

  await expect(page).toHaveURL(/\/account$/);
  await expect(page.getByTestId("page-title")).toHaveText("My account");
});

Birinchi API testlari — tests/api/products.spec.ts:

import { test, expect } from "@playwright/test";
import { z } from "zod";

test.use({
  baseURL: process.env.API_BASE_URL ?? "https://api.practicesoftwaretesting.com",
});

const ProductPage = z.object({
  current_page: z.number(),
  per_page: z.number(),
  total: z.number(),
  last_page: z.number(),
  data: z.array(
    z.object({
      id: z.string(),
      name: z.string(),
      price: z.number(),
      in_stock: z.boolean(),
    }),
  ),
});

test("API: login token qaytaradi", async ({ request }) => {
  const res = await request.post("/users/login", {
    data: {
      email: process.env.TOOLSHOP_EMAIL ?? "customer@practicesoftwaretesting.com",
      password: process.env.TOOLSHOP_PASSWORD ?? "welcome01",
    },
  });
  expect(res.status()).toBe(200);
  const body = await res.json();
  expect(typeof body.access_token).toBe("string");
});

test("API: mahsulotlar sahifalanadi va sxemaga mos", async ({ request }) => {
  const res = await request.get("/products?page=1");
  expect(res.ok()).toBeTruthy();
  const page1 = ProductPage.parse(await res.json());
  expect(page1.data.length).toBeLessThanOrEqual(page1.per_page);
  expect(page1.last_page).toBe(Math.ceil(page1.total / page1.per_page));
});

Bu uchta test 2026-yil oktabrda Chromium'da o'tdi. Login ma'lumotlari koddan emas, muhit o'zgaruvchilaridan olinadi (TOOLSHOP_EMAIL, TOOLSHOP_PASSWORD, BASE_URL, API_BASE_URL); fallback qiymatlar faqat ommaviy demo akkaunt uchun. .env faylini o'qish uchun QA 19dagi kabi dotenv ulang va o'zgaruvchilarni prefiks bilan nomlang (USERNAME kabi tizim nomlaridan qoching). Shu yerdan boshlab QA 19'dagi kabi POM va fixture'larga o'ting.

💡 Maslahat: Network mocking uchun tayyor g'oya: QA 19da mahsulotlar API'si 500 qaytarganda Toolshop interfeysi foydalanuvchiga hech qanday xato xabarini ko'rsatmasligi aniqlangan. Shu holat uchun page.route testi va bug report — capstone'ga kuchli qo'shimcha.

API qismi uchun tayyor g'oyalar (2026-yil 9-oktabrda curl bilan tekshirilgan):

So'rovNatijaNimani ko'rsatadi
GET /users token'siz401Autentifikatsiya ishlaydi
GET /users customer token bilan403Avtorizatsiya: oddiy foydalanuvchi admin ro'yxatini ko'rmaydi
GET /users/me customer token bilan200O'z profiliga ruxsat bor
GET /products?sort=hacker,up500Noto'g'ri parametr validatsiya qilinmagan — 400 kutilardi; bug report uchun material

2.5. 3 haftalik reja

HaftaKunlarNima qilasiz
11–2Ilovani o'rganish (har bir sahifa, rollar, API Swagger), savollar ro'yxati
13–4Test strategiya va risk matritsasi
15–7Checklist, 30 ta test case, RTM
28–9v5 build'da test case'larni bajarish, natijalarni yozish
210–12Bug'li build'da bug hunting: 2 ta 60 daqiqalik exploratory sessiya, 10 ta bug report
213–14API kolleksiya: login → token → mahsulotlar → savatcha; negative testlar; newman
315–17Playwright: config, POM, fixtures, 10–15 ta UI test
318–19API testlar (Zod), a11y va visual test
320–21GitHub Actions, README, demo video, yakuniy tekshiruv

2.6. Baholash rubrikasi

SohaA'loQayta ishlash kerak
Strategiya va riskRisklar asosli, test chuqurligi risk bilan bog'langanUmumiy gaplar, risk va test o'rtasida bog'liqlik yo'q
Test case'larTexnikalar ko'rinadi (chegaralar, kombinatsiyalar), kutilgan natija aniq"Ishlashi kerak" kabi kutilgan natijalar, faqat positive
Bug report'larHar biri qayta hosil qilinadi, bitta bug — bitta report, dalil borBir report'da bir nechta bug, qadamlar yo'q
APIChaining, assertion'lar, negative holatlarFaqat "status 200" tekshiruvi
AvtomatlashtirishPOM, mustaqil testlar, barqaror locator'lar, sleep yo'qwaitForTimeout, testlar bir-biriga bog'liq
CI va hisobotPR'da ishlaydi, report artifact, yashilCI yo'q yoki doimiy qizil
README1 daqiqada tushuniladi, natijalar va cheklovlar halol yozilganFaqat "npm test"

⚠️ Diqqat: Toolshop — ko'pchilik o'quvchilar foydalanadigan ommaviy sayt. Ro'yxatdan o'tishni testlasangiz, o'rtacha miqdorda va unikal emaillar bilan qiling; yuklama testi va xavfsizlik skanerlarini ishga tushirmang. Bug'li versiyada topilgan bug'larni portfolio'ingizda hujjatlashtiring.


3. Topshiriqlar xaritasi {#mashqlar}

#TopshiriqDarajaDarslar
01SMS kod uchun Equivalence Partitioning🟢QA 5
02Savatcha soni uchun 2 va 3 qiymatli BVA🟢QA 5
03Bepul yetkazib berish chegarasi🟢QA 2, 5
04Chegirmalar decision table🟡QA 5
05Buyurtma holatlari: state transition🟡QA 6
06Pairwise: 54 kombinatsiyadan 9 ta test🟡QA 6
07Muddatli to'lov: EP + BVA kombinatsiyasi🔴QA 5
08Exploratory charter va sessiya hisoboti🟡QA 6
09OTP login uchun 5 ta test case🟢QA 7
10Yomon test case'ni tuzatish🟢QA 7
11Toolshop'dagi real bug uchun bug report🟡QA 8
128 ta bug: severity va priority🟡QA 8
13Mini RTM va qamrov🟡QA 7
14DevTools: bug kimniki?🟢QA 9
15curl bilan booking yaratish va o'qish🟢QA 9–10
16API negative va authZ testlari🟡QA 11, 24
17Postman: token chaining🟡QA 10
18SQL: buyurtmalar yaxlitligi🟡QA 12
19SQL: to'lovlar va eng ko'p daromad🔴QA 12
20Checkout uchun mobil interruption checklisti🟢QA 14
21Proxyman: har stsenariyga to'g'ri asbob🟡QA 15
22Proxyman Map Local: chegaraviy javoblar🟡QA 15
23Playwright: login testlari🟢QA 18
24Playwright: savatcha badge🟡QA 18
25Playwright POM: checkout summasi🔴QA 19
26Playwright API + Zod🔴QA 20
27GitHub Actions: PR'da smoke🟡QA 21
28k6: thresholds va natijani o'qish🟡QA 23
29Accessibility: axe bilan skanerlash🔴QA 25
30AI yozgan test case'larni audit qilish🔴QA 26

4. Test dizayn: 1–8 {#test-dizayn}

Topshiriq 01: SMS kod uchun Equivalence Partitioning (🟢) {#t01}

DemoBozor qoidasi: SMS kod — 6 raqam, 120 soniya amal qiladi, 3 marta noto'g'ri kiritilsa raqam 15 daqiqaga bloklanadi. Kod kiritish maydoni uchun ekvivalent bo'laklarni (valid va invalid) aniqlang va har biriga vakil qiymat hamda kutilgan natija yozing.

<details> <summary>💡 Yechimni ko'rish</summary>

#Bo'lakVakil qiymatKutilgan natija
V16 raqam, to'g'ri, 120 s ichidaSMS'dagi kod, masalan 482915Kirish muvaffaqiyatli
V26 raqam, 0 bilan boshlanadi012345 (agar SMS'da shu bo'lsa)Qabul qilinadi — kod matn sifatida solishtiriladi
I16 raqam, noto'g'ri000000"Kod noto'g'ri", qolgan urinishlar soni kamayadi
I25 raqam48291Yuborib bo'lmaydi yoki format xatosi
I37 raqam48291507-raqam kiritilmaydi yoki format xatosi
I4Raqam bo'lmagan belgi48a915Harf qabul qilinmaydi
I5Bo'shTugma faol emas yoki "kodni kiriting"
I6To'g'ri kod, lekin muddati o'tganto'g'ri kod 121-soniyada"Kod muddati tugagan", yangi kod so'rash taklifi
I73 marta noto'g'ri kiritilgandan keyinto'g'ri kod 4-urinishdaRaqam bloklangan, to'g'ri kod ham qabul qilinmaydi

E'tibor bering:

  • V2 — klassik tuzoq: kod son sifatida saqlansa, 012345 → 12345 bo'lib qoladi va to'g'ri kod rad etiladi;
  • I6 va I7 — vaqt va holatga bog'liq bo'laklar; ularning chegaralarini (119/120/121 soniya; 2- va 3-xato) keyingi texnikalar — BVA va state transition bilan to'liq tekshiramiz.

</details>

Topshiriq 02: Savatcha soni uchun 2 va 3 qiymatli BVA (🟢) {#t02}

DemoBozor: savatchada bitta mahsulot soni 1–99 (butun son). Ekvivalent bo'laklarni yozing, keyin 2 qiymatli va 3 qiymatli BVA bo'yicha test qiymatlarini va kutilgan natijalarni chiqaring.

<details> <summary>💡 Yechimni ko'rish</summary>

Bo'laklar: ≤ 0 (invalid) · 1–99 (valid) · ≥ 100 (invalid). Har bir chegarada ikkita chegaraviy qiymat bor — chap bo'lakning oxiri va o'ng bo'lakning boshi: 0 | 1 va 99 | 100.

  • 2 qiymatli BVA (chegaraviy qiymat + qo'shni bo'lakdagi eng yaqin qiymat): 0, 1, 99, 100;
  • 3 qiymatli BVA (har bir chegaraviy qiymat + ikkala qo'shnisi): 0 → {−1, 0, 1}, 1 → {0, 1, 2}, 99 → {98, 99, 100}, 100 → {99, 100, 101}. Birlashtirilganda: −1, 0, 1, 2, 98, 99, 100, 101.
QiymatKutilgan natija
−1Rad etiladi: UI'da manfiy son kiritib bo'lmaydi, API'da 400/422
0Rad etiladi (yoki talab bo'yicha mahsulot savatchadan o'chiriladi — PO bilan aniqlang)
1Qabul qilinadi; "−" tugmasi faol emas yoki o'chirishni taklif qiladi
2Qabul qilinadi
98Qabul qilinadi
99Qabul qilinadi; "+" tugmasi faol emas
100Rad etiladi: UI'da kiritib bo'lmaydi, API'da 400/422
101Rad etiladi

⚠️ Diqqat: Ko'p manbalarda 3 qiymatli BVA faqat valid bo'lakning chegaralari atrofida olinadi ({0, 1, 2, 98, 99, 100}). Bu ISTQB ta'rifining keng tarqalgan noto'g'ri talqini: invalid bo'laklarning chegaraviy qiymatlari (0 va 100) ham chegaraviy qiymat hisoblanadi. Batafsil: QA 5.

Qo'shimcha: −1 va 100 ni API orqali ham yuboring (POST /api/v1/cart/items — xayoliy endpoint) — UI cheklovi server cheklovi emas.

</details>

Topshiriq 03: Bepul yetkazib berish chegarasi (🟢) {#t03}

Qoida: mahsulotlar summasi ≥ 300 000 so'm bo'lsa yetkazib berish bepul, aks holda 20 000 so'm. Premium a'zolar uchun har doim bepul. Chegaraviy test qiymatlarini yozing. Qaysi qiymat QA 2dagi > vs >= defektini ushlaydi? Qanday savollarni PO'ga berasiz?

<details> <summary>💡 Yechimni ko'rish</summary>

Bo'laklar: < 300 000 (yetkazish pullik) va ≥ 300 000 (bepul); chegara 299 999 | 300 000.

Mahsulotlar summasiPremiumKutilgan yetkazish narxiQaysi BVA
299 998Yo'q20 0003 qiymatli
299 999Yo'q20 0002 va 3 qiymatli
300 000Yo'q02 va 3 qiymatli
300 001Yo'q03 qiymatli
299 999Ha0Premium istisnosi
  • > vs >= defektini aynan 300 000 ushlaydi: noto'g'ri kodda 300 000 so'mlik buyurtmaga 20 000 qo'shiladi. Bu — QA 8dagi deliveryFee() bug'i (DB-210).
  • Amaliy nuans: agar narxlar faqat mingga karrali bo'lsa, real qo'shnilar 299 000 va 301 000 bo'ladi. BVA'da qo'shni qiymat — ma'lumotning eng kichik qadami.

PO'ga savollar:

  1. Chegirma qo'llanib, summa 300 000 dan pastga tushsa — yetkazish pullikmi? (Qoida "mahsulotlar summasi" deydi — chegirmadan oldingi summa, lekin tasdiqlatish kerak.)
  2. Savatchadan mahsulot o'chirilib, summa chegaradan tushsa, narx darhol qayta hisoblanadimi?
  3. Viloyatlar uchun ham shu qoidami?

</details>

Topshiriq 04: Chegirmalar decision table (🟡) {#t04}

DemoBozor qoidalari: yangi mijoz (birinchi buyurtma) — 10%; yaroqli BAHOR15 promo-kodi — 15% (minimal summa 200 000 so'm); chegirmalar qo'shilmaydi — kattasi qo'llanadi; Premium a'zo — har doim bepul yetkazib berish. Mahsulotlar summasi 250 000 so'm deb oling (promo minimalidan yuqori, bepul yetkazish chegarasidan past). To'liq decision table tuzing (chegirma, yetkazish, jami), keyin uni qisqartiring.

<details> <summary>💡 Yechimni ko'rish</summary>

To'liq jadval (2³ = 8 qoida):

Shart / natijaR1R2R3R4R5R6R7R8
Yangi mijozHaHaHaHaYo'qYo'qYo'qYo'q
BAHOR15 yaroqliHaHaYo'qYo'qHaHaYo'qYo'q
PremiumHaYo'qHaYo'qHaYo'qHaYo'q
Chegirma15% (37 500)15% (37 500)10% (25 000)10% (25 000)15% (37 500)15% (37 500)00
Yetkazish020 000020 000020 000020 000
Jami212 500232 500225 000245 000212 500232 500250 000270 000

Qisqartirilgan jadval: promo-kod yaroqli bo'lsa, "yangi mijoz" sharti natijaga ta'sir qilmaydi (15% > 10%), shuning uchun R1+R5 va R2+R6 birlashadi:

Shart / natijaABCDEF
Yangi mijoz––HaHaYo'qYo'q
BAHOR15 yaroqliHaHaYo'qYo'qYo'qYo'q
PremiumHaYo'qHaYo'qHaYo'q
Chegirma15%15%10%10%00
Yetkazish020 000020 000020 000

8 o'rniga 6 ta test. Lekin ehtiyot bo'ling: qisqartirish haqiqiy foizlarga bog'liq. TEJA5 (5%) promo-kodi bilan yangi mijozning 10% i yutadi va R1/R5 natijalari farq qiladi — konfiguratsiyani tekshirib, kerak bo'lsa to'liq jadvalga qayting. Muddati o'tgan QISH10 yoki KUZ10 esa "promo-kod yaroqli = Yo'q" ustunlariga tushadi.

</details>

Topshiriq 05: Buyurtma holatlari — state transition (🟡) {#t05}

DemoBozor buyurtma holatlari: CREATED → PENDING_PAYMENT → PAID → PACKING → SHIPPED → DELIVERED; CANCELLED — CREATED, PENDING_PAYMENT, PAID (pul qaytariladi) va PACKING dan; RETURNED — DELIVERED dan 10 kun ichida; naqd to'lovda CREATED → PACKING.

  1. Barcha ruxsat etilgan o'tishlarni sanang.
  2. Barcha o'tishlarni qamraydigan minimal test yo'llarini (path) tuzing.
  3. Kamida 5 ta ruxsat etilmagan o'tishni yozing.

<details> <summary>💡 Yechimni ko'rish</summary>

1. Ruxsat etilgan o'tishlar — 11 ta (hodisa nomlari QA 6dagi state table bilan bir xil):

#DanGaHodisa
1CREATEDPENDING_PAYMENTE1 to'lovni boshlash [karta]
2PENDING_PAYMENTPAIDE3 to'lov o'tdi
3PAIDPACKINGE4 yig'ishni boshlash
4PACKINGSHIPPEDE5 kuryerga topshirish
5SHIPPEDDELIVEREDE6 yetkazildi
6DELIVEREDRETURNEDE8 qaytarish [≤ 10 kun]
7CREATEDCANCELLEDE7 bekor qilish
8PENDING_PAYMENTCANCELLEDE7 bekor qilish
9PAIDCANCELLEDE7 bekor qilish (pul qaytariladi)
10PACKINGCANCELLEDE7 bekor qilish
11CREATEDPACKINGE2 tasdiqlash [naqd]

8 holat × 8 hodisa = 64 katak; shundan faqat 11 tasi ruxsat etilgan o'tish, qolgan 53 tasi — "ruxsat etilmagan" kataklar, ularning eng xavflilarini alohida testlaymiz.

2. Barcha 11 o'tishni qamraydigan 5 ta yo'l:

Yo'lKetma-ketlikQamralgan o'tishlar
P1CREATED → PENDING_PAYMENT → PAID → PACKING → SHIPPED → DELIVERED → RETURNED1, 2, 3, 4, 5, 6
P2CREATED → CANCELLED7
P3CREATED → PENDING_PAYMENT → CANCELLED8
P4CREATED → PENDING_PAYMENT → PAID → CANCELLED (pul qaytgani tekshiriladi)9
P5CREATED → PACKING (naqd) → CANCELLED11, 10

3. Ruxsat etilmagan o'tishlar (kutilgan natija: rad etiladi, holat o'zgarmaydi, tushunarli xabar):

  • SHIPPED → CANCELLED
  • DELIVERED → CANCELLED
  • CANCELLED → PAID
  • PENDING_PAYMENT → SHIPPED (bosqichdan sakrash)
  • RETURNED → DELIVERED
  • DELIVERED → RETURNED 11-kuni (guard sharti: chegarani BVA bilan — 10-kun ruxsat, 11-kun rad)

Ruxsat etilmagan o'tishlarni odatda API orqali testlash qulay — UI'da bunday tugma ko'rinmasligi mumkin, lekin server buni baribir tekshirishi shart.

</details>

Topshiriq 06: Pairwise — 54 kombinatsiyadan 9 ta test (🟡) {#t06}

Checkout'ni quyidagi parametrlar bilan testlash kerak:

  • Brauzer: Chrome, Safari, Firefox
  • Til: uz, ru, en
  • To'lov: Uzcard, Humo, Naqd
  • Qurilma: Desktop, Mobil

To'liq kombinatsiyalar soni nechta? Har bir juftlik kamida bir marta uchraydigan to'plam tuzing.

<details> <summary>💡 Yechimni ko'rish</summary>

To'liq: 3 × 3 × 3 × 2 = 54 kombinatsiya. Pairwise to'plam — 9 ta test (uchta 3-qiymatli parametr juftligi uchun kamida 3 × 3 = 9 qator kerak):

#BrauzerTilTo'lovQurilma
1ChromeuzUzcardDesktop
2ChromeruHumoMobil
3ChromeenNaqdMobil
4SafariuzHumoDesktop
5SafariruNaqdDesktop
6SafarienUzcardMobil
7FirefoxuzNaqdMobil
8FirefoxruUzcardMobil
9FirefoxenHumoDesktop

Bu to'plam L9 ortogonal massiviga asoslangan; barcha juftliklar qamralgani skript bilan tekshirildi (yetishmayotgan juftlik — 0). Amalda bunday jadvalni qo'lda emas, Microsoft PICT kabi vosita bilan yarating va cheklovlarni (masalan, "Safari faqat Apple qurilmalarida") model faylida yozing — QA 6.

</details>

Topshiriq 07: Muddatli to'lov — EP + BVA kombinatsiyasi (🔴) {#t07}

Qoida: muddatli (foizsiz) to'lov — yosh 18–65 (shu jumladan), buyurtma summasi 500 000 – 30 000 000 so'm, muddat 3, 6 yoki 12 oy. Minimal, lekin kuchli test to'plamini tuzing. Nega bitta testda bir nechta noto'g'ri qiymatni birlashtirmaslik kerak?

<details> <summary>💡 Yechimni ko'rish</summary>

#YoshSummaMuddatKutilganNimani tekshiradi
118500 0003RuxsatPastki chegaralar birga
26530 000 00012RuxsatYuqori chegaralar birga
34015 000 0006RuxsatO'rta (tipik) qiymatlar
4171 000 0006Rad: yoshYosh pastki chegaradan tashqari
5661 000 0006Rad: yoshYosh yuqori chegaradan tashqari
630499 9996Rad: summaSumma pastki chegaradan tashqari
73030 000 0016Rad: summaSumma yuqori chegaradan tashqari
8301 000 0009Rad: muddatRuxsat etilmagan muddat

Bu yerda 2 qiymatli BVA ishlatildi (17/18, 65/66, 499 999/500 000, 30 000 000/30 000 001). 3 qiymatli BVA har chegaraga yana qo'shni qiymatlarni qo'shadi — masalan, yosh uchun 16, 19, 64 va 67 (QA 5).

"Bir vaqtda bitta noto'g'ri qiymat" qoidasi: agar testda yosh ham, summa ham noto'g'ri bo'lsa va tizim rad etsa — qaysi tekshiruv ishlaganini bilmaysiz; bittasi buzilgan bo'lsa ham test "o'tadi" (defect masking).

Qo'shimcha nozik joylar:

  • Yosh tug'ilgan sanadan hisoblanadi: bugun 18 yoshga to'lgan va ertaga 66 ga to'ladigan (bugun hali 65) mijozlar — ikkalasi ham ruxsat;
  • "Bugun" qaysi vaqt zonasida? Asia/Tashkent (UTC+5) — server UTC'da ishlasa, tunda chegara siljishi mumkin;
  • Summa chegarasi chegirmadan oldingi yoki keyingi summaga qo'llanadimi — talabni aniqlashtiring.

</details>

Topshiriq 08: Exploratory charter va sessiya hisoboti (🟡) {#t08}

DemoBozor checkout'idagi promo-kod maydoni uchun 60 daqiqalik exploratory sessiya rejalang: charter yozing va kamida 10 ta g'oya ro'yxatini tuzing. Sessiya hisoboti qanday ko'rinishda bo'lishi kerak?

<details> <summary>💡 Yechimni ko'rish</summary>

Charter: Promo-kod maydonini checkout'da (Web, Chrome) turli formatdagi va holatdagi kodlar, ikki brauzer tab'i va sekin tarmoq bilan tekshirib, chegirma hisobidagi va qayta ishlatishdagi xatolarni topish.

G'oyalar:

  1. Kichik harflar: bahor15 (qoida: faqat katta harf — avtomatik o'zgartiriladimi yoki rad etiladimi?);
  2. Boshida/oxirida probel: " BAHOR15 ";
  3. Uzunlik chegaralari: 5, 6, 12, 13 belgi;
  4. Kirill harflari lotinga o'xshash: ВАНОR15 (В, А, Н, О — kirill) — ko'zga bir xil, lekin boshqa kod; eng "makkor" holatlardan biri;
  5. Muddati o'tgan kodlar (QISH10, KUZ10) va kelajakda boshlanadigan kod;
  6. BAHOR15ning minimal summasi chegarasida (200 000) va undan 1 so'm kam (199 999);
  7. Promo-kod + yangi mijoz chegirmasi birga: TEJA5 (5%) bilan yangi mijozning 10% i qo'llanishi kerak;
  8. Kod qo'llangandan keyin mahsulot o'chirilib, summa minimaldan tushsa — chegirma olib tashlanadimi?;
  9. Ikki tab'da bir vaqtda bitta kodni ishlatish (race condition);
  10. Sekin tarmoqda "Qo'llash" tugmasini ikki marta bosish;
  11. Kod qo'llanib, sahifa yangilansa yoki "orqaga" qaytilsa;
  12. Bir marta ishlatilgan kodni boshqa buyurtmada qayta ishlatish.

Sessiya hisoboti tuzilmasi (session-based test management uslubida):

Bo'limMazmuni
CharterYuqoridagi matn
Tester, sana, vaqtIsm, sana, 60 daqiqa (sozlashga ~10, testlashga ~45, hisobotga ~5)
MuhitStaging, build raqami, brauzer
Test eslatmalariNima qilindi, nima kuzatildi
Bug'larTopilgan bug'lar ticket raqamlari bilan
Savollar / muammolarTalabdagi noaniqliklar, bloklovchi muammolar
QamrovYuqoridagi g'oyalardan qaysilari tekshirildi, qaysilari keyingi sessiyaga

</details>


5. Hujjatlar va bug'lar: 9–13 {#hujjatlar}

Topshiriq 09: OTP login uchun 5 ta test case (🟢) {#t09}

DemoBozor mobil ilovasida telefon raqami va SMS kod bilan kirish uchun 5 ta test case yozing (ID, sarlavha, oldingi shartlar, qadamlar, test ma'lumotlari, kutilgan natija, ustuvorlik).

<details> <summary>💡 Yechimni ko'rish</summary>

IDSarlavhaOldingi shartlarQadamlarKutilgan natijaUstuvorlik
TC-AUTH-001To'g'ri SMS kod bilan kirishTest akkaunt +998 90 000 00 01, SMS keladi1) Raqamni kiriting 2) "Kod olish" 3) SMS'dagi 6 raqamni 120 s ichida kiritingBosh sahifa ochiladi, foydalanuvchi nomi ko'rinadiP0
TC-AUTH-002Noto'g'ri kod xato xabarini chiqaradiTC-001 dagi kabi1–2) Kod oling 3) 000000 kiriting"Kod noto'g'ri" xabari; qolgan urinishlar: 2; kirish yo'qP0
TC-AUTH-003Muddati o'tgan kod qabul qilinmaydiKod olingan1) 121 soniya kuting 2) To'g'ri kodni kiriting"Kod muddati tugagan", "Qayta yuborish" taklifi; kirish yo'qP1
TC-AUTH-0043 ta noto'g'ri urinishdan keyin raqam 15 daqiqaga bloklanadiKod olingan1) 3 marta noto'g'ri kod 2) To'g'ri kodni kiriting 3) 15 daqiqadan keyin qayta urining2-qadamda "15 daqiqaga bloklangan"; 3-qadamda yangi kod olish mumkinP0
TC-AUTH-005"Qayta yuborish" 60 soniyadan keyin faollashadiKod olingan1) Taymerni kuzating 2) 59-soniyada va 60-soniyadan keyin tugmani tekshiring59 s da tugma faol emas; 60 s dan keyin faol; yangi kod eskisini bekor qiladiP1

Test ma'lumotlari va muhit (staging, test raqamlari) test case'ning o'zida yoki test suite darajasida ko'rsatiladi. TC-005'dagi "yangi kod eskisini bekor qiladi" — talabda yo'q bo'lsa, PO'dan tasdiqlatiladigan taxmin.

</details>

Topshiriq 10: Yomon test case'ni tuzatish (🟢) {#t10}

Quyidagi test case'ning kamchiliklarini toping va uni qayta yozing:

TC1: Login'ni tekshirish
Qadamlar: Ilovaga kiring va hamma narsani tekshiring.
Kutilgan natija: Hammasi ishlaydi.

<details> <summary>💡 Yechimni ko'rish</summary>

Kamchiliklar: sarlavha nimani tekshirishini aytmaydi; bitta case'da "hamma narsa" (atomar emas); oldingi shartlar va test ma'lumotlari yo'q; qadamlar takrorlanmaydi; kutilgan natija o'lchab bo'lmaydigan ("ishlaydi"); talabga bog'lanmagan; ustuvorlik yo'q.

Qayta yozilgani (bir nechta case'ga bo'linadi; bittasi namuna):

MaydonQiymat
IDTC-AUTH-006
Sarlavha9 raqamdan kam telefon raqami bilan SMS kod so'rab bo'lmaydi
TalabREQ-AUTH-01 (telefon: +998 + 9 raqam)
Oldingi shartlarIlova o'rnatilgan, foydalanuvchi tizimdan chiqqan
Test ma'lumoti+998 90 123 45 6 (8 raqam)
Qadamlar1) Kirish ekranini oching 2) Raqamni kiriting 3) "Kod olish" tugmasini bosing
Kutilgan natijaTugma faol emas yoki "Raqamni to'liq kiriting" xabari; SMS yuborilmaydi; API'ga so'rov ketmaydi
Ustuvorlik / turP1 / Negative, funksional

</details>

Topshiriq 11: Toolshop'dagi real bug uchun bug report (🟡) {#t11}

https://with-bugs.practicesoftwaretesting.com ni oching. Saralash ro'yxatidan "Price (High - Low)" ni tanlang va natijani kuzating. Bu xatti-harakat uchun to'liq bug report yozing.

<details> <summary>💡 Yechimni ko'rish</summary>

Biz 2026-yil oktabrda kuzatgan natija: saralashdan keyin narxlar o'sish tartibida chiqdi ($4.92, $9.17, $11.14, $11.48, ...). Normal v5 build'da xuddi shu variant narxlarni kamayish tartibida ko'rsatadi ($89.55, $86.71, $80.19, ...).

ID: BUG-003
Sarlavha: [Katalog] "Price (High - Low)" saralash mahsulotlarni narx o'sishi bo'yicha ko'rsatadi

Muhit: https://with-bugs.practicesoftwaretesting.com (Toolshop v5.0 with bugs)
       Chrome for Testing 156 (Playwright 1.64), macOS; mehmon foydalanuvchi
Oldingi shartlar: yo'q

Qayta hosil qilish qadamlari:
1. Bosh sahifani oching.
2. "Sort" ro'yxatidan "Price (High - Low)" ni tanlang.
3. Birinchi qatordagi mahsulot narxlarini kuzating.

Kutilgan natija: mahsulotlar narx kamayishi bo'yicha (eng qimmati birinchi).
Haqiqiy natija:  mahsulotlar narx o'sishi bo'yicha ($4.92, $9.17, $11.14, $11.48, ...).

Takrorlanishi: 3/3
Severity: Major (funksiya teskari ishlaydi; workaround: "Low - High" ni tanlash)
Priority: P2
Komponent: Catalog / Sorting
Ilovalar: skrinshot (sort-high-low.png)

Qo'shimcha ma'lumot: DevTools'da "Price (High - Low)" option'ining qiymati "price,asc".
Label va qiymat almashib qolgan bo'lishi mumkin. Boshqa variantlar ("Name (A - Z)" — qiymati
"name,desc") alohida tekshirilib, alohida report qilinadi.

Nega bunday yozildi: sarlavha qayerda + nima formulasida (QA 8); bitta report — bitta bug; haqiqiy natijada aniq qiymatlar; ildiz sababi haqida taxmin "Qo'shimcha" bo'limida, faktlardan ajratilgan. Bu build'da boshqa bug'lar ham bor — ularni capstone uchun o'zingiz topasiz.

</details>

Topshiriq 12: 8 ta bug — severity va priority (🟡) {#t12}

Har bir DemoBozor bug'iga severity (Blocker/Critical/Major/Minor/Trivial) va priority (P0–P3) bering, qisqa asoslang:

  1. Android 14'da "To'lash" tugmasi bosilganda ilova yopilib qoladi (barcha foydalanuvchilar).
  2. Bosh sahifadagi logotip ostida "DemoBozr" deb yozilgan.
  3. Admin panelidagi oylik PDF hisobot eksporti crash bo'ladi (oyiga 2 marta ishlatiladi, CSV eksport ishlaydi).
  4. Aynan 300 000 so'mlik buyurtmaga yetkazish haqi olinadi.
  5. Sharh matni 1000 belgidan uzun bo'lsa server 500 qaytaradi (UI 1000 dan ortiq yozdirmaydi, faqat API orqali mumkin).
  6. Dark mode'da "Savatcha" tugmasi kontrasti juda past.
  7. Bitta promo-kodni ikki tab'da bir vaqtda ikki marta ishlatish mumkin.
  8. Rus tilida savatcha sahifasi sarlavhasi "Cart" bo'lib qolgan.

<details> <summary>💡 Yechimni ko'rish</summary>

#SeverityPriorityAsos
1BlockerP0Asosiy biznes oqimi barcha Android 14 foydalanuvchilari uchun to'xtagan
2TrivialP1Texnik ta'sir yo'q, lekin brend obro'si — har kim ko'radi
3MajorP3Funksiya buziladi, lekin kam ishlatiladi va workaround (CSV) bor
4MajorP1Pul bilan bog'liq, ko'p buyurtmaga ta'sir qiladi (QA 8dagi DB-210)
5MinorP2Server validatsiyasi yo'q (500 o'rniga 400/422 kerak); oddiy foydalanuvchiga ta'siri yo'q, lekin API sifati va xavfsizlik nuqtai nazaridan tuzatilishi kerak
6MinorP2A11y muammosi; ba'zi foydalanuvchilar uchun ishlatish qiyin (QA 25)
7CriticalP0–P1To'g'ridan-to'g'ri pul yo'qotish va suiiste'mol imkoniyati
8MinorP2–P3Lokalizatsiya xatosi, funksiya ishlaydi

±1 daraja farq normal — muhimi asoslash. Esda tuting: severity — texnik ta'sir, priority — biznes shoshilinchligi; ularni triage'da PO bilan birga yakunlaysiz.

</details>

Topshiriq 13: Mini RTM va qamrov (🟡) {#t13}

Talablar va test case'lar:

  • REQ-01: SMS kod 6 raqam, 120 soniya amal qiladi → TC-AUTH-001, TC-AUTH-003
  • REQ-02: 300 000 so'mdan yetkazish bepul → TC-DLV-001, TC-DLV-002
  • REQ-03: Promo-kod har foydalanuvchiga bir marta → TC-PRM-004
  • REQ-04: Savatchada soni 1–99 → TC-CRT-001 ... TC-CRT-006
  • REQ-05: Sharhni faqat DELIVERED buyurtma egasi yozadi → (yo'q)

Oxirgi run: TC-DLV-002 — Failed (BUG-012), TC-PRM-004 — Blocked (staging'da promo-kodlar yo'q), qolganlari — Passed. RTM tuzing, talablar qamrovini hisoblang va xulosa yozing.

<details> <summary>💡 Yechimni ko'rish</summary>

TalabTest case'larNatijaBug'larHolat
REQ-01TC-AUTH-001, TC-AUTH-003Passed, Passed—✅ Qamralgan, o'tdi
REQ-02TC-DLV-001, TC-DLV-002Passed, FailedBUG-012❌ Qamralgan, bug bor
REQ-03TC-PRM-004Blocked—⚠️ Qamralgan, bajarilmagan
REQ-04TC-CRT-001 ... 006Passed—✅ Qamralgan, o'tdi
REQ-05———❌ Qamrov yo'q
  • Talablar qamrovi (kamida 1 testi bor): 4 / 5 = 80%;
  • To'liq tasdiqlangan talablar: 2 / 5 (REQ-01, REQ-04).

Xulosa va harakatlar: REQ-05 uchun test case'lar yozish (DELIVERED egasi — ruxsat; boshqa holatdagi buyurtma egasi va begona foydalanuvchi — rad, API orqali ham); REQ-03 uchun staging'ga test promo-kodlari qo'shilishi kerak (bloklovchi muammoni DevOps/PO'ga ko'tarish); BUG-012 tuzatilgach TC-DLV-002 ni qayta testlash va regressiya.

</details>


6. Web, API va SQL: 14–19 {#web-api-sql}

Topshiriq 14: DevTools — bug kimniki? (🟢) {#t14}

Har bir holat uchun bug front-end'dami yoki back-end'dami aniqlang va bug report'ga nimani biriktirishni ayting:

  1. Katalog bo'sh ko'rinadi. Network: GET /api/v1/products → 200, javobda 24 ta mahsulot. Console'da TypeError: Cannot read properties of undefined (reading 'map').
  2. "Buyurtma berish" bosilganda xato oynasi. Network: POST /api/v1/orders → 500, javobda stack trace va SQL so'rovi ko'rinadi.
  3. Narx API'da 250000, UI'da "25 000 so'm".
  4. "Saqlash" tugmasi bosilganda hech narsa bo'lmaydi; Network'da so'rov yo'q; Console toza.

<details> <summary>💡 Yechimni ko'rish</summary>

#KimnikiAsosBiriktiriladi
1Front-endAPI to'g'ri ma'lumot qaytargan, JS xatosi render'ni buzganConsole xatosi (stack bilan), javob JSON'i
2Back-end (+ xavfsizlik)Server xatosi; stack trace va SQL'ning javobga chiqishi — alohida xavfsizlik bug'i (QA 24)So'rov body'si, javob, vaqt, request id
3Front-endMa'lumot to'g'ri, formatlashda xato (bir nol yo'qolgan)Javob qiymati va UI skrinshoti yonma-yon
4Front-end (ehtimol)So'rov umuman ketmagan: event handler ulanmagan yoki validatsiya jim to'xtatganVideo, qadamlar, Network bo'sh ekani

4-holatda jim ishlamaslik — UX bug'i ham: foydalanuvchi hech qanday xabar ko'rmaydi.

</details>

Topshiriq 15: curl bilan booking yaratish va o'qish (🟢) {#t15}

restful-booker'da curl bilan yangi booking yarating, uni ID bo'yicha o'qing va status kodlarini ko'rsating.

<details> <summary>💡 Yechimni ko'rish</summary>

# 1) Booking yaratish
curl -s -w "\nHTTP %{http_code}\n" -X POST https://restful-booker.herokuapp.com/booking \
  -H "Content-Type: application/json" \
  -H "Accept: application/json" \
  -d '{"firstname":"Aziz","lastname":"Karimov","totalprice":250,"depositpaid":true,"bookingdates":{"checkin":"2026-11-01","checkout":"2026-11-05"},"additionalneeds":"Breakfast"}'

# 2) Javobdagi bookingid ni qo'yib o'qish (masalan, 2142)
curl -s -w "\nHTTP %{http_code}\n" https://restful-booker.herokuapp.com/booking/2142 \
  -H "Accept: application/json"

2026-yil oktabrdagi haqiqiy javob (ID har safar boshqacha):

{
  "bookingid": 2142,
  "booking": {
    "firstname": "Aziz",
    "lastname": "Karimov",
    "totalprice": 250,
    "depositpaid": true,
    "bookingdates": { "checkin": "2026-11-01", "checkout": "2026-11-05" },
    "additionalneeds": "Breakfast"
  }
}

E'tibor bering: yaratish **200 OK** qaytaradi. REST konvensiyasida yangi resurs uchun odatda 201 Created kutiladi — bu farqni ham kuzatuv sifatida qayd qiling. GET esa 200 va booking obyektini qaytaradi.

</details>

Topshiriq 16: API negative va authZ testlari (🟡) {#t16}

restful-booker uchun kamida 6 ta negative/avtorizatsiya testini rejalashtiring, har biri uchun REST nuqtai nazaridan kutilgan natijani yozing. Keyin ularni curl bilan bajarib, haqiqiy natijani solishtiring. DemoBozor'da IDOR (BOLA) testini qanday qilgan bo'lardingiz?

<details> <summary>💡 Yechimni ko'rish</summary>

2026-yil 9-oktabrda bajarilgan natijalar:

#So'rovKutilgan (REST)HaqiqiyXulosa
1PUT /booking/{id} token'siz401 yoki 403403✅ Himoyalangan
2DELETE /booking/{id} noto'g'ri token (token=abc123)401 yoki 403403✅ Himoyalangan
3POST /booking faqat firstname bilan400 + xato tavsifi500 Internal Server Error🐞 Validatsiya yo'q
4POST /booking: totalprice=-5, checkout < checkin400 yoki 422200, booking saqlandi🐞 Biznes validatsiya yo'q
5POST /auth noto'g'ri parol bilan401200 va {"reason":"Bad credentials"}🐞 Noto'g'ri status kod
6DELETE /booking/{id} to'g'ri token bilan200 yoki 204201 Created🐞 Noto'g'ri status (ma'lum "quirk")
7O'chirilgan booking'ni GET404404✅
8O'chirilgan booking'ni yana DELETE (token bilan)404405 Method Not Allowed🐞 Noto'g'ri status kod

Negative so'rov namunasi (3-qator):

curl -s -w "\nHTTP %{http_code}\n" -X POST https://restful-booker.herokuapp.com/booking \
  -H "Content-Type: application/json" -H "Accept: application/json" \
  -d '{"firstname":"Aziz"}'

IDOR / BOLA — restful-booker'da bitta admin bor, shuning uchun "begona resurs" testini qilib bo'lmaydi. DemoBozor'da (xayoliy API) ikkita xaridor akkaunti kerak:

  1. A foydalanuvchi o'z buyurtmasini oladi: GET /api/v1/orders/1001 (A token) → 200;
  2. A foydalanuvchi B'ning buyurtmasini so'raydi: GET /api/v1/orders/1002 (A token) → **403 yoki 404** kutiladi; 200 va B'ning ma'lumoti — kritik xavfsizlik bug'i;
  3. Xuddi shuni POST /api/v1/orders/1002/cancel uchun ham — o'qish himoyalangan, lekin o'zgartirish himoyalanmagan holatlar uchraydi.

Batafsil: QA 11, QA 24. Faqat o'z test muhitingizda!

</details>

Topshiriq 17: Postman — token chaining (🟡) {#t17}

Postman kolleksiyasi yarating: (1) POST /auth → token'ni o'zgaruvchiga saqlash; (2) POST /booking → bookingIdni saqlash; (3) token bilan DELETE; (4) o'chirilgan booking GET → 404. Har so'rovga Post-response testlari yozing va kolleksiyani Newman bilan ishga tushiring.

<details> <summary>💡 Yechimni ko'rish</summary>

Kolleksiya o'zgaruvchilari: baseUrl = https://restful-booker.herokuapp.com, token, bookingId.

1. Auth — Post-response (Tests) skripti:

pm.test("Status 200", () => pm.response.to.have.status(200));
const body = pm.response.json();
pm.test("Token bor va bo'sh emas", () => {
  pm.expect(body.token).to.be.a("string").and.not.empty;
});
pm.collectionVariables.set("token", body.token);

2. Booking yaratish (POST {{baseUrl}}/booking, Accept: application/json):

pm.test("Status 200", () => pm.response.to.have.status(200));
const body = pm.response.json();
pm.test("bookingid son", () => pm.expect(body.bookingid).to.be.a("number"));
pm.test("Ism saqlangan", () =>
  pm.expect(body.booking.firstname).to.eql("Aziz"),
);
pm.test("Javob 2 soniyadan tez", () =>
  pm.expect(pm.response.responseTime).to.be.below(2000),
);
pm.collectionVariables.set("bookingId", body.bookingid);

3. O'chirish (DELETE {{baseUrl}}/booking/{{bookingId}}, header Cookie: token={{token}}):

pm.test("Status 201 (restful-booker quirk)", () =>
  pm.response.to.have.status(201),
);

4. Tekshirish (GET {{baseUrl}}/booking/{{bookingId}}):

pm.test("Status 404", () => pm.response.to.have.status(404));

Ishga tushirish (kolleksiyani eksport qilib):

npx newman run booker.postman_collection.json

Biz Newman 6.2.3 bilan ishga tushirdik: 4 ta so'rov, 8 ta assertion, 0 ta xato. Eslatma: Postman'ning Free tarifi 2026-yil martidan bitta foydalanuvchiga cheklangan — jamoaviy ish uchun Bruno yoki Hoppscotch'da xuddi shu mantiqni qurish mumkin (QA 10).

</details>

Topshiriq 18: SQL — buyurtmalar yaxlitligi (🟡) {#t18}

Quyidagi DemoBozor ma'lumotlarini SQLite'ga yuklang (sqlite3 capstone.db < capstone_seed.sql) va to'rtta so'rov yozing:

  • (a) subtotal buyurtma qatorlari yig'indisiga (quantity × unit_price) teng bo'lmagan buyurtmalar;
  • (b) total ≠ subtotal − discount + delivery_fee bo'lgan buyurtmalar;
  • (c) yetkazish qoidasi buzilgan buyurtmalar (≥ 300 000 bo'lsa ham haq olingan yoki < 300 000 bo'lsa ham premium bo'lmagan mijozdan olinmagan);
  • (d) mavjud bo'lmagan buyurtmaga bog'langan "yetim" order_items.
-- capstone_seed.sql
CREATE TABLE users (
  id INTEGER PRIMARY KEY,
  phone TEXT UNIQUE NOT NULL,
  full_name TEXT NOT NULL,
  role TEXT CHECK (role IN ('buyer','seller','admin')) DEFAULT 'buyer',
  is_premium INTEGER DEFAULT 0,
  created_at TEXT
);
CREATE TABLE products (
  id INTEGER PRIMARY KEY,
  name TEXT NOT NULL,
  category TEXT,
  price INTEGER NOT NULL,
  stock INTEGER NOT NULL,
  seller_id INTEGER REFERENCES users(id)
);
CREATE TABLE orders (
  id INTEGER PRIMARY KEY,
  user_id INTEGER REFERENCES users(id),
  status TEXT CHECK (status IN ('CREATED','PENDING_PAYMENT','PAID','PACKING','SHIPPED','DELIVERED','CANCELLED','RETURNED')),
  payment_method TEXT CHECK (payment_method IN ('UZCARD','HUMO','VISA','MASTERCARD','CASH')),
  promo_code TEXT,
  subtotal INTEGER,
  discount INTEGER,
  delivery_fee INTEGER,
  total INTEGER,
  created_at TEXT
);
CREATE TABLE order_items (
  id INTEGER PRIMARY KEY,
  order_id INTEGER REFERENCES orders(id),
  product_id INTEGER REFERENCES products(id),
  quantity INTEGER CHECK (quantity BETWEEN 1 AND 99),
  unit_price INTEGER
);
CREATE TABLE payments (
  id INTEGER PRIMARY KEY,
  order_id INTEGER REFERENCES orders(id),
  amount INTEGER,
  status TEXT CHECK (status IN ('SUCCESS','FAILED','REFUNDED')),
  provider TEXT,
  created_at TEXT
);

INSERT INTO users VALUES
  (1, '+998900000001', 'Aziz Karimov',     'buyer',  0, '2026-08-01 10:00:00'),
  (2, '+998900000002', 'Malika Rasulova',  'buyer',  1, '2026-08-03 12:30:00'),
  (3, '+998900000003', 'Jasur Toshmatov',  'seller', 0, '2026-07-15 09:00:00'),
  (4, '+998900000004', 'Dilnoza Yusupova', 'buyer',  0, '2026-08-20 18:45:00'),
  (5, '+998900000005', 'Admin',            'admin',  0, '2026-07-01 08:00:00');

INSERT INTO products VALUES
  (1, 'Elektr choynak',   'Maishiy texnika', 250000,  40, 3),
  (2, 'Paxta ko''ylak',   'Kiyim',           120000, 100, 3),
  (3, 'Simsiz quloqchin', 'Elektronika',     450000,  25, 3),
  (4, 'Gilam (2x3 m)',    'Uy',             1800000,   5, 3),
  (5, 'Telefon g''ilofi', 'Aksessuar',        45000, 200, 3);

INSERT INTO orders VALUES
  (101, 1, 'DELIVERED', 'UZCARD',     NULL,       295000,  29500, 20000,  285500, '2026-09-01 11:00:00'),
  (102, 2, 'DELIVERED', 'VISA',       NULL,       450000,      0,     0,  450000, '2026-09-02 15:20:00'),
  (103, 4, 'PAID',      'HUMO',       NULL,       240000,      0, 20000,  260000, '2026-09-05 09:10:00'),
  (104, 1, 'SHIPPED',   'UZCARD',     'BAHOR15', 1890000, 283500,     0, 1606500, '2026-09-07 19:00:00'),
  (105, 2, 'DELIVERED', 'MASTERCARD', NULL,       340000,      0,     0,  340000, '2026-09-08 13:40:00'),
  (106, 4, 'CANCELLED', 'VISA',       NULL,       250000,      0, 20000,  270000, '2026-09-10 10:05:00'),
  (107, 1, 'CREATED',   'CASH',       NULL,       450000,      0,     0,  405000, '2026-09-12 21:15:00'),
  (108, 4, 'DELIVERED', 'UZCARD',     NULL,       700000,      0, 20000,  720000, '2026-09-14 08:30:00'),
  (109, 1, 'DELIVERED', 'HUMO',       NULL,        90000,      0, 20000,  110000, '2026-09-15 17:50:00');

INSERT INTO order_items VALUES
  (1, 101, 1, 1, 250000),
  (2, 101, 5, 1,  45000),
  (3, 102, 3, 1, 450000),
  (4, 103, 2, 2, 120000),
  (5, 104, 4, 1, 1800000),
  (6, 104, 5, 2,  45000),

Markdown manba

iOS Lessons