IlmHamroh
JavaScript Full-stack/22-qism. Frontend testlash2/16-dars30 daqiqa
Mundarija (43)

Vitest I: sozlash va birinchi testlar — describe, test, expect va matcherlar

Qisqacha: Vitest — Vite asosidagi test vositasi: loyihangizning Vite sozlamalarini (plaginlar, taxalluslar) qayta ishlatadi va Jest'ga o'xshash API beradi. Test describe (guruh), test (bitta holat) va expect(qiymat).toBe(kutilgan) (tekshiruv) dan iborat. Fayl nomi *.test.js yoki *.spec.ts bo'lsa, npx vitest run uni o'zi topadi. DOM kerak bo'lsa — environment: "jsdom" yoki "happy-dom".

Bu darsda

  • Vitest'ni o'rnatib, birinchi test faylini yozasiz va terminal chiqishini o'qiysiz.
  • describe, test/it, expect va asosiy matcherlarni (toBe, toEqual, toStrictEqual, toThrow, resolves/rejects) ishlatasiz.
  • vitest.config.ts va vite.config.ts dagi test bloki farqini, include, globals va environment sozlamalarini bilasiz.
  • jsdom, happy-dom va node muhitini o'lchov bilan taqqoslaysiz; watch rejimi va --ui ni bilasiz.
  • vazifalar dagi node:test testlarini Vitest'ga ko'chirasiz — hammasi bitta vositada.

Oldin bilishingiz kerak: Nega test yozamiz va frontend test turlari, Vite II: vite.config ni o'qish va yozish, Birinchi avtomatik test: node:test.

1. Nega bu kerak?

O'tgan darsda TESTLAR.md ni tuzdik. Birinchi bo'shliq: vazifalar da ikki test vositasi bor. Sof mantiq (255 test) — node:test da, komponentlar (65 test) — Vitest'da. npm test ikkalasini ketma-ket yurgizadi: node --test && vitest run.

