WisarWisar
Hamroh materiallar/Chuqur bilim5 daqiqa

Testing qo'llanmasi — unit, integration, e2e, TDD

Senior dasturchini junior'dan ajratadigan narsalardan biri — test yozish odati. Test — kodga ishonch, refaktoring erkinligi va "tunda qo'ng'iroq" kamayishi. Bu qo'llanma kitobning 11.17 va 15-QISMiga tayanadi.


1. Nega test yozamiz?

  • Ishonch — kod ishlashini isbotlaydi (qo'lda har safar tekshirmaysan).
  • Refaktoring erkinligi — kodni o'zgartirsang, testlar buzilmasligini ko'rsatadi.
  • Hujjat — test kod qanday ishlatilishini ko'rsatadi.
  • Regressiyani oldini olish — tuzatilgan bug qayta paydo bo'lmaydi.
  • Yaxshiroq dizayn — testlanadigan kod — toza, kam bog'liq kod.

"Test yozishga vaqt yo'q" — aslida test yozmaslik keyinchalik ko'proq vaqt yeydi (qo'lda tekshirish, production bug, qo'rqib refaktoring qilmaslik).


2. Test piramidasi

text
        ╱╲          E2E (kam, sekin, qimmat)
       ╱  ╲         — butun tizimni foydalanuvchidek sinaydi
      ╱────╲        Integration (o'rtacha)
     ╱      ╲       — bir necha qism birga ishlashini sinaydi
    ╱────────╲      Unit (ko'p, tez, arzon)
   ╱__________╲     — bitta funksiya/komponentni alohida sinaydi

Qoida: ko'p unit, o'rtacha integration, kam e2e. Pastdagilar tez va arzon — ko'p yoz. Yuqoridagilar sekin va mo'rt — kam, lekin muhim oqimlar uchun.


3. Unit test (birlik testi)

Bitta funksiya/komponentni alohida, boshqalardan ajratib sinaydi.

js
// sum.js
export function sum(a, b) { return a + b; }

// sum.test.js (Jest / Vitest)
import { sum } from "./sum";

describe("sum", () => {
  it("ikki musbat sonni qo'shadi", () => {
    expect(sum(2, 3)).toBe(5);
  });
  it("manfiy son bilan ishlaydi", () => {
    expect(sum(-1, 1)).toBe(0);
  });
});

AAA naqshi — har testni 3 qismga bo'l:

js
it("savatga mahsulot qo'shadi", () => {
  const cart = new Cart();        // Arrange (tayyorla)
  cart.add({ id: 1, price: 100 }); // Act (bajar)
  expect(cart.total).toBe(100);    // Assert (tekshir)
});

Nimani unit test qilish kerak: sof mantiq (hisob, validatsiya, transform), chekka holatlar (bo'sh, null, manfiy, juda katta).


4. Mocking (soxtalashtirish)

Tashqi bog'liqlikni (DB, API, vaqt) soxta bilan almashtirish — testni tez va bashoratli qiladi.

js
// API'ni mock qilish
import { getUser } from "./api";
jest.mock("./api");

it("foydalanuvchi ismini ko'rsatadi", async () => {
  getUser.mockResolvedValue({ name: "Ali" }); // soxta javob
  const result = await loadUserName(5);
  expect(result).toBe("Ali");
  expect(getUser).toHaveBeenCalledWith(5);     // to'g'ri chaqirilganini tekshir
});

Mock turlari: stub (tayyor javob qaytaradi), spy (chaqiruvni kuzatadi), mock (ikkalasi). Vaqt: jest.useFakeTimers() bilan setTimeoutni boshqar.

Hammasini mock qilma. Faqat sekin/tashqi/bashoratsiz narsalarni (tarmoq, DB, vaqt, tasodif). Ortiqcha mock — testni mo'rt qiladi.


5. Integration test

Bir necha qism birga ishlashini sinaydi (masalan API endpoint + DB).

js
// Express API'ni real (test) DB bilan sinash
import request from "supertest";
import { app } from "./app";

describe("POST /users", () => {
  it("yangi foydalanuvchi yaratadi", async () => {
    const res = await request(app)
      .post("/users")
      .send({ name: "Ali", email: "ali@mail.uz" });
    expect(res.status).toBe(201);
    expect(res.body.id).toBeDefined();
  });

  it("noto'g'ri email'ni rad etadi", async () => {
    const res = await request(app).post("/users").send({ email: "xato" });
    expect(res.status).toBe(400);
  });
});

Test DB: alohida test bazasi (yoki Docker'da vaqtinchalik PostgreSQL — testcontainers). Har testdan keyin tozala.


6. E2E (end-to-end) test

Butun tizimni foydalanuvchidek sinaydi — brauzerni boshqaradi (Playwright/Cypress).

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

test("foydalanuvchi kirib, vazifa qo'shadi", async ({ page }) => {
  await page.goto("/login");
  await page.fill('[name="email"]', "ali@mail.uz");
  await page.fill('[name="password"]', "parol123");
  await page.click('button[type="submit"]');

  await expect(page).toHaveURL("/dashboard");
  await page.fill('[name="task"]', "Test yozish");
  await page.click("text=Qo'shish");
  await expect(page.locator(".task")).toContainText("Test yozish");
});

E2E — eng ishonchli (real foydalanuvchi oqimi), lekin eng sekin/mo'rt. Faqat kritik oqimlar uchun (kirish, to'lov, ro'yxatdan o'tish).


7. TDD (Test-Driven Development)

Avval test, keyin kod. Tsikl: Red Green Refactor.

text
1.  RED    — ishlamaydigan test yoz (kod hali yo'q)
2.  GREEN  — testni o'tkazadigan eng oddiy kodni yoz
3.  REFACTOR — kodni tozala (test hali yashil)
    takrorla

Foydasi: kod doim testlangan, dizayn yaxshilanadi, ortiqcha kod yozilmaydi. Kamchiligi: o'rganish vaqti, har joyda mos kelmaydi (prototip, UI).


8. Coverage (qamrov)

Kodning necha foizi test bilan qamralganini ko'rsatadi.

bash
jest --coverage    # hisobot: % lines, branches, functions

100% coverage — maqsad emas. Yuqori foiz testlar yaxshi ekanini bildirmaydi (ma'nosiz test ham foizni oshiradi). Muhim mantiq va chekka holatlar qamralganmi. 70–80% — odatda yaxshi nishon.


9. Yaxshi test belgilari (FIRST)

  • Fast — tez (minglab unit test sekundlarda).
  • Independent — bir-biriga bog'liq emas (har biri alohida ishlaydi).
  • Repeatable — har safar bir xil natija (vaqt/tasodif mock qilingan).
  • Self-validating — o'zi pass/fail aytadi (qo'lda tekshirish yo'q).
  • Timely — kod bilan birga (yoki oldin) yoziladi.

Yaxshi test: bitta narsani sinaydi, aniq nom ("bo'sh savat 0 qaytaradi"), AAA tuzilishi, mantiq emas — natija sinaydi.


10. Best practices

  • Xulqni sina, implementatsiyani emas — ichki tafsilot o'zgarsa test buzilmasin.
  • Chekka holatlarni qamrab ol — bo'sh, null, manfiy, juda katta, bir element.
  • Aniq test nomi — "nima sinaladi va nima kutiladi".
  • Har testdan keyin tozala — DB, mock, holat.
  • CI'da test ishlat — har push'da avtomatik (10.5, 15.3).
  • Bug topilsa — avval test yoz (regressiyani qaytarmaslik uchun).
  • Mock'ni o'lchov bilan ishlat — kam, faqat kerakli joyda.

Mashq

  1. sum, isPalindrome, validateEmail uchun unit testlar yoz (chekka holatlar bilan).
  2. Bir REST endpoint uchun integration test yoz (supertest).
  3. Kirish oqimi uchun bitta e2e test yoz (Playwright).
  4. Bir kichik funksiyani TDD bilan yoz (avval test, keyin kod).

Bog'liq: Mashqlar M5/M11 · Bosh sahifa: README.

Izohlar (0)

Izoh yozish uchun kiring.

  • Hozircha izoh yo'q. Birinchi bo'ling!
Testing qo'llanmasi — unit, integration, e2e, TDD — Wisar