IlmHamroh
JavaScript Full-stack/25-qism. HTTP, Express va REST API45/51-dars16 daqiqa
Mundarija (28)

Backend test strategiyasi: unit, integration, e2e va contract testlar

Qisqacha: Backend'ning asosiy qiymati — HTTP shartnomasi (qaysi so'rovga qaysi status, sarlavha va tana) va ma'lumotning to'g'ri saqlanishi. Shuning uchun backend'da eng foydali test — integration test: haqiqiy HTTP so'rov → haqiqiy Express → xotiradagi ombor. U unit testdan biroz sekin, lekin ichki refaktoringda buzilmaydi va haqiqiy xatolarni ushlaydi. Test "trofeyi" modelida aynan shu qatlam eng keng. vazifalar-api ning 67 testidan 41 tasi HTTP integration, 13 tasi contract (shartnoma) testi — har ombor (xotira, fayl, 26-qismda Postgres) bir xil testdan o'tadi.

Bu darsda

  • Backend'dagi unit, integration, e2e va contract testlarni farqlay olasiz.
  • Test piramidasi va test trofeyini solishtirib, backend uchun tanlov qilasiz.
  • Testning narxi va ishonchliligi orasidagi muvozanatni tushuntirasiz.
  • Shartnoma testini yozib, uni ikki xil amalga oshirishda ishlatasiz.
  • vazifalar-api testlarini darajalar bo'yicha o'zingiz sanay olasiz.

Oldin bilishingiz kerak: Nega test yozamiz va frontend test turlari, Birinchi avtomatik test: node:test, express.Router va qatlamli tuzilma, Global error handler.

1. Nega bu kerak?

Xato iyerarxiyasi darsida vazifalar-api ning ichi jiddiy o'zgardi: HttpXato o'chdi, olti yangi klass paydo bo'ldi, xizmat va marshrutlar qayta yozildi. Shunga qaramay testlar o'zgarmasdan o'tdi. Nega? Chunki ular ichki klasslarni emas, tashqi xulqni tekshiradi: "bo'sh matn yuborsam — 422 va Problem Details".

Teskari holat ham bo'ldi. Kanon 22-qism frontendini API'ga haqiqiy brauzerda uladi va frontend'da 4 ta o'zgarish kerak bo'ldi: api.ts (manzil, sahifalash, xato formati), .env sozlamasi, Vite proxy va CSP. Ularning hech birini API testlari ushlamadi — muammolar API va frontend orasidagi chegarada edi. Bu ulanishni o'zingiz Coverage darsining «Frontend'ni ulash» bo'limida qilasiz.

Ikkala voqea bitta savolga olib keladi: qaysi testni, qancha va qayerda yozish kerak? Bu — test strategiyasi. Hayotiy o'xshatish: avtomobil zavodidagi sifat nazorati. Har bolt alohida tekshiriladi (unit), lekin eng ko'p vaqt yig'ilgan dvigatelni stendda yurgizishga ketadi (integration). Har mashinani yo'lga olib chiqish (e2e) qimmat — bu faqat bir nechta namuna bilan qilinadi.

2. Backend'da to'rt xil test

FT-01 darsida frontend test turlarini ko'rgansiz. Backend'da ular quyidagicha ko'rinadi:

Tur Nimani tekshiradi vazifalar-api misoli
Unit bitta toza funksiya, I/O'siz kunBoshiUtc("2026-10-24", "Asia/Tashkent")
Integration bir necha qatlam birga, haqiqiy HTTP POST /v1/vazifalar → 201 + Location
E2E butun tizim: brauzer + frontend + API Playwright: vazifa qo'shish, sahifani yangilash
Contract ikki tomon orasidagi kelishuv har ombor bir xil omborShartnomasi() dan o'tadi

Ta'riflarni aniqlaymiz.

Unit test (unit test) — bitta kichik birlikni (funksiya, klass) tashqi dunyodan ajratib tekshiradi. Tez (millisekundlar), sababini aniq ko'rsatadi, lekin "bo'laklar birga ishlaydimi?" degan savolga javob bermaydi.