Bu nimaga xalaqit beradi?

  • Ikki xil hisobot, ikki xil watch (o'zgarishni kuzatish), ikki xil soxta (mock) API.
  • Coverage (qamrov) bitta raqam bo'lib chiqmaydi — ikki vosita ikki xil o'lchaydi.
  • @/ taxallusi (Path alias) node:test da ishlamaydi: u Vite sozlamasini bilmaydi.

Vitest shu muammoni hal qiladi. U Vite ustiga qurilgan: TypeScript, JSX, taxalluslar va plaginlar testda ham ilovadagidek ishlaydi. API'si Jest'ga (eng mashhur eski test vositasi, Jest darsida ko'ramiz) juda o'xshaydi. Shuning uchun Jest'ni bilgan dasturchi Vitest'da darhol ishlay oladi.

2. O'rnatish va birinchi test

2.1 O'rnatish

Bo'sh loyihada boshlaymiz. Versiya — 2026-10 holatiga kanondagi barqaror reliz:

bash
npm init -y
npm pkg set type=module
npm i -D -E vitest@5.0.4
text
added 35 packages, and audited 36 packages in 19s

12 packages are looking for funding
  run `npm fund` for details

found 0 vulnerabilities

35 paket, node_modules — 40 MB (Vite ham shu ichida). Sizda vaqt boshqacha chiqadi.

2.2 Kod va test fayli

«Bahor» savatchasi uchun ikki funksiya — src/cart.js:

js
// «Bahor» savatchasi: jami narx va chegirma
export function cartTotal(items) {
  return items.reduce((sum, item) => sum + item.price * item.qty, 0);
}

// 200 000 so'mdan boshlab — 10% chegirma
export function applyDiscount(amount) {
  if (amount < 0) throw new RangeError("Summa manfiy bo'lmaydi");
  return amount >= 200000 ? amount * 0.9 : amount;
}

Yonida test fayli — src/cart.test.js. Nomidagi .test. — Vitest'ga "bu test fayli" degan belgi:

js
import { describe, test, expect } from "vitest";
import { cartTotal, applyDiscount } from "./cart.js";

describe("cartTotal", () => {
  test("ikki osh va bitta choy", () => {
    const cart = [
      { name: "Osh", price: 35000, qty: 2 },
      { name: "Ko'k choy", price: 5000, qty: 1 },
    ];
    expect(cartTotal(cart)).toBe(75000);
  });

  test("bo'sh savat — 0", () => {
    expect(cartTotal([])).toBe(0);
  });
});

describe("applyDiscount", () => {
  test("chegara: aynan 200 000 — chegirma bor", () => {
    expect(applyDiscount(200000)).toBe(180000);
  });

  test("manfiy summa — xato", () => {
    expect(() => applyDiscount(-1)).toThrow("manfiy");
  });
});

Uch so'z:

  • describe(nom, fn) — guruh (suite). node:test dagi describe bilan bir xil.
  • test(nom, fn) — bitta test. it — uning taxallusi, ikkalasi bir narsa: it("savatni hisoblaydi") inglizchada gap bo'lib o'qiladi ("it calculates…").
  • expect(qiymat).toBe(kutilgan) — tekshiruv. expect qiymatni "qo'liga oladi", .toBe — matcher (moslashtiruvchi): qanday solishtirishni aytadi.

node:test bilan solishtiring:

node:test Vitest
import { test } from "node:test" import { test } from "vitest"
assert.equal(a, b) expect(a).toBe(b)
assert.deepEqual(a, b) expect(a).toStrictEqual(b)
assert.throws(() => f(), /x/) expect(() => f()).toThrow(/x/)
node --test vitest run

expect uslubida gap tabiiy o'qiladi: "kutaman: jami narx 75 000 bo'lsin".

2.3 Ishga tushirish

bash
npx vitest run --reporter=verbose
text
 RUN  v5.0.4 C:/Users/…/bahor-test

 ✓ src/cart.test.js > cartTotal > ikki osh va bitta choy 3ms
 ✓ src/cart.test.js > cartTotal > bo'sh savat — 0 0ms
 ✓ src/cart.test.js > applyDiscount > chegara: aynan 200 000 — chegirma bor 0ms
 ✓ src/cart.test.js > applyDiscount > manfiy summa — xato 1ms

 Test Files  1 passed (1)
      Tests  4 passed (4)
   Start at  14:40:25
   Duration  453ms (import 49%, transform 39%, worker 7%, tests 5%)

Har qator: fayl → guruh → test nomi → vaqt. Pastda — jami: 1 fayl, 4 test o'tdi, 453 ms. --reporter=verbose har testni alohida qatorga chiqaradi. Usiz terminal oynasida fayl bo'yicha qisqa ko'rinish chiqadi (✓ src/cart.test.js (4 tests)).

vitest run — bir marta ishga tushiradi va tugaydi. Faqat vitest desangiz — watch rejimi (pastda). package.json ga odatda ikkalasi yoziladi:

json
{
  "scripts": {
    "test": "vitest run",
    "test:kuzat": "vitest"
  }
}

3. Natija oynasida test

3.1 O'quv modeli — halol eslatma

Bu darsdan boshlab test bloklari ostida ham «Ishga tushir» tugmasi bor. Uni bossangiz, testlar shu sahifadagi natija oynasida ishlaydi va natija konsolga chiqadi.

Diqqat: natija oynasidagi vitest — IlmHamroh o'quv modeli, haqiqiy Vitest emas. U describe, test, expect, matcherlar va vi ning eng ko'p ishlatiladigan qismini takrorlaydi. Xabar matni haqiqiy Vitest'ga o'xshaydi, lekin ayni emas. Haqiqiy chiqish — terminalda: uni har bo'limda pastdagi text blokida beramiz. Ikkalasini aralashtirmang.

Xabar matnining o'zi (expected 200000 to be 180000 // Object.is equality) haqiqiy Vitest'dagidek. Farqlar — uning atrofida (2026-10 holati; ba'zi qatorlar keyingi darslarda kerak bo'ladi):

Natija oynasi (o'quv modeli) Haqiqiy Vitest (terminal)
✓ guruh > nom — fayl nomi va vaqtsiz ✓ src/cart.test.js > guruh > nom 2ms
xato — faqat xabar qatori (→ …) yana - Expected / + Received farqi va kod qatori ^ bilan
rangsiz, bo'sh qatorlar tushib qoladi ranglar va bo'sh qatorlar bor
DOM matcher xabari qisqa: expected <button> to be disabled uzunroq, element HTML'i bilan
ekran har testdan keyin doim tozalanadi sozlamaga bog'liq (RTL I)
React act ogohlantirishlari chiqmaydi sozlamaga bog'liq (RTL II)
vi.mock, snapshot, coverage yo'q bor (Vitest II)
Testlar: 1 yiqildi, 3 o'tdi (jami 4) Tests 1 failed | 3 passed (4)

Yana bir farq ijobiy: natija oynasi — haqiqiy Chrome, jsdom emas. document, CSS va fokus u yerda haqiqiy (sahifada faqat bo'sh <div id="root"> turadi).

3.2 Birinchi jonli test

«Ishga tushir» ni bosing:

jsx
import { describe, test, expect } from "vitest";

function cartTotal(items) {
  return items.reduce((sum, item) => sum + item.price * item.qty, 0);
}

describe("cartTotal", () => {
  test("ikki osh va bitta choy", () => {
    const cart = [
      { name: "Osh", price: 35000, qty: 2 },
      { name: "Ko'k choy", price: 5000, qty: 1 },
    ];
    expect(cartTotal(cart)).toBe(75000);
  });

  test("bo'sh savat — 0", () => {
    expect(cartTotal([])).toBe(0);
  });
});

Konsolda:

text
  ✓ cartTotal > ikki osh va bitta choy
  ✓ cartTotal > bo'sh savat — 0
Testlar: 2 o'tdi (jami 2)

Natija oynasi testni jsx blokida yurgizadi — oddiy JS ham shu yerda ishlaydi. Testlar e'lon tartibida, birin-ketin bajariladi.

4. Yiqilgan testni o'qish

4.1 Jonli: chegaradagi xato

Sardor chegirmada >= o'rniga > yozdi (node:test darsidagi o'sha xato). Test buni ushlaydimi?

jsx
import { describe, test, expect } from "vitest";

// Xato: «200 000 dan boshlab» uchun >= kerak edi
function applyDiscount(amount) {
  return amount > 200000 ? amount * 0.9 : amount;
}

describe("applyDiscount", () => {
  test("kichik buyurtma — chegirmasiz", () => {
    expect(applyDiscount(70000)).toBe(70000);
  });
  test("chegara: aynan 200 000 — chegirma bor", () => {
    expect(applyDiscount(200000)).toBe(180000);
  });
  test("katta buyurtma — 10% kam", () => {
    expect(applyDiscount(300000)).toBe(270000);
  });
});

Konsolda:

text
  ✓ applyDiscount > kichik buyurtma — chegirmasiz
  × applyDiscount > chegara: aynan 200 000 — chegirma bor
    → expected 200000 to be 180000 // Object.is equality
  ✓ applyDiscount > katta buyurtma — 10% kam
Testlar: 1 yiqildi, 2 o'tdi (jami 3)

× — test yiqildi. Xabarni o'qing: "200000 ning 180000 bo'lishi kutilgan edi". // Object.is equality — toBe qiymatlarni Object.is bilan solishtirgani ("Tenglik uch xil" bo'limida). Qolgan testlar baribir ishladi — biri yiqilsa, boshqalari to'xtamaydi.

4.2 Haqiqiy terminalda

Xuddi shu xato npx vitest run da (fayl — «Kod va test fayli» bo'limidagi cart.test.js, applyDiscount ichida >):

text
 ❯ src/cart.test.js (4 tests | 1 failed) 19ms
   ❯ applyDiscount (2)
     × chegara: aynan 200 000 — chegirma bor 11ms

⎯⎯⎯⎯⎯⎯⎯ Failed Tests 1 ⎯⎯⎯⎯⎯⎯⎯

 FAIL  src/cart.test.js > applyDiscount > chegara: aynan 200 000 — chegirma bor
AssertionError: expected 200000 to be 180000 // Object.is equality

- Expected
+ Received

- 180000
+ 200000

 ❯ src/cart.test.js:20:35
     18| describe("applyDiscount", () => {
     19|   test("chegara: aynan 200 000 — chegirma bor", () => {
     20|     expect(applyDiscount(200000)).toBe(180000);
       |                                   ^
     21|   });
     22|

 Test Files  1 failed (1)
      Tests  1 failed | 3 passed (4)

Natija oynasida yo'q uch narsa:

  • - Expected / + Received — kutilgan (-, yashil) va olingan (+, qizil) qiymat yonma-yon.
  • ❯ src/cart.test.js:20:35 — fayl, qator, ustun. Ostida kod bo'lagi va ^ — aynan qaysi tekshiruv yiqildi.
  • Chiqish kodi 1 — npm test ham xato bilan tugaydi. CI shunga qarab "qizil" beradi.

Tekshirib ko'ring: Test yiqildi: expected 200000 to be 180000. Xato kodda yoki testda — buni qanday bilasiz?

Javob

Xabarning o'zi aytmaydi — u faqat "kutilgan va olingan farq qiladi" deydi. Qoidaga (talabga) qarang: "200 000 so'mdan boshlab chegirma" — demak 200 000 ning o'zi ham chegirmali, 180 000 to'g'ri. Xato kodda (> o'rniga >=). Agar talab "200 000 dan ko'p" bo'lganida, testni tuzatish kerak edi. Test — talabning yozma shakli.

5. Matcherlar

5.1 Tenglik uch xil: toBe, toEqual, toStrictEqual

Eng ko'p adashtiriladigan joy. Uchtasini bitta blokda ko'ring — ikkita test ataylab yiqiladi:

jsx
import { test, expect } from "vitest";

const plov = { name: "Osh", price: 35000 };

test("toBe: son", () => {
  expect(35000 * 2).toBe(70000);
});

test("toEqual: tarkibi bir xil obyekt", () => {
  expect({ name: "Osh", price: 35000 }).toEqual(plov);
});

test("toBe: tarkibi bir xil, lekin boshqa obyekt", () => {
  expect({ name: "Osh", price: 35000 }).toBe(plov);
});

test("toEqual undefined maydonni e'tiborsiz qoldiradi", () => {
  expect({ name: "Osh", note: undefined }).toEqual({ name: "Osh" });
});

test("toStrictEqual undefined maydonni ham sanaydi", () => {
  expect({ name: "Osh", note: undefined }).toStrictEqual({
    name: "Osh",
  });
});

Konsolda:

text
  ✓ toBe: son
  ✓ toEqual: tarkibi bir xil obyekt
  × toBe: tarkibi bir xil, lekin boshqa obyekt
    → expected { name: 'Osh', price: 35000 } to be { name: 'Osh', price: 35000 } // Object.is equality
If it should pass with deep equality, replace "toBe" with "toStrictEqual"
  ✓ toEqual undefined maydonni e'tiborsiz qoldiradi
  × toStrictEqual undefined maydonni ham sanaydi
    → expected { name: 'Osh', note: undefined } to strictly equal { name: 'Osh' }
Testlar: 2 yiqildi, 3 o'tdi (jami 5)
Matcher Nimani solishtiradi Qachon
toBe Object.is — aynan o'sha qiymat yoki o'sha obyekt son, satr, true, null
toEqual tarkibni ichkarigacha; undefined maydonlarni tashlaydi obyekt, massiv
toStrictEqual tarkib + undefined maydonlar + klass turi API javobi, aniq shakl

Uchinchi testdagi xabar g'alati tuyuladi: "{…} ning {…} bo'lishi kutilgan edi" — ikkalasi bir xil ko'rinadi. Sabab — obyektlar havola orqali solishtiriladi: ikkita alohida obyekt, tarkibi bir xil bo'lsa ham, Object.is uchun har xil. Ostidagi maslahat qatorini natija oynasi ham beradi. Haqiqiy Vitest'da u farq bloki bilan keladi:

text
AssertionError: expected { name: 'Osh', price: 35000 } to be { name: 'Osh', price: 35000 } // Object.is equality

If it should pass with deep equality, replace "toBe" with "toStrictEqual"

Expected: { name: 'Osh', price: 35000 }
Received: serializes to the same string

Tarjimasi: "Chuqur tenglik bilan o'tishi kerak bo'lsa, toBe ni toStrictEqual ga almashtiring. Kutilgan va olingan qiymat bir xil satrga aylanadi" — ya'ni ko'rinishi bir xil, lekin obyekt boshqa.

node:assert/strict dagi deepEqual aslida toStrictEqual ga yaqin. Shuning uchun node:test dan ko'chirganda toStrictEqual xavfsizroq tanlov.

5.2 Boshqa ko'p ishlatiladigan matcherlar

jsx
import { test, expect } from "vitest";

const menu = ["Osh", "Lag'mon", "Manti"];

test("massiv", () => {
  expect(menu).toContain("Manti");
  expect(menu).toHaveLength(3);
  expect(menu).not.toContain("Shashlik");
});

test("satr", () => {
  expect("Osh — 35 000 so'm").toMatch(/\d+ \d{3} so'm/);
  expect("Bahor oshxonasi").toContain("oshxona");
});

test("kasr son", () => {
  expect(0.1 + 0.2).not.toBe(0.3);
  expect(0.1 + 0.2).toBeCloseTo(0.3);
});

test("obyektning bir qismi", () => {
  const order = {
    id: 7,
    customer: "Ali",
    total: 75000,
    at: Date.now(),
  };
  expect(order).toHaveProperty("customer", "Ali");
  expect(order).toMatchObject({ customer: "Ali", total: 75000 });
  expect(order).toEqual({
    id: 7,
    customer: "Ali",
    total: 75000,
    at: expect.any(Number),
  });
});

test("bor-yo'q", () => {
  expect(menu.find((t) => t === "Somsa")).toBeUndefined();
  expect("".trim()).toBeFalsy();
  expect(menu.length).toBeGreaterThan(2);
});

Konsolda:

text
  ✓ massiv
  ✓ satr
  ✓ kasr son
  ✓ obyektning bir qismi
  ✓ bor-yo'q
Testlar: 5 o'tdi (jami 5)

Bitta testda bir nechta expect bo'lishi mumkin — birinchisi yiqilsa, test o'sha joyda to'xtaydi.

Matcher Ma'nosi
toContain(x) massivda element yoki satrda bo'lak bor
toHaveLength(n) length — n
toMatch(/…/) satr regexga mos (Regex)
toBeCloseTo(x) kasr son x ga yaqin (sukut bo'yicha 2 xona)
toHaveProperty(yo'l, qiymat) xususiyat bor (va qiymati shu)
toMatchObject(qism) obyektda shu maydonlar bor, qolgani muhim emas
toBeTruthy / toBeFalsy truthy/falsy
toBeNull / toBeUndefined / toBeDefined aniq null / undefined / undefined emas
toBeGreaterThan(n) va o'xshashlari >, >=, <, <=

Asimmetrik moslashtiruvchilar — expect.any(Number), expect.stringContaining("…"), expect.objectContaining({…}) — "aniq qiymat muhim emas, turi yoki bir qismi muhim". Yuqorida at (buyurtma vaqti) har safar boshqa bo'ladi, shuning uchun "istalgan son" dedik.

0.1 + 0.2 — sonlar darsidagi kasr xatosi: natija 0.30000000000000004. Kasr pul yoki foiz hisobida doim toBeCloseTo.

5.3 Xato kutish: toThrow

jsx
import { test, expect } from "vitest";

function applyDiscount(amount) {
  if (amount < 0) throw new RangeError("Summa manfiy bo'lmaydi");
  return amount >= 200000 ? amount * 0.9 : amount;
}

test("to'g'ri: funksiyaga o'rab beriladi", () => {
  expect(() => applyDiscount(-1)).toThrow("manfiy");
  expect(() => applyDiscount(-1)).toThrow(RangeError);
});

test("noto'g'ri: applyDiscount(-1) darhol chaqirildi", () => {
  expect(applyDiscount(-1)).toThrow();
});

Konsolda:

text
  ✓ to'g'ri: funksiyaga o'rab beriladi
  × noto'g'ri: applyDiscount(-1) darhol chaqirildi
    → Summa manfiy bo'lmaydi
Testlar: 1 yiqildi, 1 o'tdi (jami 2)

Ikkinchi test yiqildi — lekin expected … tekshiruv xabari bilan emas, funksiyaning o'z RangeError xatosi matni bilan. applyDiscount(-1) expect ga yetib bormasdan, argument hisoblanayotganda xato tashladi. expect xatoni ushlay olishi uchun unga funksiya berish kerak: () => applyDiscount(-1). Bu assert.throws dagi qoidaning aynan o'zi. toThrow("manfiy") — xabarda shu bo'lak bor; toThrow(RangeError) — xato shu turdan (O'z xato klasslaringiz).

5.4 Asinxron kod: await, resolves, rejects

Test funksiyasi async bo'lsa, Vitest u tugashini kutadi:

jsx
import { test, expect } from "vitest";

// Soxta server: 100 ms dan keyin menyu yoki xato
function fetchMenu(isOpen) {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      if (isOpen) resolve(["Osh", "Manti"]);
      else reject(new Error("Oshxona yopiq"));
    }, 100);
  });
}

test("await bilan", async () => {
  const menu = await fetchMenu(true);
  expect(menu).toEqual(["Osh", "Manti"]);
});

test("resolves", async () => {
  await expect(fetchMenu(true)).resolves.toContain("Osh");
});

test("rejects", async () => {
  await expect(fetchMenu(false)).rejects.toThrow("yopiq");
});

Konsolda:

text
  ✓ await bilan
  ✓ resolves
  ✓ rejects
Testlar: 3 o'tdi (jami 3)
  • .resolves — "Promise bajarilsin, keyin qiymatini tekshir".
  • .rejects — "Promise rad etilsin, keyin xatoni tekshir".
  • Ikkalasidan oldin await shart. Usiz test tekshiruv tugashini kutmasdan "o'tdi" deyishi mumkin. Haqiqiy Vitest 5 buni ushlaydi va testni yiqitadi: Promise returned by \expect(actual).resolves.toBe(expected)` was not awaited` ("Promise kutilmadi"). Natija oynasidagi model ham testni shu xabar bilan yiqitadi.

rejects.toThrow("yopiq") — rad etish xatosining xabarida shu bo'lak bor. Bu yerda toThrow funksiyani emas, Promise'ning xatosini tekshiradi.

6. Testlarni tanlash: skip, only, todo va filtr

jsx
import { describe, test, expect } from "vitest";

describe("menyu", () => {
  test("osh bor", () => {
    expect(["Osh"]).toContain("Osh");
  });
  test.skip("narxlar 2027 yildan", () => {
    expect(1).toBe(2);
  });
  test.todo("kechki menyu");
  test("manti bor", () => {
    expect(["Manti"]).toContain("Manti");
  });
});

Konsolda:

text
  ✓ menyu > osh bor
  ↓ menyu > narxlar 2027 yildan [skipped]
  □ menyu > kechki menyu
  ✓ menyu > manti bor
Testlar: 2 o'tdi, 1 o'tkazildi, 1 todo (jami 4)
  • test.skip — vaqtincha o'tkazib yuborish. Ichidagi xato (1 va 2) ishga tushmaydi.
  • test.todo("…") — reja: "bu test hali yozilmagan". Hisobotda ko'rinib turadi va unutilmaydi.
  • test.only — faylda faqat shu test(lar) ishlaydi, qolgani o'tkaziladi. Bitta testni tuzatayotganda qulay. Lekin only commit'ga tushsa, qolgan testlar jim o'tkaziladi. CI'da Vitest buni rad etadi (allowOnly — CI'da sukut bo'yicha false).

Belgilar haqiqiy terminaldagidek: ↓ — o'tkazildi, □ — todo. Terminalda jami qatori: Tests 2 passed | 1 skipped | 1 todo (4).

Terminaldan tanlash ham mumkin — fayl nomining bir qismi va -t (test nomi bo'yicha):

bash
npx vitest run cart -t "chegara" --reporter=verbose
text
 ↓ src/cart.test.js > cartTotal > ikki osh va bitta choy
 ↓ src/cart.test.js > cartTotal > bo'sh savat — 0
 ✓ src/cart.test.js > applyDiscount > chegara: aynan 200 000 — chegirma bor 3ms
 ↓ src/cart.test.js > applyDiscount > manfiy summa — xato

 Test Files  1 passed (1)
      Tests  1 passed | 3 skipped (4)

7. Sozlash: vitest.config.ts yoki vite.config.ts

7.1 Ikki joy

Vitest sozlamasi — test kaliti ostida. Uni ikki joyga yozish mumkin:

1-yo'l: vite.config.ts ichida — ilova va testlar bitta faylda. Birinchi qator TypeScript'ga test kalitini tanitadi:

ts
/// <reference types="vitest/config" />
import { defineConfig } from "vite";
import react from "@vitejs/plugin-react";

export default defineConfig({
  plugins: [react()],
  test: {
    environment: "jsdom",
  },
});

2-yo'l: alohida vitest.config.ts — defineConfig endi vitest/config dan:

ts
import { defineConfig } from "vitest/config";

export default defineConfig({
  test: {
    include: ["src/**/*.test.js"],
    environment: "node",
  },
});

Ikkala fayl ham bo'lsa — vitest.config ustun, vite.config umuman o'qilmaydi. Buni sinab ko'rdik: vite.config.js dagi globals: true e'tiborsiz qoldi va test ReferenceError: test is not defined bilan yiqildi. Qaysi yo'l? Test sozlamalari ilovanikidan farq qilsa — alohida fayl. vazifalar aynan shunday: uning vite.config.ts i .env.<mode> faylini talab qiladi, testga esa faqat JSX, taxallus va define kerak («Vazifalar qadami» da).

7.2 Fayl nomlari va include

Sukut bo'yicha Vitest shu andozadagi fayllarni qidiradi (Vitest 5.0.4 manba kodidan):

text
**/*.{test,spec}.?(c|m)[jt]s?(x)

Ya'ni cart.test.js, Tugma.spec.tsx, api.test.mts — topiladi. node_modules va .git — chiqarib tashlanadi. Nom bitta harfga xato bo'lsa:

bash
npx vitest run g/
text
No test files found, exiting with code 1

filter: g/
include: **/*.{test,spec}.?(c|m)[jt]s?(x)
exclude:  **/node_modules/**, **/.git/**

Bu papkada fayl global.tests.js deb nomlangan — tests ko'plikda, andozaga tushmaydi. Xabar qaysi andoza bilan qidirganini ko'rsatadi. Fayl nomini yoki include ni tekshiring.

Test faylini qayerga qo'yish — ikki uslub: kod yonida (src/cart.test.js) yoki alohida papkada (tests/, vazifalar da tekshiruv/). Ikkalasi ham to'g'ri — loyihada bittasini tanlang.

7.3 globals

Har test faylida import { test, expect } from "vitest" yozish shart emasmi? globals: true qilsangiz — describe, test, expect, vi global bo'ladi (Jest'dagidek):

ts
export default defineConfig({
  test: { globals: true },
});

Usiz importsiz fayl yiqiladi:

text
 FAIL  g/global.test.js [ g/global.test.js ]
ReferenceError: test is not defined
 ❯ g/global.test.js:1:1
      1| test("importsiz", () => {
       | ^

TypeScript ham bu globallarni bilishi uchun tsconfig ga "types": ["vitest/globals"] qo'shiladi (hujjat bo'yicha). vazifalar importlarni aniq yozadi — qayerdan kelgani ko'rinib turadi va tsconfig'ga tegish shart emas. Bir narsa esda tursin: Testing Library har testdan keyin ekranni o'zi tozalashi faqat globals: true bo'lganda ishlaydi. Shuning uchun kanon tozalashni o'zi ulaydi (afterEach(cleanup) — React Testing Library I da).

8. Muhit: node, jsdom, happy-dom

8.1 Node'da document yo'q

Vitest sukut bo'yicha testlarni node muhitida yurgizadi — brauzer obyektlari yo'q. Sahifa sarlavhasini yangilaydigan funksiya:

js
// src/title.js — sahifa sarlavhasida savatdagi taomlar soni
export function updateTitle(count) {
  document.title = count > 0 ? `(${count}) Bahor` : "Bahor";
}

Uning testi node muhitida:

text
 FAIL  src/title.test.js > savatda 3 ta taom — sarlavhada (3)
ReferenceError: document is not defined
 ❯ updateTitle src/title.js:3:3
      1| // Sahifa sarlavhasida savatdagi taomlar soni
      2| export function updateTitle(count) {
      3|   document.title = count > 0 ? `(${count}) Bahor` : "Bahor";
       |   ^

Yechim — DOM beradigan muhit. Butun loyiha uchun environment: "jsdom", yoki faqat bitta fayl uchun uning birinchi qatoriga izoh:

js
// @vitest-environment jsdom

Shundan keyin test o'tdi. Natija oynasida esa bu test darhol ishlaydi — u yerda haqiqiy brauzer:

jsx
import { test, expect } from "vitest";

function updateTitle(count) {
  document.title = count > 0 ? `(${count}) Bahor` : "Bahor";
}

test("savatda 3 ta taom — sarlavhada (3)", () => {
  updateTitle(3);
  expect(document.title).toBe("(3) Bahor");
});

test("bo'sh savat — faqat nom", () => {
  updateTitle(0);
  expect(document.title).toBe("Bahor");
});

Konsolda:

text
  ✓ savatda 3 ta taom — sarlavhada (3)
  ✓ bo'sh savat — faqat nom
Testlar: 2 o'tdi (jami 2)

8.2 jsdom va happy-dom

Ikki "brauzer o'rinbosari" bor, ikkalasi ham Node ichida ishlaydi va alohida o'rnatiladi (npm i -D jsdom yoki happy-dom):

  • jsdom — eski va eng keng tarqalgan; veb standartlarini to'liqroq bajaradi. vazifalar da shu (30.1.2).
  • happy-dom — yangiroq, tezlikka qaratilgan. Vitest hujjati uni "tezroq, lekin ba'zi API'lar yo'q" deb ta'riflaydi.

Biz shu kompyuterda (i5-12500H, Windows 11, Node 24.21.0) o'lchadik: cart.test.js (4 test) uch muhitda, har biri 5 marta, Vitest'ning Duration mediana qiymati. Ustunlar farqiga qarang:

Bitta test faylining vaqti muhitga qarab (mediana, 5 marta)
  • node0,26 s
  • happy-dom 21.0.11,17 s
  • jsdom 30.1.21,92 s

Manba: O'lchandi: Vitest 5.0.4, src/cart.test.js, --environment, i5-12500H, Windows 11, Node 24.21.0, 2026-10-20

Vaqtning deyarli hammasi muhitni tayyorlashga ketadi (hisobotda environment 94%), testlarning o'ziga emas. happy-dom bu yerda taxminan 1.6 baravar tez. Hajmi esa kattaroq: happy-dom 21.0.1 o'rnatilganda node_modules ga 9 paket va 20 MB qo'shildi (jsdom paketining o'zi 7 MB).

Qaysi birini tanlash? DOM'ga tayangan testlar ko'p bo'lsa va tezlik muhim bo'lsa — happy-dom'ni sinab ko'rish mumkin. Lekin biror test faqat happy-dom'da o'tsa yoki faqat unda yiqilsa — farq muhitda. Ikkalasi ham haqiqiy brauzer emas: jsdom 30.1.2 da <dialog> ning showModal() metodi yo'q, buni Browser Mode darsida haqiqiy Chrome bilan yechamiz. Muhitni almashtirgandan keyin butun to'plamni bir marta yurgizib ko'ring.

Sof mantiq (DOM'siz) testlarni esa doim node muhitida qoldiring — eng tez.

9. Watch rejimi va --ui

9.1 vitest — kuzatib turadi

npx vitest (run siz) terminalda ochiq qoladi. Fayl saqlanganda Vitest faqat shu o'zgarishga bog'liq testlarni qayta yurgizadi. cart.js ni o'zgartirsangiz — cart.test.js ishlaydi, boshqa fayllar emas. Vite'ning modullar grafigini (Vite I) bilgani uchun shunday tez.

Watch rejimida h bosilsa, tugmalar ro'yxati chiqadi (Vitest 5.0.4 manba kodidan):

Tugma Nima qiladi
a yoki Enter hamma testlarni qayta yurgizish
f faqat yiqilganlarni
p fayl nomi bo'yicha filtr
t test nomi bo'yicha filtr (regex)
q chiqish

Terminal TTY bo'lmasa (CI'da) yoki CI o'zgaruvchisi bo'lsa, vitest o'zi run rejimida ishlaydi — CI kutib qolmaydi.

9.2 --ui — brauzerdagi panel

npx vitest --ui — testlar daraxti, natijalar va modul grafigi brauzer sahifasida. Buning uchun alohida paket kerak:

text
 MISSING DEPENDENCY  Cannot find dependency '@vitest/ui'

Tarjimasi: "@vitest/ui bog'liqligi topilmadi". O'rnatiladi: npm i -D -E @vitest/ui@5.0.4 — versiyasi vitest niki bilan bir xil bo'lishi shart. vazifalar kanoniga --ui kirmagan (o'lchanmagan) — terminal va watch yetarli.

10. Vazifalar qadami: hamma testlar bitta vositada (holat 02)

10.1 Qaror — o'lchab

Ko'chirishdan oldin kanon o'lchadi (natijalar/02-vaqt.txt, devor soati, 3 marta):

Oldin (ikki vosita) Keyin (Vitest)
Sof mantiq, 255 test node:test 1.14–1.47 s 3.61–3.75 s
Komponentlar, 65 test 7.18–7.90 s 7.11–7.32 s
npm test jami 9.21–9.74 s 8.19–9.59 s

Halol natija: sof mantiq Vitest'da 2.5 baravar sekin (3.7 va 1.3 s) — Vitest har faylni Vite orqali o'giradi va alohida izolyatsiyada yurgizadi. Lekin umumiy npm test o'zgarmadi: Vitest ikki guruhni parallel yurgizadi. Evaziga — bitta watch, bitta hisobot, keyingi darsda bitta coverage, @/ taxallusi va vi.* API hamma joyda. Qaror: ko'chiramiz.

--no-isolate sof mantiqni 2.5 s ga tushirdi, lekin kanonga kirmadi: izolyatsiyasiz globallar va soxtalar bir fayldan boshqasiga o'tib qoladi.

Bir marta aytib qo'yamiz: npm ci dan keyingi birinchi (sovuq) ishga tushirish ancha sekin — qism davomida 44 dan 110 soniyagacha bo'ldi (vaqtning ko'pi jsdom muhitini tayyorlash, Windows'da antivirus ham). Keyingilari — 7–10 soniya.

10.2 Branch va vitest.config.ts

  • Branch: chore/vitest-hammasi
bash
git switch -c chore/vitest-hammasi

Paket o'rnatilmaydi — Vitest 17-qismdan beri bor. vitest.config.ts kanondan (izohlar telefon uchun bo'lingan):

ts
// vitest.config.ts — hamma testlar bitta vositada (22/#02).
// Ikki "loyiha" (project): sof mantiqqa DOM kerak emas
// (node — tez), komponentlarga — jsdom.
// vite.config.ts ishlatilmaydi: u .env.<mode> ni talab qiladi,
// testga esa faqat JSX, taxallus va define kerak
import { defineConfig } from "vitest/config";
import { resolve } from "node:path";
import react from "@vitejs/plugin-react";

export default defineConfig({
  plugins: [react()],
  // 21/#19: vite.config.ts dagi define (u bu yerda o'qilmaydi)
  define: { __RELIZ__: JSON.stringify("test") },
  // 20/#02: @/ taxallusi — vite.config.ts dagidek
  resolve: { alias: { "@": resolve(import.meta.dirname, "src") } },
  test: {
    projects: [
      {
        // extends: true — yuqoridagi plugins/define/resolve
        // meros olinadi
        extends: true,
        test: {
          name: "mantiq",
          environment: "node",
          include: ["tekshiruv/**/*.test.js"],
        },
      },
      {
        extends: true,
        test: {
          name: "komponent",
          environment: "jsdom",
          include: ["tekshiruv/**/*.test.tsx"],
          setupFiles: ["tekshiruv/vitest-sozlash.ts"],
        },
      },
      {
        // Haqiqiy mashq API (internet kerak) — npm test da YO'Q,
        // faqat npm run test:tarmoq (--project tarmoq)
        extends: true,
        test: {
          name: "tarmoq",
          environment: "node",
          include: ["tekshiruv/**/*.tarmoq.js"],
        },
      },
    ],
  },
});
  • projects — bitta Vitest ichida bir nechta "loyiha", har biri o'z muhiti va fayllari bilan. Sof mantiq — node (tez), komponentlar — jsdom.
  • extends: true — yuqoridagi umumiy plugins, define, resolve har loyihaga meros.
  • include — har loyiha o'z andozasi bilan: *.test.js, *.test.tsx, *.tarmoq.js. Oxirgisi sukut andozasiga tushmaydi — shuning uchun npm test uni ko'rmaydi.
  • setupFiles — har test faylidan oldin bajariladigan fayl (tozalash, soxta fetch, i18n).

