Wisar
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 tekshirmaysiz).
  • Refaktoring erkinligi — kodni o'zgartirsangiz, 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 yozing. 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'ling:

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 boshqaring.

Hammasini mock qilmang. 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 tozalang.


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 sinang, implementatsiyani emas — ichki tafsilot o'zgarsa test buzilmasin.
  • Chekka holatlarni qamrab oling — bo'sh, null, manfiy, juda katta, bir element.
  • Aniq test nomi — "nima sinaladi va nima kutiladi".
  • Har testdan keyin tozalang — DB, mock, holat.
  • CI'da test ishlating — har push'da avtomatik (10.5, 15.3).
  • Bug topilsa — avval test yozing (regressiyani qaytarmaslik uchun).
  • Mock'ni o'lchov bilan ishlating — kam, faqat kerakli joyda.

Mashq

  1. sum, isPalindrome, validateEmail uchun unit testlar yozing (chekka holatlar bilan).
  2. Bir REST endpoint uchun integration test yozing (supertest).
  3. Kirish oqimi uchun bitta e2e test yozing (Playwright).
  4. Bir kichik funksiyani TDD bilan yozing (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