# QA 16: Test avtomatlashtirishga kirish — nimani avtomatlashtirish kerak, ROI va 2026 asboblar xaritasi

> **Holat:** 2026-yil oktabr. Bu dars Avtomatlashtirish modulini ochadi: avtotest nima va nima emas, qaysi testni avtomatlashtirish o'zini oqlaydi, ROI qanday hisoblanadi, 2026-yilda qaysi asboblar ishlatiladi va avtomatlashtirish framework'i qanday quriladi. Versiyalar 2026-yil 9-oktabrda npm va GitHub'dan tekshirilgan (masalan, `@playwright/test` 1.64.0).

> **Bu darsdan keyin siz:** "buni avtomatlashtiramizmi?" degan savolga hissiyot bilan emas, hisob-kitob bilan javob bera olasiz.

- avtotest va qo'lda (manual) testning kuchli tomonlarini ajrata olasiz;
- test case'ni avtomatlashtirish kerakmi yoki yo'qligini mezonlar asosida hal qilasiz;
- ROI va qoplanish nuqtasini (break-even) hisoblaysiz;
- 2026-yilgi asboblar xaritasida yo'naltirilasiz va nega bu kursda Playwright + TypeScript tanlanganini tushuntira olasiz;
- yaxshi avtotestning tamoyillarini bilasiz va yomon testni ko'rganda taniysiz.

## Mundarija