package.json skriptlari:

diff
-    "test": "node --test && vitest run",
-    "test:tarmoq": "node --test tekshiruv/api.tarmoq.js",
+    "test": "vitest run --project mantiq --project komponent",
+    "test:kuzat": "vitest --project mantiq --project komponent",
+    "test:tarmoq": "vitest run --project tarmoq",

10.3 37 ta faylni ko'chirish

Qo'lda emas — kanon kichik kodmod (kodni avtomatik o'zgartiradigan skript) yozdi. U 37 ta faylda quyidagi almashtirishlarni qildi:

node:test Vitest
from "node:test" from "vitest"
mock.fn() vi.fn()
fn.mock.callCount() fn.mock.calls.length
fn.mock.calls[0].arguments fn.mock.calls[0]
mock.method(obj, "m", …) vi.spyOn(obj, "m").mockImplementation(…)
mock.timers.tick(300) vi.advanceTimersByTime(300)
t.after(fn) onTestFinished(fn)

vi.fn, vi.spyOn va soxta taymerlarni Vitest II darsida to'liq o'rganamiz. Diqqat qiling: node:assert/strict tekshiruvlari qoldi. Vitest assert tashlagan AssertionError ni ham o'zi chiroyli ko'rsatadi. Yangi testlar esa expect bilan yoziladi.