Integration test (integration test) — bir necha qismning birga ishlashini tekshiradi. Backend'da odatda: ilovani tasodifiy portda (listen(0)) yoki portsiz ishga tushirish, haqiqiy HTTP so'rov yuborish va javobni tekshirish. Ichida haqiqiy marshrut, middleware, validatsiya, xato ishlovchi va (xotiradagi) ombor ishlaydi.

E2E test (end-to-end) — tizimni foydalanuvchi ko'zi bilan, boshidan oxirigacha: brauzer, frontend, API, baza. Eng ishonchli, eng sekin va eng mo'rt.

Contract test (contract test) — "shartnoma testi": ikki tomon kelishgan qoidani tekshiradi. Uning ikki ma'nosi bor — «Contract testlar» bo'limida.

Tekshirib ko'ring: test/rest.test.ts dagi "sahifala: kursor qatori o'chirilsa ham keyingisidan davom etadi" testi sahifala() funksiyasini to'g'ridan chaqiradi, server ochmaydi. U qaysi tur?

Javob

Unit. Server yo'q, HTTP yo'q, faqat toza funksiya va massiv. Fayl nomi (rest.test.ts) turini belgilamaydi — muhimi test nimani ishga tushiradi. Shu faylning qolgan 6 testi esa integration: ular serverga fetch yuboradi.

3. Piramida va trofey

3.1 Ikki model

Test piramidasi (test pyramid) — eski va mashhur model (Mike Cohn, 2009): pastda ko'p unit, o'rtada kamroq integration, tepada ozgina e2e. G'oyasi: arzon testlar ko'p, qimmatlari kam.

Test trofeyi (testing trophy) — Kent C. Dodds modeli (2018): pastda statik tekshiruv (TypeScript, ESLint), keyin unit, eng keng qatlam — integration, tepada e2e. G'oyasi: "foydalanuvchi qanday ishlatsa, shunday tekshir" — eng ko'p ishonchni integration beradi.