1. [Test avtomatlashtirish nima](#nima)
2. [Qo'lda va avtomatik test: kim nimada kuchli](#manual-vs-auto)
3. [Nimani avtomatlashtirish kerak, nimani yo'q](#nimani)
4. [ROI: avtomatlashtirish qachon o'zini oqlaydi](#roi)
5. [Piramida avtomatlashtirish nigohidan](#piramida)
6. [2026-yil asboblar xaritasi](#asboblar)
7. [Nega bu kursda Playwright + TypeScript](#nega-playwright)
8. [Avtomatlashtirish framework'i arxitekturasi](#arxitektura)
9. [Yaxshi avtotestning 10 tamoyili](#tamoyillar)
10. [Amaliy mashqlar](#mashqlar)
11. [O'zingizni tekshiring](#checklist)
12. [Xulosa](#xulosa)
13. [Manbalar](#manbalar)

---

## 1. Test avtomatlashtirish nima {#nima}

**Test avtomatlashtirish** — test'ni (yoki test ishining bir qismini) dastur yordamida bajarish. Dastur ilovani ochadi, foydalanuvchi qiladigan harakatlarni takrorlaydi, natijani kutilgan natija bilan solishtiradi va hisobot beradi.

Oddiy qilib aytganda: **avtotest — sizning test case'ingizning kod ko'rinishidagi nusxasi.** U charchamaydi, xato bosmaydi, kechasi ham ishlaydi. Lekin u faqat siz o'rgatgan narsani tekshiradi.

Keling, bitta qo'lda yoziladigan test case'ni avtotestga aylantirib ko'ramiz. Mashq uchun haqiqiy demo do'kon — [saucedemo.com](https://www.saucedemo.com) dan foydalanamiz:

| Test case qadami (qo'lda)                         | Avtotestdagi qatori (Playwright)                                  |
| ------------------------------------------------- | ----------------------------------------------------------------- |
| 1. Login sahifasini oching                        | `await page.goto('/');`                                           |
| 2. Username: `standard_user`                      | `await page.getByTestId('username').fill('standard_user');`       |
| 3. Parol: `secret_sauce`                          | `await page.getByTestId('password').fill('secret_sauce');`        |
| 4. "Login" tugmasini bosing                       | `await page.getByTestId('login-button').click();`                 |
| **Kutilgan natija:** "Products" sahifasi ochiladi | `await expect(page.getByTestId('title')).toHaveText('Products');` |

To'liq ko'rinishi:

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

test("standard_user muvaffaqiyatli kiradi", async ({ page }) => {
  await page.goto("/");
  await page.getByTestId("username").fill("standard_user");
  await page.getByTestId("password").fill("secret_sauce");
  await page.getByTestId("login-button").click();

  await expect(page).toHaveURL(/\/inventory\.html$/);
  await expect(page.getByTestId("title")).toHaveText("Products");
});
```

Hozircha sintaksisni tushunish shart emas — buni [QA 17](/ios-lessons/qa-typescript) (TypeScript) va [QA 18](/ios-lessons/qa-playwright-basics) (Playwright) darslarida bosqichma-bosqich o'rganamiz. Muhimi — g'oya: **qadam → kod, kutilgan natija → assertion**.

### Avtomatlashtirish nima EMAS

- **Yangi bug'larni "o'zi" topadigan sehr emas.** Avtotest asosan **regressiyani** ushlaydi: kecha ishlagan narsa bugun buzilmaganini tekshiradi. Yangi, kutilmagan muammolarni ko'pincha inson exploratory testing'da topadi.
- **Manual QA'ni almashtirmaydi.** "Bu ekran tushunarlimi?", "foydalanuvchi bu yerda adashmaydimi?" degan savollarga dastur javob bermaydi.
- **"Bir marta yozdim — tamom" emas.** Avtotest — kod. U ham eskiradi, buziladi, refactoring talab qiladi.
- **100% qamrov maqsad emas.** Maqsad — eng muhim risk'larni eng arzon qatlamda tekshirish.
- **Faqat UI emas.** Unit, API, performance, accessibility, visual tekshiruvlar ham avtomatlashtiriladi.

> **🎯 Intervyuda:** "Avtomatlashtirish manual testing'ni to'liq almashtira oladimi?" — Yo'q. Avtomatlashtirish takrorlanadigan va aniq natijali tekshiruvlarni tezlashtiradi; exploratory, usability va yangi funksiyani birinchi marta "his qilib" ko'rish inson ishi bo'lib qoladi. Yaxshi jamoada ular bir-birini to'ldiradi.

---

## 2. Qo'lda va avtomatik test: kim nimada kuchli {#manual-vs-auto}

| Mezon                           | Qo'lda (manual) test                     | Avtomatik test                               |
| ------------------------------- | ---------------------------------------- | -------------------------------------------- |
| Bir martalik tekshiruv narxi    | Arzon — darhol boshlanadi                | Qimmat — avval kod yozish kerak              |
| Ko'p marta takrorlash narxi     | Har safar yana inson vaqti               | Deyarli bepul (mashina vaqti)                |
| Tezlik                          | Daqiqalar–soatlar                        | Soniyalar–daqiqalar                          |
| Charchoq va e'tiborsizlik       | Bor (100-test'da ko'z "o'rganib qoladi") | Yo'q                                         |
| Kutilmagan narsani payqash      | Kuchli: "bu tugma g'alati joyda-ku!"     | Zaif: faqat yozilgan assertion'ni tekshiradi |
| UX/usability baholash           | Faqat inson                              | Deyarli imkonsiz                             |
| Ko'p ma'lumot kombinatsiyalari  | Zerikarli, xatoga moyil                  | Kuchli (data-driven test)                    |
| Kechasi, har PR'da, 3 brauzerda | Amalda imkonsiz                          | Odatiy holat                                 |
| Tez o'zgaruvchan UI             | Moslashuvchan                            | Testlar tez-tez buziladi                     |
| Hisobot va iz (trace)           | Tester yozgan narsa                      | Avtomatik: log, screenshot, video, trace     |

### Keng tarqalgan afsonalar

| Afsona                                | Haqiqat                                                                                                  |
| ------------------------------------- | -------------------------------------------------------------------------------------------------------- |
| "Avtotest yozsak, QA kerak bo'lmaydi" | Avtotestni ham kimdir loyihalaydi, yozadi, tahlil qiladi. Exploratory va risk tahlili baribir inson ishi |
| "Hammasini avtomatlashtiramiz"        | Har bir test'ning narxi bor. Bir yilda 2 marta ishlaydigan test'ni avtomatlashtirish ko'pincha zarar     |
| "UI testlar eng muhimi"               | UI testlar eng sekin va eng beqaror qatlam. Ko'p tekshiruv unit/API darajasida arzonroq                  |
| "Yashil test = bug yo'q"              | Yashil test faqat **siz tekshirgan narsa** buzilmaganini bildiradi (QA 2 dagi 1-printsip)                |
| "Avtotest bir marta yoziladi"         | U ham kod: ilova o'zgarsa, test ham o'zgaradi                                                            |

> **🧠 Esda tuting:** Avtomatlashtirish — **test qilishning o'zi emas, test qilishni tezlashtiruvchi vosita.** Nimani tekshirishni test dizayn (QA 5–6) hal qiladi, avtomatlashtirish faqat uni tez va ko'p marta bajaradi.

---

## 3. Nimani avtomatlashtirish kerak, nimani yo'q {#nimani}

### "Ha" degan signallar

1. **Ko'p takrorlanadi** — har relizdagi regression, har PR'dagi smoke.
2. **Funksionallik barqaror** — talab va UI har hafta o'zgarmaydi.
3. **Biznes riski yuqori** — login, savatcha, checkout, to'lov. Bu yerda bug qimmatga tushadi.
4. **Ma'lumotga asoslangan** — bir xil qadamlar, lekin o'nlab kirish qiymatlari (QA 5 dagi EP/BVA jadvallari).
5. **Qo'lda zerikarli yoki xato qilish oson** — 80 ta API endpoint, 3 brauzer × 4 ekran o'lchami.
6. **Natija aniq** — "summa 340 000 so'm bo'lishi kerak" kabi qat'iy kutilgan natija (oracle) bor.

### "Yo'q" yoki "hozircha yo'q" degan signallar

1. **Exploratory testing** — u ta'rifiga ko'ra oldindan yozilmaydi.
2. **UX va "chiroyli ko'rinadimi?"** — qisman visual testlar yordam beradi (QA 25), lekin yakuniy hukm insonda.
3. **Bir martalik tekshiruv** — masalan, bir martalik ma'lumot migratsiyasini qo'lda tekshirish arzonroq.
4. **Tez o'zgarayotgan UI** — prototip bosqichidagi ekran uchun yozilgan test har hafta buziladi.
5. **Boshqarib bo'lmaydigan tashqi tizim** — "SMS haqiqatan telefonga keldimi?", "bank kartadan pul yechdimi?". Bularni test muhitida sandbox, mock yoki test hook bilan quyi qatlamda tekshiramiz.
6. **Ataylab avtomatlashtirishga qarshi himoyalar** — CAPTCHA kabi. Test muhitida ular dasturchilar bilan kelishilgan holda o'chiriladi, avtotest ularni "aylanib o'tmaydi".

### Amaliy baholash usuli

Har bir test case'ga 4 ta mezon bo'yicha 1–3 ball qo'ying va yig'ing. Bu **standart emas, amaliy usul** — jamoa ichida qaror qabul qilishni tezlashtiradi:

| Mezon          | 1 ball                             | 2 ball           | 3 ball                          |
| -------------- | ---------------------------------- | ---------------- | ------------------------------- |
| Chastota       | Kvartalda 1 marta                  | Har relizda      | Har PR / har kuni               |
| Risk           | Kosmetik                           | Muhim funksiya   | Pul, login, ma'lumot yo'qolishi |
| Barqarorlik    | Har hafta o'zgaradi                | Ba'zan o'zgaradi | Deyarli o'zgarmaydi             |
| Texnik osonlik | Juda qiyin (tashqi tizim, CAPTCHA) | O'rtacha         | Oson (API yoki barqaror UI)     |

**9–12 ball** → avtomatlashtiramiz; **6–8** → muhokama qilamiz; **4–5** → qo'lda qoldiramiz.

DemoBozor (kurs davomidagi xayoliy onlayn do'konimiz) misolida:

| Test                                              | Chastota | Risk | Barqarorlik | Osonlik | Jami | Qaror va qatlam                           |
| ------------------------------------------------- | -------- | ---- | ----------- | ------- | ---- | ----------------------------------------- |
| SMS kod bilan login                               | 3        | 3    | 3           | 2       | 11   | ✅ API + 1 ta E2E                         |
| Bepul yetkazib berish chegarasi (≥ 300 000 so'm)  | 3        | 3    | 3           | 3       | 12   | ✅ Unit (BVA qiymatlari) + API            |
| Promo-kod va chegirmalar jadvali                  | 3        | 3    | 2           | 3       | 11   | ✅ Unit/API, data-driven                  |
| Checkout: savatchadan buyurtmagacha               | 3        | 3    | 2           | 2       | 10   | ✅ 1–2 ta E2E                             |
| Yangi bosh sahifa dizayni (har hafta o'zgaryapti) | 2        | 1    | 1           | 2       | 6    | ⏸ Hozircha qo'lda + exploratory           |
| SMS haqiqiy telefonga yetib keldimi               | 2        | 2    | 3           | 1       | 8    | 🔍 SMS provayder sandbox'i bilan muhokama |
| Sharh matni 10–1000 belgi                         | 2        | 1    | 3           | 3       | 9    | ✅ API (BVA)                              |
| Yillik hisobotni bir marta eksport qilish         | 1        | 2    | 2           | 2       | 7    | ⏸ Qo'lda                                  |

---

## 4. ROI: avtomatlashtirish qachon o'zini oqlaydi {#roi}

Menejer sizdan "avtomatlashtirishga 160 soat sarflasak, nima olamiz?" deb so'raydi. Javobni his bilan emas, hisob bilan bering.

```text
M  = bitta qo'lda regression yugurishi narxi (soat)
A  = avtomatlashgan yugurishdagi qoldiq ish (qo'lda qolgan testlar + natijani tahlil + testlarni tuzatish)
I  = boshlang'ich investitsiya (framework + testlarni yozish, soat)

Bir yugurishdagi tejash:          S = M − A
Qoplanish nuqtasi (break-even):   n = I / S   (shuncha yugurishdan keyin investitsiya qaytadi)
Davr uchun ROI:                   ROI = (S × yugurishlar soni − I) / I × 100%
```

### Ishlangan misol: DemoBozor regression'i

- Regression to'plami: **120 ta test case × 6 daqiqa = 12 soat** (M = 12).
- Reliz har 2 haftada → yiliga **26 ta** regression.
- Avtomatlashtirish: framework + 100 ta test'ni yozish — **I = 160 soat**. Qolgan 20 ta test (UX, tashqi tizimlar) qo'lda qoladi.
- Avtomatik yugurishdagi qoldiq ish: 20 ta qo'lda test ≈ 2 soat + natijani tahlil va testlarni tuzatish ≈ 2 soat → **A = 4 soat**.

Hisob:

```text
S = 12 − 4 = 8 soat tejaladi (har yugurishda)
n = 160 / 8 = 20 yugurish → 20 × 2 hafta ≈ 40 hafta (~9 oy)
1-yil ROI = (8 × 26 − 160) / 160 × 100% = (208 − 160) / 160 = 30%
```

| Yugurishlar soni | Tejalgan vaqt (S × n) | Sof natija (− I) | Holat                            |
| ---------------- | --------------------- | ---------------- | -------------------------------- |
| 10               | 80 soat               | −80 soat         | Hali zarar                       |
| 20               | 160 soat              | 0                | Qoplanish nuqtasi                |
| 26 (1 yil)       | 208 soat              | +48 soat         | Foydaga chiqdi                   |
| 52 (2 yil)       | 416 soat              | +256 soat        | Investitsiya ~2,6 barobar qaytdi |

> **💡 Maslahat:** Testlar qanchalik ko'p ishga tushsa, investitsiya shunchalik tez qaytadi. Agar regression faqat relizda emas, **har PR'da** ishlasa, qo'lda bunday tekshiruvni hech kim qila olmasdi — avtomatlashtirishning haqiqiy qiymati shu yerda ochiladi.

### Hisobga kirmaydigan, lekin muhim narsalar

| Yashirin xarajatlar                                   | Yashirin foyda                                                  |
| ----------------------------------------------------- | --------------------------------------------------------------- |
| Flaky (beqaror) testlarni tekshirishga ketadigan vaqt | Feedback soatlar emas, daqiqalarda keladi                       |
| CI serverlar va ularning daqiqalari                   | Har PR'da regression — bug kodga qo'shilishidan oldin ushlanadi |
| Jamoani o'qitish                                      | Kechasi 3 brauzerda ishlaydi                                    |
| UI o'zgarganda testlarni yangilash                    | Manual QA vaqti exploratory testing'ga bo'shaydi                |
| Test ma'lumotlarini (test data) qo'llab-quvvatlash    | Relizga ishonch ortadi, hotfix'lar kamayadi                     |

> **⚠️ Diqqat:** Yuqoridagi raqamlar — **o'quv misoli**. O'z loyihangiz uchun haqiqiy vaqtlarni o'lchang: bitta regression necha soat oladi, testlarni tuzatishga haftasiga qancha vaqt ketadi. Aks holda ROI jadvali chiroyli, lekin yolg'on bo'ladi.

> **🎯 Intervyuda:** "Avtomatlashtirish foydali ekanini qanday isbotlaysiz?" — Qo'lda regression narxi, yugurishlar chastotasi va qo'llab-quvvatlash xarajatini o'lchab, qoplanish nuqtasini hisoblayman; bundan tashqari tezroq feedback va ushlangan regression bug'lar sonini ko'rsataman.

---

## 5. Piramida avtomatlashtirish nigohidan {#piramida}

[QA 4](/ios-lessons/qa-levels-types) da test piramidasi bilan tanishgansiz. Avtomatlashtirishda bu piramida **byudjet rejasi** kabi ishlaydi: tekshiruvni qayerda qilsangiz, shuncha narx to'laysiz.

Google Testing Blog'dagi mashhur maqolada shunday maslahat bor: boshlang'ich taxmin sifatida **70% unit, 20% integratsion, 10% end-to-end** test; aniq nisbat jamoaga qarab farq qiladi, lekin **piramida shakli saqlanishi kerak**. Teskari piramida — "muzqaymoq" (ice cream cone) — anti-pattern sifatida ko'rsatilgan.

```text
                 ▲  sekin, qimmat, beqarorroq
               /E2E\        ~10%  — foydalanuvchi oqimi (Playwright UI)
              /------\
             /  API   \     ~20%  — servislar va integratsiya (Playwright request, Postman)
            /----------\
           /    Unit    \   ~70%  — funksiya va klasslar (Vitest, Jest, XCTest)
          /--------------\
                 ▼  tez, arzon, barqaror
```

| Qatlam             | Kim yozadi                          | Bitta test vaqti            | Yiqilsa, bug qayerda?               | DemoBozor misoli                           |
| ------------------ | ----------------------------------- | --------------------------- | ----------------------------------- | ------------------------------------------ |
| Unit               | Asosan dasturchi (QA review qiladi) | Millisekundlar              | Aniq funksiyada                     | `calculateDeliveryFee(299_999) === 20_000` |
| API / integratsion | QA + dasturchi                      | Yuz millisekundlar – soniya | Aniq endpoint'da                    | `POST /api/v1/orders` → `total` to'g'ri    |
| E2E (UI)           | QA (AQA)                            | Soniyalar – daqiqa          | Istalgan joyda: UI, API, DB, tarmoq | Savatchadan "Rahmat!" sahifasigacha        |

### Bitta qoida — uch qatlam

DemoBozor'da "mahsulotlar summasi ≥ 300 000 so'm bo'lsa yetkazib berish bepul" qoidasi bor. Uni qanday taqsimlaymiz?

| Qatlam | Nechta test | Nima tekshiriladi                                                                   |
| ------ | ----------- | ----------------------------------------------------------------------------------- |
| Unit   | 6 ta        | BVA qiymatlari: 0, 299 999, 300 000, 300 001, juda katta summa, manfiy summa (xato) |
| API    | 2 ta        | `POST /orders` javobidagi `deliveryFee` 299 999 va 300 000 uchun to'g'ri            |
| E2E    | 1 ta        | Checkout ekranida "Bepul yetkazib berish" yozuvi chiqishi                           |

Ko'rdingizmi: chegaradagi barcha holatlar arzon qatlamda, UI'da esa faqat "ulanish ishlayaptimi" tekshiriladi. Agar 6 ta BVA holatini ham UI orqali tekshirsak, 6 ta sekin va beqaror test olamiz.

---

## 6. 2026-yil asboblar xaritasi {#asboblar}

Versiyalar 2026-yil 9-oktabrdagi npm `latest` (k6 — GitHub releases) bo'yicha. Versiyalar tez o'zgaradi — loyihaga qo'shishdan oldin `npm view <paket> version` bilan tekshiring.

| Yo'nalish                   | Asboblar (2026)                                                                                                                            | Bu kursda                                                                                |
| --------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------ | ---------------------------------------------------------------------------------------- |
| Web UI (E2E)                | **Playwright** (`@playwright/test` 1.64.0), Cypress 16.1.1, Selenium WebDriver (JS paketi `selenium-webdriver` 4.50.0), WebdriverIO 10.0.2 | [QA 18](/ios-lessons/qa-playwright-basics), [QA 19](/ios-lessons/qa-playwright-advanced) |
| API                         | Playwright `request`, Postman + Newman 6.2.3 (yoki Bruno), REST Assured (Java), pytest + requests (Python)                                 | [QA 10](/ios-lessons/qa-api-postman), [QA 20](/ios-lessons/qa-api-automation)            |
| Mobil                       | Appium 3.8.0, Maestro, XCUITest, Espresso, Detox, Patrol                                                                                   | [QA 22](/ios-lessons/qa-mobile-automation)                                               |
| Performance                 | k6 (v2.3.0, 2026-yil 21-sentabr), JMeter, Gatling, Locust                                                                                  | [QA 23](/ios-lessons/qa-performance-k6)                                                  |
| Accessibility               | axe-core (`@axe-core/playwright` 4.13.0), Lighthouse                                                                                       | [QA 25](/ios-lessons/qa-a11y-l10n-visual)                                                |
| Visual                      | Playwright `toHaveScreenshot`, Percy, Applitools, Chromatic                                                                                | [QA 19](/ios-lessons/qa-playwright-advanced), [QA 25](/ios-lessons/qa-a11y-l10n-visual)  |
| Unit (dasturchilar bilan)   | Vitest 5.0.3, Jest 30.5.2, JUnit, pytest, XCTest / Swift Testing                                                                           | [XCTest darsi](/ios-lessons/testing)                                                     |
| BDD (Gherkin)               | Cucumber (`@cucumber/cucumber` 13.3.0), playwright-bdd 9.2.1                                                                               | [QA 3](/ios-lessons/qa-sdlc-stlc-agile)                                                  |
| Test ma'lumotlari va schema | `@faker-js/faker` 10.6.0, Zod 4.6.5                                                                                                        | [QA 17](/ios-lessons/qa-typescript), [QA 20](/ios-lessons/qa-api-automation)             |
| Hisobotlar                  | Playwright HTML report, Allure (`allure-playwright` 3.13.0)                                                                                | [QA 21](/ios-lessons/qa-ci-cd)                                                           |
| CI/CD                       | GitHub Actions, GitLab CI, Jenkins                                                                                                         | [QA 21](/ios-lessons/qa-ci-cd)                                                           |
| AI yordamchilar             | Playwright Test Agents (planner, generator, healer — v1.56 dan), Playwright MCP                                                            | [QA 26](/ios-lessons/qa-ai-testing)                                                      |

> **💡 Maslahat:** Asboblar ro'yxatini yodlash shart emas. Muhimi — **kategoriyalarni** bilish: "bu UI test asbobi", "bu yuk (load) testi asbobi". Vakansiyada notanish asbob ko'rsangiz, uning kategoriyasini aniqlab, tanish analogiga bog'lang.

---

## 7. Nega bu kursda Playwright + TypeScript {#nega-playwright}

### Playwright haqida faktlar

- Microsoft tomonidan ishlab chiqiladi, ochiq kodli (**Apache-2.0** litsenziya).
- Uchta brauzer dvigatelida ishlaydi: **Chromium, Firefox, WebKit** (Safari dvigateli).
- Tillar: **TypeScript/JavaScript, Python, Java, .NET**. Node.js versiyasi o'zining test runner'i bilan keladi; Python uchun rasmiy tavsiya — Pytest plagini.
- **Auto-waiting**: action'dan oldin element ko'rinishi, barqaror bo'lishi va bosilishga tayyorligini o'zi kutadi.
- **Test izolyatsiyasi**: har bir test uchun yangi `BrowserContext` (inkognitoga o'xshash profil) yaratadi — cookie va localStorage testlar orasida "oqib o'tmaydi".
- O'zida: test runner, parallel ishga tushirish, retry, fixture'lar, API testlash, trace viewer, UI mode, codegen.
- Tizim talablari (rasmiy hujjat): Node.js 22.x, 24.x yoki 26.x; macOS 14+; Windows 11+ yoki WSL; Debian 12/13, Ubuntu 22.04/24.04/26.04.

### Uch mashhur asbobni solishtiramiz

| Mezon                      | Playwright                                           | Cypress                                                                                      | Selenium WebDriver                                                   |
| -------------------------- | ---------------------------------------------------- | -------------------------------------------------------------------------------------------- | -------------------------------------------------------------------- |
| Litsenziya                 | Apache-2.0                                           | MIT                                                                                          | Apache-2.0                                                           |
| Tillar                     | TS/JS, Python, Java, .NET                            | Faqat JavaScript/TypeScript (rasmiy hujjat: "faqat veb tili — JavaScript")                   | Java, JavaScript, Python, .NET, Ruby                                 |
| Brauzerlar                 | Chromium, Firefox, WebKit                            | Chrome oilasi, Firefox; WebKit — `experimentalWebKitSupport` sozlamasi bilan (eksperimental) | Chrome, Firefox, Edge, Safari va boshqalar (W3C WebDriver standarti) |
| Test kodi qayerda ishlaydi | Node.js jarayonida, brauzerni tashqaridan boshqaradi | Brauzer ichida ("Cypress commands run inside of a browser")                                  | Alohida jarayonda, driver orqali                                     |
| Bir nechta brauzer/tab     | Bir test ichida bir nechta `page` va `context`       | Bir vaqtda faqat 1 ta brauzer; ko'p tab — `@cypress/puppeteer` plagini orqali                | Mumkin                                                               |
| Kutish                     | Auto-wait + web-first assertion'lar                  | Ichki qayta urinish (retry) mexanizmi                                                        | Kutishni o'zingiz yozasiz (explicit wait)                            |
| Test runner                | O'zida bor (`@playwright/test`)                      | O'zida bor                                                                                   | Alohida: JUnit, TestNG, pytest, Mocha...                             |
| Driver boshqaruvi          | Brauzerlar `npx playwright install` bilan            | O'zi boshqaradi                                                                              | Selenium Manager (4.6 versiyadan beri) driverni o'zi yuklaydi        |

**Xulosa:** uchalasi ham ishlaydigan, haqiqiy loyihalarda ishlatiladigan asboblar. Bu kurs uchun Playwright'ni tanladik, chunki u **bitta asbobda** UI, API, mobil emulyatsiya, trace va parallel ishga tushirishni beradi, hamda TypeScript'da birinchi darajali qo'llab-quvvatlanadi. Selenium'ni bilish ham foydali — ko'plab katta va eski loyihalar unda yozilgan.

### Qaysi tilni tanlash kerak?

| Til                     | Qachon mantiqiy                                                                                                      |
| ----------------------- | -------------------------------------------------------------------------------------------------------------------- |
| TypeScript / JavaScript | Frontend React/Vue/Angular'da yozilgan; dasturchilar bilan bitta tilda ishlash; Playwright hujjatlari TS'da birinchi |
| Python                  | Jamoa backend'i yoki data qismi Python'da; pytest ekotizimi                                                          |
| Java                    | Jamoa Java/Spring'da; Selenium + TestNG yoki REST Assured ishlatilgan loyihalar                                      |
| Swift / Kotlin          | Native mobil UI testlar: XCUITest (iOS), Espresso (Android) — [QA 22](/ios-lessons/qa-mobile-automation)             |

> **💡 Maslahat:** "Eng yaxshi til" yo'q. Eng yaxshisi — **jamoangiz yozadigan til**: kod review'dan o'tadi, dasturchilar yordam bera oladi, CI'da bir xil asboblar ishlaydi. Boshlovchi uchun maslahat: bitta tilni chuqur o'rganing, qolganlari keyin tez o'zlashtiriladi.

> **🎯 Intervyuda:** "Nega Selenium emas, Playwright?" — Playwright auto-wait, test izolyatsiyasi (har test uchun yangi browser context), o'zida runner, trace viewer va API testlashni beradi; Selenium esa W3C standartiga asoslangan, tillar tanlovi keng va eski loyihalarda keng tarqalgan. Tanlov loyiha va jamoaga bog'liq.

---

## 8. Avtomatlashtirish framework'i arxitekturasi {#arxitektura}

"Framework" — bu shunchaki testlar to'plami emas, balki testlarni **yozish, ishga tushirish va qo'llab-quvvatlashni osonlashtiradigan tuzilma**. Yaxshi tuzilmada har bir qatlamning bitta vazifasi bor.

![Avtomatlashtirish framework'ining qatlamlari: test spec'lardan CI'gacha](/lessons/images/qa/qa_16_framework_layers.svg)

Kurs davomida quradigan loyihamiz tuzilmasi ([QA 18](/ios-lessons/qa-playwright-basics)–[QA 21](/ios-lessons/qa-ci-cd)):

```text
qa-demo-tests/
├── package.json
├── playwright.config.ts      # baseURL, brauzerlar, testIdAttribute, trace
├── .env.example              # BASE_URL, API_BASE_URL, SAUCE_USERNAME, SAUCE_PASSWORD
├── pages/                    # Page Object'lar (QA 19): LoginPage.ts, InventoryPage.ts ...
├── fixtures/test.ts          # test.extend — page object'larni testga berish (QA 19)
├── api/BookingClient.ts      # API client (QA 20)
├── schemas/booking.ts        # Zod schema'lar (QA 20)
├── tests/
│   ├── auth.setup.ts         # bir marta login, storageState (QA 19)
│   ├── ui/login.spec.ts      # QA 18
│   ├── ui/cart.spec.ts       # QA 18–19
│   ├── ui/checkout.spec.ts   # QA 18–19
│   └── api/booking.spec.ts   # QA 20
└── .github/workflows/playwright.yml   # CI (QA 21)
```

| Qatlam                                          | Vazifasi                                                    | Nimani bilmasligi kerak                          |
| ----------------------------------------------- | ----------------------------------------------------------- | ------------------------------------------------ |
| Test spec'lar (`tests/`)                        | **Nima** tekshiriladi: senariy va assertion                 | CSS selektorlar, URL'lar, parol qayerdan kelishi |
| Page Object'lar (`pages/`)                      | Sahifa bilan **qanday** ishlash: locator va action'lar      | Test qaysi natijani kutayotgani                  |
| Fixture va helper'lar (`fixtures/`)             | Tayyorlash va tozalash: login, ma'lumot yaratish            | Aniq bir test senariysi                          |
| API client va test data (`api/`, `schemas/`)    | Ma'lumotni tez yaratish (UI'siz), javob shaklini tekshirish | UI tuzilmasi                                     |
| Konfiguratsiya (`playwright.config.ts`, `.env`) | Muhit: URL, brauzerlar, timeout, maxfiy ma'lumotlar         | Test mantig'i                                    |
| Runner, hisobot, CI                             | Ishga tushirish, parallel, retry, hisobot, PR status        | —                                                |

> **🧠 Esda tuting:** Bog'liqlik **yuqoridan pastga** ketadi: test → page object → locator. Agar sahifadagi tugma o'zgarsa, faqat bitta page object'ni tuzatasiz, 40 ta testni emas. Bu tamoyilni [QA 19](/ios-lessons/qa-playwright-advanced) da amalda ko'ramiz.

---

## 9. Yaxshi avtotestning 10 tamoyili {#tamoyillar}

1. **Har bir test mustaqil.** Test boshqa test'dan oldin yoki keyin ishlashiga bog'liq bo'lmasligi kerak. Playwright har test uchun yangi browser context beradi — bundan foydalaning.
2. **Ma'lumot deterministik.** Har yugurishda test o'z ma'lumotini yaratadi (unikal nom, faker + seed) va iloji bo'lsa o'zi tozalaydi. Bir umumiy hisobni parallel testlar o'zgartirmasin.
3. **`sleep` yo'q.** "3 soniya kutib turaman" — sekin va baribir beqaror. O'rniga auto-wait va web-first assertion (QA 18).
4. **AAA tuzilmasi:** Arrange (tayyorlash) → Act (harakat) → Assert (tekshirish).
5. **Bitta test — bitta xatti-harakat.** "Login, savatcha, profil va chiqish" bitta testda bo'lsa, yiqilganda nima buzilganini topish qiyin.
6. **Nom xatti-harakatni tasvirlaydi.** `test1` emas, `"2 ta mahsulot qo'shilsa badge 2 ni ko'rsatadi"`.
7. **Testlarda DAMP > DRY.** Testlar o'qilishi oson bo'lsin (Descriptive And Meaningful Phrases). Biroz takror normal; faqat "shovqin"ni (login, ma'lumot yaratish) fixture/page object'ga chiqaring. Google Testing Blog'ning "Tests Too DRY? Make Them DAMP!" maqolasi aynan shu haqida.
8. **Barqaror locator'lar.** Rol, label, test id. `div:nth-child(3) > span` kabi DOM tuzilmasiga bog'liq selektorlardan qoching. Kerak bo'lsa dasturchilardan `data-testid` qo'shishni so'rang — testlanuvchanlik (testability) jamoaning umumiy ishi.
9. **Test kodi = production kodi.** Git, code review, lint, tushunarli nomlar. Yomon yozilgan test ham texnik qarz.
10. **Yiqilish o'zini tushuntirsin.** Aniq assertion, kerak bo'lsa izohli xabar, trace va screenshot. "Expected true, received false" — yomon xabar.

### Yomon test qanday ko'rinadi: haqiqiy tajriba

Quyidagi ikki test saucedemo'da yozilgan. Ularda bir nechta tamoyil buzilgan:

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

let loggedIn = false; // ❌ testlar orasida umumiy holat

test("1-test: login", async ({ page }) => {
  await page.goto("https://www.saucedemo.com/");
  await page.locator("#user-name").fill("standard_user");
  await page.locator("#password").fill("secret_sauce");
  await page.locator("#login-button").click();
  await page.waitForTimeout(5000); // ❌ "uxlash"
  loggedIn = true;
});

test("2-test: savatcha", async ({ page }) => {
  if (!loggedIn) return; // ❌ shart bajarilmasa test "jimgina o'tadi"
  await page.goto("https://www.saucedemo.com/inventory.html");
  await page
    .locator('//*[@id="inventory_container"]/div/div[1]/div[2]/div[2]/button')
    .click(); // ❌ mo'rt XPath
  const badge = await page.locator(".shopping_cart_badge").textContent();
  expect(badge).toBe("1"); // ❌ qayta urinmaydigan tekshiruv
});
```

Biz bu testni Playwright 1.64 da ikki xil rejimda ishga tushirib ko'rdik:

| Rejim               | 2-test natijasi         | Nega                                                                                                                              |
| ------------------- | ----------------------- | --------------------------------------------------------------------------------------------------------------------------------- |
| Parallel (standart) | ✅ **"O'tdi" — 163 ms** | 2-test boshqa worker jarayonida ishladi, u yerda `loggedIn = false`, test hech narsa tekshirmay chiqib ketdi. **Yolg'on yashil!** |
| `--workers=1`       | ❌ 30 soniya timeout    | Har test yangi browser context'da: 2-test login qilinmagan, saucedemo login sahifasiga qaytaradi, XPath topilmaydi                |

Bir xil kod — ikki xil natija. Mana shu **flaky (beqaror) test**ning tug'ilishi. Uni qanday tuzatishni [mashq 4](#mashqlar) da ko'rasiz.

> **⚠️ Diqqat:** Eng xavfli test — yiqiladigan test emas, **hech narsani tekshirmay o'tadigan** test. U jamoaga yolg'on xotirjamlik beradi. Har yangi testni bir marta ataylab "sindirib" ko'ring: kutilgan natijani noto'g'ri qilib yozing — test qizarishi kerak.

Flaky testlarning sabablari (vaqtga bog'liqlik, umumiy ma'lumot, testlar tartibi, tashqi servislar) va ularni boshqarish — [QA 21](/ios-lessons/qa-ci-cd) da.

---

## 10. Amaliy mashqlar {#mashqlar}

### Mashq 1: Avtomatlashtiramizmi?

DemoBozor uchun quyidagi tekshiruvlarni ko'rib chiqing. Har biri uchun qaror qabul qiling: avtomatlashtiramiz (qaysi qatlamda?) yoki qo'lda qoldiramiz. Sababini bir jumlada yozing.

1. Telefon raqami formati (`+998` + 9 raqam) — 15 ta turli kirish qiymati.
2. Yangi "Bayram aksiyasi" banneri chiroyli ko'rinadimi.
3. Buyurtma statusi `PAID` → `PACKING` → `SHIPPED` o'tishlari.
4. iOS ilovada qo'ng'iroq kelganda checkout holati saqlanishi.
5. 3 marta noto'g'ri SMS kod → 15 daqiqa blok.
6. Admin panelda bir martalik ma'lumot ko'chirish natijasi.
7. Har relizdan oldin login → qidiruv → savatcha → buyurtma oqimi.
8. Mahsulot sahifasida rasm sifati.

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

| #   | Qaror                                           | Qatlam                   | Sabab                                                                                                             |
| --- | ----------------------------------------------- | ------------------------ | ----------------------------------------------------------------------------------------------------------------- |
| 1   | ✅ Avtomatlashtiramiz                           | Unit + API (data-driven) | 15 qiymat, aniq natija, tez-tez ishlaydi                                                                          |
| 2   | ❌ Qo'lda                                       | —                        | Estetik baho — inson ishi (visual test faqat o'zgarishni ko'rsatadi)                                              |
| 3   | ✅ Avtomatlashtiramiz                           | API                      | Yuqori risk, aniq state transition qoidalari (QA 6)                                                               |
| 4   | ⏸ Asosan qo'lda                                 | Real qurilma             | Interruption'larni avtomatlashtirish qiyin; avval exploratory, keyin imkon bo'lsa mobil avtomatlashtirish (QA 22) |
| 5   | ✅ Avtomatlashtiramiz                           | API                      | Xavfsizlik qoidasi, aniq natija; vaqtni boshqarish uchun test muhitida soat/konfiguratsiya kerak                  |
| 6   | ❌ Qo'lda                                       | —                        | Bir martalik ish, avtomatlashtirish o'zini oqlamaydi                                                              |
| 7   | ✅ Avtomatlashtiramiz                           | 1–2 ta E2E               | Eng muhim foydalanuvchi oqimi, har relizda takrorlanadi                                                           |
| 8   | ❌ Qo'lda (yoki visual test yordamchi sifatida) | —                        | Sifat bahosi subyektiv                                                                                            |

</details>

### Mashq 2: ROI hisobi

Ma'lumotlar: qo'lda regression — **90 ta test case × 5 daqiqa**. Regression **har hafta** ishlaydi. Avtomatlashtirish uchun boshlang'ich investitsiya — **120 soat**. Avtomatlashgandan keyin har yugurishda qoldiq ish: **1,5 soat** qo'lda testlar + **1,5 soat** tahlil va testlarni tuzatish.

Hisoblang: M, A, S, qoplanish nuqtasi (necha hafta?) va 1 yillik (52 hafta) ROI.

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

```text
M = 90 × 5 daqiqa = 450 daqiqa = 7,5 soat
A = 1,5 + 1,5 = 3 soat
S = 7,5 − 3 = 4,5 soat (har yugurishda)
n = 120 / 4,5 = 26,7 → 27 ta yugurish ≈ 27 hafta (~6 oy)
1-yil: tejash = 4,5 × 52 = 234 soat
ROI = (234 − 120) / 120 × 100% = 95%
```

Xulosa: haftalik regression bilan investitsiya yarim yilda qaytadi, birinchi yilning o'zida ~95% ROI. Agar testlar har PR'da ishlasa, foyda yanada katta bo'ladi (garchi qoldiq tahlil vaqti ham o'zgarishi mumkin).

</details>

### Mashq 3: Qaysi asbob?

Har bir vaziyat uchun asbobni tanlang va bir jumlada asoslang:

1. iOS jamoasi native ilovaning login ekranini Xcode ichida testlamoqchi.
2. QA jamoasi kod bazasiga kirmasdan iOS va Android ilovalarining asosiy oqimlarini YAML'da tez avtomatlashtirmoqchi.
3. API 500 so'rov/soniya yukni ko'tara oladimi — tekshirish kerak.
4. TypeScript biladigan QA REST API regression'ini CI'da ishga tushirmoqchi.
5. Dizayn tizimidagi tugmalar tasodifan o'zgarib qolmasligini nazorat qilish kerak.
6. Java/Spring'da ishlaydigan jamoa API testlarini o'z tilida yozmoqchi.
7. Sahifa WCAG talablariga mosligini avtomatik tekshirish kerak.

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

| #   | Asbob                                             | Sabab                                                                                                 |
| --- | ------------------------------------------------- | ----------------------------------------------------------------------------------------------------- |
| 1   | XCUITest                                          | Apple'ning native UI test framework'i, Xcode bilan integratsiyalashgan                                |
| 2   | Maestro (yoki Appium)                             | Maestro oqimlari YAML'da yoziladi va kod bazasini talab qilmaydi; Appium — kod bilan, ko'proq nazorat |
| 3   | k6 (yoki JMeter/Gatling)                          | Yuk (load) testi uchun mo'ljallangan, threshold'lar bilan                                             |
| 4   | Playwright `request` (yoki Newman)                | QA biladigan tilda, UI testlar bilan bir loyihada, CI'da oson                                         |
| 5   | Playwright `toHaveScreenshot` / Percy / Chromatic | Visual regression — piksel/vizual farqni ushlaydi                                                     |
| 6   | REST Assured                                      | Java ekotizimidagi API test kutubxonasi, JUnit/TestNG bilan                                           |
| 7   | axe-core (`@axe-core/playwright`)                 | Avtomatik accessibility tekshiruvi; lekin qo'lda tekshiruvni almashtirmaydi (QA 25)                   |

</details>

### Mashq 4: Yomon testni tuzating

[9-bo'limdagi](#tamoyillar) ikki testni oling. (a) Undagi barcha muammolarni sanab chiqing. (b) Testni tamoyillarga mos qilib qayta yozing (`baseURL` = `https://www.saucedemo.com` va `testIdAttribute: 'data-test'` sozlangan deb hisoblang).

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

**(a) Muammolar:**

1. `let loggedIn` — testlar orasida umumiy o'zgaruvchan holat; parallel rejimda har worker'da alohida bo'ladi.
2. 2-test 1-test'ga bog'liq (tartibga bog'liqlik).
3. `if (!loggedIn) return;` — test hech narsani tekshirmay "o'tadi" (yolg'on yashil).
4. `waitForTimeout(5000)` — har safar 5 soniya yo'qotiladi va baribir kafolat yo'q.
5. Uzun XPath — DOM sal o'zgarsa buziladi.
6. `textContent()` + `toBe()` — qayta urinmaydigan tekshiruv, sahifa kechiksa yiqiladi.
7. To'liq URL testlar ichida — muhit almashtirish qiyin (`baseURL` ishlatilmagan).
8. Test nomlari xatti-harakatni emas, tartib raqamini aytadi.

**(b) Tuzatilgan versiya** (Playwright 1.64 da ishga tushirib tekshirilgan):

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

test.describe("Savatcha", () => {
  test.beforeEach(async ({ page }) => {
    await page.goto("/");
    await page.getByTestId("username").fill("standard_user");
    await page.getByTestId("password").fill("secret_sauce");
    await page.getByTestId("login-button").click();
    await expect(page.getByTestId("title")).toHaveText("Products");
  });

  test("Backpack qo'shilganda savatcha belgisi 1 bo'ladi", async ({ page }) => {
    // Arrange: beforeEach'da login qilindi
    // Act
    await page.getByTestId("add-to-cart-sauce-labs-backpack").click();
    // Assert
    await expect(page.getByTestId("shopping-cart-badge")).toHaveText("1");
  });
});
```

Har test o'zi login qiladi (keyinroq [QA 19](/ios-lessons/qa-playwright-advanced) da buni `storageState` bilan tezlashtiramiz), `sleep` yo'q, locator'lar barqaror, assertion auto-retry qiladi.

</details>

### Mashq 5: Piramidaga joylang

DemoBozor promo-kod funksiyasi uchun quyidagi tekshiruvlarni Unit / API / E2E qatlamlariga taqsimlang:

1. Promo-kod formati: 6–12 belgi, faqat `A–Z` va `0–9`.
2. Muddati o'tgan promo-kod rad etiladi.
3. Yangi mijoz (10%) va promo-kod (15%) bir vaqtda — kattasi (15%) qo'llanadi.
4. Checkout ekranida promo-kod maydoniga kod kiritib, "Qo'llash" bosilganda chegirma qatori ko'rinadi.
5. Bitta foydalanuvchi bir promo-kodni ikkinchi marta ishlata olmaydi.
6. Promo-kod minimal summadan kam buyurtmaga qo'llanmaydi.

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

| #   | Qatlam     | Sabab                                                  |
| --- | ---------- | ------------------------------------------------------ |
| 1   | Unit       | Sof validatsiya funksiyasi, ko'p BVA qiymatlari        |
| 2   | Unit + API | Sana mantiqi unit'da; API javobi va xato xabari API'da |
| 3   | Unit       | Chegirma hisoblash qoidasi (decision table)            |
| 4   | E2E (1 ta) | UI va backend ulanishi ishlayotganini ko'rsatadi       |
| 5   | API        | Ma'lumotlar bazasidagi holatga bog'liq biznes qoidasi  |
| 6   | Unit + API | Chegara qiymatlari unit'da, integratsiya API'da        |

Natija: 1 ta E2E, qolganlari arzon va tez qatlamlarda — piramida shakli saqlandi.

</details>

### Mashq 6: Framework qatlamlari

Har bir fayl qaysi papkaga tegishli? `pages/`, `fixtures/`, `api/`, `schemas/`, `tests/ui/`, `tests/api/`, ildiz (root), `.github/workflows/`.

1. `CheckoutPage.ts`
2. `booking.ts` (Zod schema)
3. `playwright.yml`
4. `checkout.spec.ts`
5. `BookingClient.ts`
6. `test.ts` (`test.extend` bilan page object'larni beradi)
7. `playwright.config.ts`
8. `booking.spec.ts` (API CRUD testlari)

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

| Fayl                   | Papka                |
| ---------------------- | -------------------- |
| `CheckoutPage.ts`      | `pages/`             |
| `booking.ts`           | `schemas/`           |
| `playwright.yml`       | `.github/workflows/` |
| `checkout.spec.ts`     | `tests/ui/`          |
| `BookingClient.ts`     | `api/`               |
| `test.ts`              | `fixtures/`          |
| `playwright.config.ts` | ildiz (root)         |
| `booking.spec.ts`      | `tests/api/`         |

</details>

---

## 11. O'zingizni tekshiring {#checklist}

- [ ] Avtotest nima ekanini va nima emasligini 1 daqiqada tushuntira olaman
- [ ] Test'ni avtomatlashtirish uchun 6 ta "ha" va 6 ta "yo'q" signalini bilaman
- [ ] M, A, S, I bilan qoplanish nuqtasi va ROI'ni hisoblay olaman
- [ ] 70/20/10 piramida g'oyasini va "muzqaymoq" anti-pattern'ini tushuntira olaman
- [ ] Playwright, Cypress va Selenium farqlarini faktlar bilan ayta olaman
- [ ] Framework qatlamlarini va bog'liqlik yo'nalishini bilaman
- [ ] Yolg'on yashil testni taniy olaman

---

## Xulosa {#xulosa}

- Avtomatlashtirish — test qilishni **tezlashtiruvchi vosita**; nimani tekshirishni test dizayn hal qiladi, inson ishi (exploratory, UX) qoladi.
- Avtomatlashtirish uchun eng yaxshi nomzodlar: ko'p takrorlanadigan, yuqori riskli, barqaror va aniq natijali tekshiruvlar.
- ROI'ni his bilan emas, hisob bilan asoslang: `S = M − A`, `n = I / S`. Testlar qanchalik ko'p ishlasa, investitsiya shunchalik tez qaytadi.
- Piramida — byudjet: ko'p tekshiruv unit/API'da, UI'da faqat asosiy oqimlar (boshlang'ich taxmin 70/20/10).
- 2026-yilda web UI uchun asosiy tanlovlar: Playwright 1.64, Cypress 16, Selenium 4.50; bu kurs Playwright + TypeScript bilan boradi.
- Framework qatlamlari: test → page object → fixture/helper → API/data → config → runner/CI. Bog'liqlik yuqoridan pastga.
- Eng xavfli test — hech narsani tekshirmay o'tadigan test. Har yangi testni bir marta ataylab "sindirib" ko'ring.
- **Keyingi dars:** [QA 17: QA uchun TypeScript — o'zgaruvchilar, funksiyalar, async/await, class'lar va npm](/ios-lessons/qa-typescript)

## Manbalar {#manbalar}

1. [Playwright — Installation (tizim talablari)](https://playwright.dev/docs/intro)
2. [Playwright — Best Practices](https://playwright.dev/docs/best-practices)
3. [Playwright — Isolation va Browser Contexts](https://playwright.dev/docs/browser-contexts)
4. [Playwright — Supported languages](https://playwright.dev/docs/languages)
5. [Playwright — GitHub releases](https://github.com/microsoft/playwright/releases)
6. [Google Testing Blog — Just Say No to More End-to-End Tests (Mike Wacker, 2015)](https://testing.googleblog.com/2015/04/just-say-no-to-more-end-to-end-tests.html)
7. [Google Testing Blog — Tests Too DRY? Make Them DAMP! (2019)](https://testing.googleblog.com/2019/12/testing-on-toilet-tests-too-dry-make.html)
8. [Martin Fowler — Test Pyramid](https://martinfowler.com/bliki/TestPyramid.html)
9. [Ham Vocke — The Practical Test Pyramid](https://martinfowler.com/articles/practical-test-pyramid.html)
10. [Cypress — Trade-offs](https://docs.cypress.io/app/references/trade-offs)
11. [Cypress — Cross Browser Testing](https://docs.cypress.io/app/guides/cross-browser-testing)
12. [Cypress — Experiments (`experimentalWebKitSupport`)](https://docs.cypress.io/app/references/experiments)
13. [Selenium — Selenium Manager](https://www.selenium.dev/documentation/selenium_manager/)
14. [Grafana k6 — GitHub releases](https://github.com/grafana/k6/releases)
15. [Sauce Labs demo do'koni — saucedemo.com](https://www.saucedemo.com)