Ko'chirishda bitta tuzoq chiqdi (kanon o'lchadi). Bitta faylning (taymer.test.js) diff'i:

diff
-beforeEach(() => mock.timers.enable({ apis: ["setTimeout"] }));
-afterEach(() => mock.timers.reset());
+beforeEach(() =>
+  vi.useFakeTimers({ toFake: ["setTimeout", "clearTimeout"] }),
+);
+afterEach(() => vi.useRealTimers());

node:test da apis: ["setTimeout"] clearTimeout ni ham soxtalaydi. Vitest'ning toFake: ["setTimeout"] esa faqat aytilganini soxtalaydi. Birinchi urinishda kechiktir testi yiqildi: haqiqiy clearTimeout soxta taymerni bekor qila olmadi. To'g'risi — ikkalasini yozish. Bir xil ko'ringan ikki API mayda farq qilishi mumkin — ko'chirgandan keyin testlar yashil ekaniga ishonmasdan, har yiqilishni o'qing.

10.4 test:tarmoq tuzatildi

O'tgan darsda topilgan eskirgan test endi npm run test:tarmoq bilan Vitest'da ishlaydi va tuzatildi (izoh telefon uchun bo'lingan):

diff
-  assert.equal(await api.ochir(3), null);
+  // 22/#02: DELETE 204 — ochir() undefined qaytaradi
+  // (api.test.js ham shuni kutadi). Bu test npm test da yo'q
+  // edi va eskirib qolgan (v11 da ham yiqilardi: null kutardi)
+  // — hech kim ishga tushirmagan
+  assert.equal(await api.ochir(3), undefined);

test:tarmoq — 2/2.

10.5 Natija

Kanon tekshiruvi (natijalar/tekshiruv-02.txt) — npm test ning yakuniy qatorlari:

text
 Test Files  49 passed (49)
      Tests  320 passed (320)
   Duration  59.49s (environment 78%, setup 16%, import 2%, tests 2%, transform 1%)

320 = 255 + 65 — hamma testlar bitta hisobotda. Bu yugurish build'dan keyin, sovuq keshda bo'lgan: vaqtning 78 % i — muhit. Lint, format, tip, knip — toza. Ilova JS — 206.7 KB gzip, o'zgarmadi: testlar build'ga tushmaydi. Kursning brauzer tekshiruvlari 159, 72, 100, 77, 81 — hammasi o'tdi, axe — 0.

TESTLAR.md dagi birinchi bo'shliq yopildi.

bash
git add -A
git commit -m "chore: node:test → Vitest (mantiq/komponent/tarmoq loyihalari); test:tarmoq tuzatildi"

11. Ko'p uchraydigan xatolar

Belgi Sabab Davosi
expected {…} to be {…} — ikkalasi bir xil ko'rinadi obyekt toBe bilan toEqual / toStrictEqual
toThrow o'rniga testning o'zi xato bilan yiqiladi expect(f(-1)) — funksiya chaqirilib qo'yilgan expect(() => f(-1)).toThrow()
expected 0.30000000000000004 to be 0.3 kasr son toBe bilan toBeCloseTo
ReferenceError: document is not defined node muhiti environment: "jsdom" yoki fayl izohi
No test files found fayl nomi andozaga tushmaydi *.test.js yoki include
ReferenceError: test is not defined import yo'q, globals o'chiq import yozing yoki globals: true
Asinxron test doim yashil resolves/rejects dan oldin await yo'q await expect(…)
vite.config dagi test sozlamasi ishlamaydi yonida vitest.config bor — u ustun bitta joyda saqlang

12. Mashqlar

Mashqlar kurs/mashqlar/22/02-vitest-asoslari/ da. Jonli yechimlarni «Ishga tushir» bilan sinang.

1-mashq (oson): bo'sh joylarni to'ldiring

  • Ikkita alohida, lekin tarkibi bir xil obyektni solishtirish: expect(a).(b)
  • Xatoni kutish uchun expect ga nima beriladi:
  • Kasr sonni solishtiradigan matcher:
  • DOM kerak bo'lgan test faylining birinchi qatori: // @vitest-environment
  • Watch rejimisiz, bir marta yurgizish: npx vitest
Yechim

toEqual tarkibni solishtiradi, toBe esa havolani — alohida obyektlar uchun toBe doim yiqiladi. toThrow xatoni ushlashi uchun unga funksiya beriladi: () => f(). toBeCloseTo — 0.1 + 0.2 kabi kasr xatolari uchun. jsdom — Node ichidagi DOM. vitest run — CI va npm test uchun; vitest — kuzatuv.

2-mashq (o'rta): yetkazib berish narxi

«Bahor» yetkazib berish narxi: 3 km gacha (3 ham) — bepul, undan keyin har km uchun 2 000 so'm (to'liq km: 4.2 km — 5 km deb hisoblanadi). Manfiy masofa — RangeError. Funksiya tayyor, unga kamida 5 ta test yozing: chegarani (3 va 3.1), oddiy holatni, kasr km ni va xatoni tekshiring.

js
function deliveryPrice(km) {
  if (km < 0) throw new RangeError("Masofa manfiy bo'lmaydi");
  if (km <= 3) return 0;
  return (Math.ceil(km) - 3) * 2000;
}

Ishora: yaxlitlash — Math.ceil; xato — «Xato kutish: toThrow» bo'limidagi kabi funksiyaga o'rab.

Yechim
jsx
import { describe, test, expect } from "vitest";

function deliveryPrice(km) {
  if (km < 0) throw new RangeError("Masofa manfiy bo'lmaydi");
  if (km <= 3) return 0;
  return (Math.ceil(km) - 3) * 2000;
}

describe("deliveryPrice", () => {
  test("yaqin — bepul", () => {
    expect(deliveryPrice(1)).toBe(0);
  });
  test("chegara: aynan 3 km — bepul", () => {
    expect(deliveryPrice(3)).toBe(0);
  });
  test("3.1 km — 4 km deb, 2 000 so'm", () => {
    expect(deliveryPrice(3.1)).toBe(2000);
  });
  test("4.2 km — 5 km deb, 4 000 so'm", () => {
    expect(deliveryPrice(4.2)).toBe(4000);
  });
  test("10 km — 14 000 so'm", () => {
    expect(deliveryPrice(10)).toBe(14000);
  });
  test("manfiy — RangeError", () => {
    expect(() => deliveryPrice(-2)).toThrow(RangeError);
  });
});

Konsolda:

text
  ✓ deliveryPrice > yaqin — bepul
  ✓ deliveryPrice > chegara: aynan 3 km — bepul
  ✓ deliveryPrice > 3.1 km — 4 km deb, 2 000 so'm
  ✓ deliveryPrice > 4.2 km — 5 km deb, 4 000 so'm
  ✓ deliveryPrice > 10 km — 14 000 so'm
  ✓ deliveryPrice > manfiy — RangeError
Testlar: 6 o'tdi (jami 6)

Eng qimmatli testlar — chegara atrofida: 3 va 3.1. Math.ceil o'rniga Math.floor yoki Math.round yozilsa, 3.1 km (expected +0 to be 2000) va 4.2 km (expected 2000 to be 4000) testlari yiqiladi.

3-mashq (qiyin): buyurtma xulosasi

orderSummary(items) funksiyasini yozing va unga testlar yozing. U obyekt qaytaradi: { count, total, mostExpensive } — taomlar soni (qty maydonlari yig'indisi), jami narx va eng qimmat taom nomi. Taom — { name, price, qty }. Bo'sh savat — { count: 0, total: 0, mostExpensive: null }. Testlarda: obyektni toStrictEqual bilan, bo'sh holatni, va natijada ortiqcha maydon yo'qligini tekshiring. Bitta test asinxron bo'lsin: funksiyaning Promise versiyasi (sendOrder — 100 ms dan keyin xulosa qaytaradi) resolves bilan.

Ishora: reduce — Massiv metodlari; toStrictEqual ortiqcha yoki undefined maydonni ham ko'radi — «Tenglik uch xil» bo'limi.

Yechim
jsx
import { describe, test, expect } from "vitest";

function orderSummary(items) {
  if (items.length === 0) {
    return { count: 0, total: 0, mostExpensive: null };
  }
  const count = items.reduce((s, i) => s + i.qty, 0);
  const total = items.reduce((s, i) => s + i.price * i.qty, 0);
  const top = items.reduce((a, b) => (b.price > a.price ? b : a));
  return { count, total, mostExpensive: top.name };
}

function sendOrder(items) {
  return new Promise((resolve) => {
    setTimeout(() => resolve(orderSummary(items)), 100);
  });
}

const cart = [
  { name: "Lag'mon", price: 28000, qty: 1 },
  { name: "Osh", price: 35000, qty: 2 },
  { name: "Ko'k choy", price: 5000, qty: 3 },
];

describe("orderSummary", () => {
  test("uch xil taom", () => {
    expect(orderSummary(cart)).toStrictEqual({
      count: 6,
      total: 113000,
      mostExpensive: "Osh",
    });
  });
  test("bo'sh savat", () => {
    expect(orderSummary([])).toStrictEqual({
      count: 0,
      total: 0,
      mostExpensive: null,
    });
  });
  test("faqat uchta maydon", () => {
    expect(Object.keys(orderSummary(cart))).toHaveLength(3);
  });
  test("yuborish — xulosa qaytadi", async () => {
    await expect(sendOrder(cart)).resolves.toMatchObject({
      total: 113000,
    });
  });
});

Konsolda:

text
  ✓ orderSummary > uch xil taom
  ✓ orderSummary > bo'sh savat
  ✓ orderSummary > faqat uchta maydon
  ✓ orderSummary > yuborish — xulosa qaytadi
Testlar: 4 o'tdi (jami 4)

Hisob: 28 000 + 2 × 35 000 + 3 × 5 000 = 113 000 so'm. Soni: 1 + 2 + 3 = 6 ta. toStrictEqual ikki narsani birga kafolatlaydi: qiymatlar to'g'ri va ortiqcha maydon yo'q. reduce boshlang'ich qiymatsiz bo'sh massivda xato tashlaydi — shuning uchun bo'sh holat birinchi tekshiriladi. Shu tartibni buzib ko'ring: "bo'sh savat" testi TypeError bilan yiqiladi.

4-mashq: vazifalar qadami

chore/vitest-hammasi branch'ida «Vazifalar qadami» ni bajaring: vitest.config.ts dagi uch loyiha, package.json skriptlari, 37 ta test faylida importlar va mock almashtirishlari, taymer.test.js dagi toFake, api.tarmoq.js tuzatishi. npm run check toza bo'lsin. Keyin:

  1. npm test ni ikki marta ishga tushiring va Duration ni solishtiring.
  2. taymer.test.js da toFake dan "clearTimeout" ni olib tashlang va testlarni yurgizing.
  3. npm run test:kuzat ni oching, src/qidiruv.ts ga bo'sh qator qo'shib saqlang — qaysi testlar qayta ishladi?
Yechim
  1. Birinchisi (sovuq) — o'nlab soniya, ikkinchisi — 7–10 soniya. Farq — jsdom muhitini tayyorlash va Vite keshi.
  2. kechiktir testlaridan biri yiqiladi: haqiqiy clearTimeout soxta taymerni bekor qila olmaydi va ishlovchi kutilmaganda chaqiriladi. "clearTimeout" ni qaytaring.
  3. Faqat qidiruv.ts ni import qiladigan test fayllari (qidiruv.test.js va uni ishlatadigan komponent testlari). Vitest modullar grafigiga qarab tanlaydi.

13. Real ishda

  • Vite loyihalarida (React, Vue, Svelte) Vitest — sukut bo'yicha tanlov. Create-vite shablonlariga u qo'shilmaydi, lekin o'rnatish bitta buyruq.
  • Jest'li eski loyihalar ko'p — API deyarli bir xil, ko'chirish ko'pincha import va jest.fn → vi.fn almashtirish (Jest va eski test muhitlari).
  • Intervyu savollari: "toBe va toEqual farqi?", "toThrow ga nega funksiya beriladi?", "jsdom nima va nega kerak?", "Vitest Jest'dan nimasi bilan farq qiladi?", "Asinxron kodni qanday testlaysiz?".

Xulosa

  • Vitest Vite sozlamasini qayta ishlatadi; test — describe + test + expect(…).matcher(…), fayl — *.test.* / *.spec.*.
  • toBe — Object.is (oddiy qiymat), toEqual — tarkib, toStrictEqual — tarkib + undefined maydonlar va tur.
  • Xato — expect(() => f()).toThrow(…); asinxron — await expect(p).resolves/rejects.
  • Sozlama vitest.config.ts da (u vite.config dan ustun) yoki vite.config.ts dagi test blokida; globals, include, environment, projects.
  • Muhit: node (eng tez), happy-dom, jsdom — o'lchovimizda 0.26 / 1.17 / 1.92 s; vaqtning ko'pi muhitni tayyorlash.
  • vazifalar: 320 test bitta Vitest'da, uch loyiha; sof mantiq sekinlashdi, umumiy vaqt o'zgarmadi — halol o'lchab qabul qilindi.

Keyingi dars: Vitest II: mock, spy, taymerlar va coverage — vi.fn, vi.spyOn, soxta taymerlar va vi.mock; qaysi kod hech qachon ishlamaganini coverage bilan ko'ramiz va chegara qo'yamiz.

Manbalar

  • Vitest: "Getting Started", "Configuring Vitest" (test.include, globals, environment, projects), "Test Environment", "expect" API, "CLI" — vitest.dev
  • Vitest 5.0.4 manba kodi: sukut include andozasi, watch tugmalari ro'yxati (npm paketi, dist/)
  • jsdom — github.com/jsdom/jsdom; happy-dom — github.com/capricorn86/happy-dom
  • O'z o'lchovimiz: Vitest 5.0.4, jsdom 30.1.2, happy-dom 21.0.1, i5-12500H, Node 24.21.0 (2026-10-20)
  • Kanon: vazifalar holat 02 (vitest.config.ts, package.json, tekshiruv/taymer.test.js, api.tarmoq.js), natijalar/02-vaqt.txt, tekshiruv-02.txt (2026-10-19)
Ulashish:Telegram'da

Izohlar (0)

Izoh yozish uchun kiring.

  • Hozircha izoh yo'q. Birinchi bo'ling!
Vitest I: sozlash va birinchi testlar — describe, test, expect va matcherlar — IlmHamroh