flowchart TB
  subgraph T[Trofey: backend]
    direction TB
    T4[E2E — oz]
    T3[Integration — eng ko'p]
    T2[Unit — o'rtacha]
    T1[Statik: tsc, eslint]
    T4 --- T3 --- T2 --- T1
  end
  subgraph P[Piramida]
    direction TB
    P3[E2E — oz]
    P2[Integration — o'rtacha]
    P1[Unit — eng ko'p]
    P3 --- P2 --- P1
  end

Rasmga qarang: farq o'rtadagi qatlamda. Piramidada eng ko'p — unit, trofeyda — integration.

3.2 Narx va ishonch

Har test uch narsa bilan o'lchanadi:

Tur Tezlik Ishonch ("ishlab chiqarishda ham ishlaydi") Refaktoringda buziladimi
Unit juda tez past–o'rta ko'pincha (ichki tuzilmaga bog'liq)
Integration tez–o'rta yuqori kam (tashqi xulqqa bog'liq)
E2E sekin eng yuqori ba'zan (UI o'zgarsa)

"Refaktoringda buziladimi" ustuni ko'pincha unutiladi. Ichki funksiyani mock bilan tekshiradigan unit test kodni o'zgartirganda qizil bo'ladi — xulq to'g'ri bo'lsa ham. Bunday test yolg'on qizil (false negative) beradi va jamoa unga ishonmay qo'yadi (FT-01 atamasi).

3.3 Nega backend'da integration ustun

Uch sabab:

  1. Qiymat chegarada. Mijoz vazifalar-api dan funksiyalarni emas, HTTP javoblarni oladi: status, sarlavha, Problem Details. Shuni tekshirgan test — eng qimmatli.
  2. Arzon bo'ldi. Express ilovasi xotiradagi ombor bilan bir necha millisekundda ishga tushadi. Kanon o'lchovida 15 fayl, 62 test (mock.test.ts dan tashqari hammasi) node --test bilan 2.5 soniyada o'tdi (t46-runner.txt). "Integration sekin" degan gap bazali, tarmoqli eski loyihalardan qolgan.
  3. Haqiqiy xatolar chegarada. Kanon topgan xatolarning ko'pi qatlamlar orasida edi: Express 5 da jim req.body undefined, 416 o'rniga 500, fetch + If-None-Match → 304 kelmasligi. Bularni hech qanday unit test ushlamasdi.

Unit test qachon kerak? Mantiq murakkab va kirish-chiqish aniq bo'lsa: sana hisoblash (DST), kursor kodlash, Zod sxemalari, sahifalash. Ularda ko'p chegaraviy holat bor — har birini HTTP orqali tekshirish ortiqcha.

4. vazifalar-api ning 67 testi

Kanon testlarini fayllar bo'yicha qayta sanadik (holat 51):

vazifalar-api: 67 test darajalar bo'yicha
  • Unitconfig, sana, sxema, sahifala, teglar, sorovId10 test
  • Contract (ombor)5 × 2 ombor + FaylOmbori 313 test
  • HTTP integration33 fetch/node:http + 8 supertest41 test
  • Jarayonexit 1, graceful shutdown3 test

Manba: IlmHamroh kanon, holat 51 (test/*.test.ts, 2026-10-24) — fayllar bo'yicha qo'lda sanaldi

Trofey shakli aniq ko'rinadi: integration — eng keng qatlam. E2E (frontend + API brauzerda) repo'da test sifatida yo'q — kanon uni bir marta qo'lda, Playwright bilan bajardi.

Diqqat: kanon TESTLAR.md jadvalida HTTP integration uchun "46" va supertest uchun "9" yozilgan — bu raqamlar boshqa qatorlar bilan qo'shilganda 67 emas, 81 bo'ladi. Biz har test(...) chaqiruvini fayl bo'yicha sanadik va 10 + 13 + 41 + 3 = 67 chiqdi (bu npm test dagi tests 67 bilan mos). Hujjatdagi raqamlar ham kod kabi eskirishi mumkin — ularni ham tekshiring.

4.1 Integration test qanday ko'rinadi

Kanondagi birinchi test (test/api.test.ts, qisqartirilgan):

ts
before(async () => ({ asos, yop } = await ishgaTushir()));
after(() => yop());

test("CRUD: yaratish → o'qish → … → o'chirish", async () => {
  const r = await fetch(`${asos}/v1/vazifalar`, jsonYubor("POST", {
    matn: "Non olish #uy",
  }));
  assert.equal(r.status, 201);
  assert.equal(r.headers.get("location"), "/v1/vazifalar/1");
  // … GET, PATCH, DELETE
});

ishgaTushir() — ilovani port 0 da (OS bo'sh portni o'zi beradi) va yangi xotira ombori bilan ishga tushiradi. Har test fayli o'z serveri va omborini oladi — testlar bir-biriga xalaqit bermaydi va parallel ishlay oladi.

Buning uchun arxitektura tayyor bo'lishi kerak edi:

  • ilova.ts da listen() yo'q — ilova yasaladi, tinglash alohida (qatlamli tuzilma qarori).
  • Bog'liqliklar tashqaridan beriladi (ilovaYarat({ ombor, log, … })) — testda boshqa ombor, jim logger.
  • process.env faqat server.ts da o'qiladi — testlar muhitga bog'liq emas.

Bu — sinovga qulay arxitektura (testability). Testni keyin yozish oson bo'lishi uchun uni oldindan loyihalash kerak.

5. Contract testlar

5.1 Birinchi ma'no: interfeys shartnomasi

vazifalar-api da VazifaOmbori interfeysi bor va uning ikki amalga oshirishi: XotiraOmbori va FaylOmbori. 26-qismda uchinchisi — Postgres — qo'shiladi. Ular bir xil xulq ko'rsatishi shart: id 1 dan, ol() nusxa qaytaradi, versiya har yozuvda oshadi.

Har ombor uchun alohida test yozish o'rniga kanon bitta shartnoma funksiyasi yozdi va uni har omborga qo'lladi. G'oyani kichik misolda ko'ramiz — ikki ombor, biri xatoli:

js
import assert from "node:assert/strict";

// Shartnoma: har "ombor" shu talablarga javob berishi kerak
async function omborShartnomasi(nom, yarat) {
  const o = yarat();
  const a = await o.qosh("Non olish");
  const b = await o.qosh("Sut");
  assert.deepEqual([a.id, b.id], [1, 2], "id 1 dan ketma-ket");
  const olingan = await o.ol(1);
  olingan.matn = "buzildi";
  const yana = await o.ol(1);
  assert.equal(yana.matn, "Non olish", "ol() nusxa beradi");
  assert.equal(await o.ol(99), undefined, "yo'q id — undefined");
  console.log(`✔ ${nom}`);
}

class MapOmbori {
  #m = new Map();
  async qosh(matn) {
    const v = { id: this.#m.size + 1, matn };
    this.#m.set(v.id, v);
    return { ...v };
  }
  async ol(id) {
    const v = this.#m.get(id);
    return v && { ...v };
  }
}

class MassivOmbori {
  #r = [];
  async qosh(matn) {
    const v = { id: this.#r.length + 1, matn };
    this.#r.push(v);
    return v;
  }
  async ol(id) {
    return this.#r.find((v) => v.id === id); // nusxa emas!
  }
}

const omborlar = [
  ["Map", () => new MapOmbori()],
  ["massiv", () => new MassivOmbori()],
];
for (const [nom, yarat] of omborlar) {
  try {
    await omborShartnomasi(nom, yarat);
  } catch (x) {
    console.log(`✘ ${nom}: ${x.message.split("\n")[0]}`);
  }
}

Konsolda:

text
✔ Map
✘ massiv: ol() nusxa beradi

MassivOmbori ichki obyektni to'g'ridan qaytardi — chaqiruvchi uni o'zgartirdi va ombordagi ma'lumot buzildi. Shartnoma buni ushladi. Bu xato 26-qismda muhim: Postgres har safar yangi obyekt qaytaradi, xotiradagi ombor esa qaytarmasligi mumkin edi — testlar xotirada o'tib, prod'da boshqacha ishlardi.

Kanondagi haqiqiy shartnoma (test/ombor-shartnoma.ts) 5 test, ishlatilishi — ikki qator:

ts
omborShartnomasi("xotira", () => Promise.resolve(new XotiraOmbori()));
omborShartnomasi("fayl", async () =>
  FaylOmbori.och(join(await yangiPapka(), "ichki", "v.json")));

26-qism bitta qator qo'shadi: omborShartnomasi("postgres", …).

5.2 Ikkinchi ma'no: servislar orasidagi shartnoma

Ko'proq tarqalgan ma'nosi — iste'molchi va provayder orasidagi shartnoma. Frontend (iste'molchi) API'dan (provayder) aniq shakl kutadi: vazifalar massivi, xato bo'lsa detail maydoni. API o'zgarsa va frontend bilmasa — ishlab chiqarishda buziladi.

vazifalar-api da bu aynan sodir bo'ldi. Problem Details darsida xato javobi { "xato": "…" } dan Problem Details'ga o'tdi — buzuvchi o'zgarish. API testlari yashil edi (ular yangi formatni kutardi). Frontend esa xato maydonini o'qirdi va buni faqat brauzerdagi ulanish sinovi ko'rsatdi.

Shartnoma testi buni oldindan ushlashi mumkin edi. Ikki mashhur yo'l (kanonda yo'q, hujjat bo'yicha):

Yo'l Qanday Vositalar
Iste'molchi boshqaradigan (consumer-driven) frontend testlari "men shuni kutaman" faylini yozadi, API CI'da shu faylga qarshi tekshiriladi Pact
Sxema asosida API sxemasi (OpenAPI / JSON Schema) yagona manba; ikkala tomon unga qarshi tekshiriladi Zod toJSONSchema, OpenAPI validatorlar

Kanonda ikkinchi yo'lning yarmi bor: npm run sxema Zod sxemalaridan docs/sxemalar.json yasaydi (Zod 4 serverda). Uni frontend testlarida ishlatish — shartnomaning ikkinchi yarmi; 25-qismda qilinmagan.

Tekshirib ko'ring: Ombor shartnomasi testi va Pact testi — ikkalasi ham "contract". Asosiy farq nimada?

Javob

Ombor shartnomasi — bitta jarayon ichida, bitta interfeysning bir nechta amalga oshirishi uchun: "hammasi bir xil xulq ko'rsatsin". Pact — ikki alohida dastur (ko'pincha alohida jamoalar) orasida: "provayder iste'molchi kutgan javobni bersin". Birinchisi almashtiriladigan qismlarni, ikkinchisi tarmoq chegarasini himoya qiladi.

6. Nimani test qilmaslik

Strategiya — nimani yozish bilan birga, nimani yozmaslik ham:

  • Kutubxonaning ichi. Express marshrutlashni, Zod min(1) ni to'g'ri ishlashini tekshirish — ularning mualliflari ishi. Siz faqat o'z sozlamangizni tekshirasiz: "bo'sh matn → 422".
  • Ichki tuzilma. "xizmat.yarat ombor.yarat ni chaqirdimi" — faqat bu xulqning o'zi bo'lsa (masalan, idempotentlikda ombor chaqirilmasligi kerak — keyingi darslarda).
  • Trivial kod. Getter, bir qatorli o'tkazgich.
  • Tasodifiy tafsilot. Xato xabarining har so'zi — o'zgaradi; status va kod maydoni — barqaror.

7. API qadami: TESTLAR.md (holat 51, 1-qism)

Holat 51 — vazifalar-api v1 ning yakuni — yetti darsga bo'lingan: bugungi strategiya, node:test, test dublyorlari, Supertest, tashqi HTTP, vaqt va tasodif, coverage. Hali commit qilmang — commit yettinchi darsda. Har dars oxirida npm run check yashil bo'lib turadi: bugun kod o'zgarmaydi, testlar holat 44 dagidek 58 ta.

Bugun — hujjat: loyiha ildizida TESTLAR.md. Kanondagi qoidalar qismi:

text
## Qoidalar
- Har test o'z serveri/omborini yaratadi — testlar orasida holat yo'q
  (port 0 — parallel ishlaydi).
- Vaqt va tasodif: XotiraOmbori(soat), sorovId(yangiId) — ukol;
  yoki t.mock.timers.enable({ apis: ["Date"] }).
- Tashqi HTTP: webhookXabarchi(url, { fetchFn }) — soxta fetch.
  Tarmoqqa chiqadigan test yo'q.
- Shartli so'rovlar (If-None-Match) — fetch bilan EMAS: undici o'zi
  Cache-Control: no-cache qo'shadi.
- Coverage foizi — sifat emas: test chaqirmagan fayl (server.ts)
  hisobotda umuman YO'Q.

(Qatorlar telefon uchun bo'lindi.) Bu qoidalarning har biri keyingi darslarda alohida mavzu. Jadvalni esa o'zingiz yozasiz — 4-mashqda, o'z sanog'ingiz bilan.

8. Ko'p uchraydigan xatolar

8.1 Hammasini mock bilan unit qilish

Har qatlam soxta bog'liqliklar bilan tekshirilgan, lekin ular birga hech qachon ishga tushmagan. Testlar yashil, ilova ishlamaydi. Asosiy oqimlar — haqiqiy HTTP orqali.

8.2 Testlar orasida umumiy holat

Bitta global ombor: birinchi test vazifa qo'shdi, ikkinchisi "ro'yxat bo'sh" deb kutdi. Natija tartibga bog'liq — yakka ishga tushirsangiz o'tadi, hammasi bilan — yiqiladi. Har test (yoki fayl) yangi ombor.

8.3 E2E bilan hamma narsani tekshirish

Sekin (soniyalar), mo'rt (UI matni o'zgarsa), sababini topish qiyin. E2E — faqat eng muhim foydalanuvchi yo'llari uchun.

8.4 listen() ni ilova faylida chaqirish

Test ilovani import qilganda server port band qiladi va jarayon tugamaydi — node --test osilib qoladi (Supertest darsida haqiqiy chiqish bilan ko'ramiz). ilova.ts — yasaydi, server.ts — tinglaydi.

8.5 Raqam uchun test yozish

"Coverage 100 % bo'lsin" deb trivial kodga test. Xavf qayerda — test shu yerda (Coverage darsi).

9. Mashqlar

1-mashq (oson): darajani aniqlang

Kanon testlari quyida. Har biri qaysi daraja?

  • (a) "config: noto'g'ri qiymat — ConfigXatosi, hammasi bitta xabarda"
  • (b) "PUT /v1/vazifalar — butun to'plam: id saqlanadi…"
  • (c) "VazifaOmbori shartnomasi: fayl — yangila…"
  • (d) "unhandledRejection: log → boshlangan so'rov tugaydi → exit 1"
  • (e) "supertest: shartli so'rov — 304"
Yechim

(a) Unit — configYukla(obyekt) toza funksiya. (b) HTTP integration — fetch bilan PUT. (c) Contract — shartnoma funksiyasi fayl omboriga qo'llangan. (d) Jarayon — alohida bola jarayon ishga tushiriladi va uning exit kodi tekshiriladi. (e) HTTP integration (portsiz, supertest bilan). Bu taqsimot «67 testi» bo'limidagi grafik bilan mos.

2-mashq (o'rta): kesh shartnomasi

Kesh interfeysi: ol(kalit) — qiymat yoki undefined; qoy(kalit, qiymat); ochir(kalit) — o'chirildimi (true/false). keshShartnomasi(nom, yarat) yozing (kamida 3 talab) va ikki amalga oshirishga qo'llang: Map asosidagi va oddiy obyekt ({}) asosidagi. Ikkinchisida ochir doim true qaytarsin — shartnoma buni ushlasin. Eslatma: node:assert/strict — node:test darsidan.

Yechim
js
import assert from "node:assert/strict";

function keshShartnomasi(nom, yarat) {
  const k = yarat();
  assert.equal(k.ol("a"), undefined, "bo'sh kesh");
  k.qoy("a", 1);
  assert.equal(k.ol("a"), 1, "qo'yilgan qiymat");
  assert.equal(k.ochir("a"), true, "bor kalit o'chadi");
  assert.equal(k.ochir("a"), false, "yo'q kalit — false");
  console.log(`✔ ${nom}`);
}

const mapKesh = () => {
  const m = new Map();
  return {
    ol: (k) => m.get(k),
    qoy: (k, v) => m.set(k, v),
    ochir: (k) => m.delete(k),
  };
};

const obyektKesh = () => {
  const o = {};
  return {
    ol: (k) => o[k],
    qoy: (k, v) => { o[k] = v; },
    ochir: (k) => delete o[k], // delete doim true qaytaradi
  };
};

const keshlar = [["Map", mapKesh], ["obyekt", obyektKesh]];
for (const [nom, yarat] of keshlar) {
  try {
    keshShartnomasi(nom, yarat);
  } catch (x) {
    console.log(`✘ ${nom}: ${x.message.split("\n")[0]}`);
  }
}

Konsolda:

text
✔ Map
✘ obyekt: yo'q kalit — false

delete operatori kalit bo'lmasa ham true qaytaradi — bu JavaScript'ning eski xususiyati. Shartnoma uni ushladi. Obyekt kalitida yana bitta tuzoq bor: ol("toString") — undefined emas, funksiya. Uni shartnomaga 5-talab qilib qo'shib ko'ring.

3-mashq (qiyin): yangi endpoint uchun test rejasi

vazifalar-api ga POST /v1/vazifalar/:id/nusxa qo'shilmoqda: vazifaning nusxasini yaratadi (matn va teglar bir xil, bajarildi: false, yangi id), 201 + Location; yo'q id — 404 Problem Details; ro'yxat to'lgan bo'lsa — 409. Qaysi testlarni, qaysi darajada yozasiz? Kod yozmang — reja bering.

Yechim

Namuna reja:

  • Integration (asosiy, 3–4 ta). (1) Mavjud vazifa → 201, Location yangi id'ga, GET bilan matn va teglar bir xil, bajarildi: false. (2) Yo'q id → 404, content-type: application/problem+json, kod. (3) Noto'g'ri id (abc) → 400. (4) Ro'yxat to'lgan → 409; MAKS_VAZIFA ni o'zgartirib bo'lmasa, omborni oldindan to'ldiring.
  • Contract: agar VazifaOmbori ga yangi metod (nusxa) qo'shilsa — shartnomaga test, aks holda kerak emas (xizmat ol + yarat bilan qila oladi).
  • Unit: kerak emas — mantiq oddiy; HTTP testlari uni to'liq qamraydi.
  • E2E: faqat frontend'da "nusxa" tugmasi bo'lsa.
  • Idempotentlik: endpoint POST — Idempotency-Key bilan takrorda ikkinchi nusxa yaratilmasligini tekshirish (Idempotency-Key).

Asosiy fikr: test soni endpoint'ning xulq holatlari soniga teng, kod qatorlari soniga emas.

4-mashq: API qadami

vazifalar-api ildizida TESTLAR.md yarating: strategiya (bir gap), «67 testi» bo'limidagi kabi jadval — lekin o'z loyihangiz testlarini fayl bo'yicha sanab, va «API qadami» bo'limidagi qoidalar. Jadvaldagi raqamlar yig'indisi npm test dagi tests bilan teng bo'lsin. Commit qilmang.

Yechim

Sanash uchun: har *.test.ts faylda test( chaqiruvlarini sanang (grep -c "^test(" test/*.test.ts), shartnoma funksiyasi ichidagilarni ombor soniga ko'paytiring. Keyin har testni bir qatorda o'qib, darajasini belgilang: server ochiladimi (integration), bola jarayonmi (jarayon), faqat funksiyami (unit). Kanon holati 51 da: 10 + 13 + 41 + 3 = 67. Yig'indi npm test bilan mos kelmasa — qaysidir faylni ikki marta sanagansiz yoki describe ichidagini unutgansiz.

10. Real ishda

  • Katta kompaniyalar backend'da integration testni "service test" yoki "component test" deb ataydi — ma'nosi bir xil: servis o'zi butun, tashqi bog'liqliklari soxta yoki konteynerda.
  • Baza bilan integration: 26–27-qismlarda xotiradagi ombor o'rniga haqiqiy Postgres (Testcontainers yoki alohida test bazasi) bilan ham testlar bo'ladi — shartnoma testlari aynan shu ko'prik.
  • Pact mikroservisli kompaniyalarda keng tarqalgan; frontend va backend jamoalari alohida bo'lsa — ayniqsa foydali.
  • Intervyu savollari: "Test piramidasi va trofeyi farqi?", "Backend'da qaysi testlarni ko'proq yozasiz va nega?", "Contract test nima?", "Testga qulay arxitektura qanday bo'ladi?".

Xulosa

  • Backend'da to'rt tur: unit (toza funksiya), integration (haqiqiy HTTP + qatlamlar), e2e (butun tizim), contract (kelishuv).
  • Trofey modeli: eng keng qatlam — integration; backend'da u arzon (port 0, xotiradagi ombor) va refaktoringga chidamli.
  • Unit — murakkab toza mantiq uchun: sana, kursor, sxema, sahifalash.
  • Contract: (1) interfeysning har amalga oshirishi bir xil testdan o'tadi (omborShartnomasi); (2) servislar orasida — Pact yoki sxema.
  • vazifalar-api: 67 test = 10 unit + 13 contract + 41 integration + 3 jarayon; hujjatdagi raqamlarni ham tekshiring.
  • Sinovga qulay arxitektura: listen() siz ilova, tashqaridan beriladigan bog'liqliklar, process.env faqat kirish nuqtasida.

Keyingi dars: node:test va node:assert — Node'ning o'rnatilgan test runner'i chuqur: describe/it, hook'lar, t.mock, snapshot, --watch va nega kanon Vitest'ni emas, node --test ni tanladi (o'lchov bilan).

Manbalar

Ulashish:Telegram'da

Izohlar (0)

Izoh yozish uchun kiring.

  • Hozircha izoh yo'q. Birinchi bo'ling!
Backend test strategiyasi: unit, integration, e2e va contract testlar — IlmHamroh