Mundarija (43)
- Bu darsda
- 1. Nega bu kerak?
- 2. O'rnatish va birinchi test
- 2.1 O'rnatish
- 2.2 Kod va test fayli
- 2.3 Ishga tushirish
- 3. Natija oynasida test
- 3.1 O'quv modeli — halol eslatma
- 3.2 Birinchi jonli test
- 4. Yiqilgan testni o'qish
- 4.1 Jonli: chegaradagi xato
- 4.2 Haqiqiy terminalda
- 5. Matcherlar
- 5.1 Tenglik uch xil: toBe, toEqual, toStrictEqual
- 5.2 Boshqa ko'p ishlatiladigan matcherlar
- 5.3 Xato kutish: toThrow
- 5.4 Asinxron kod: await, resolves, rejects
- 6. Testlarni tanlash: skip, only, todo va filtr
- 7. Sozlash: vitest.config.ts yoki vite.config.ts
- 7.1 Ikki joy
- 7.2 Fayl nomlari va include
- 7.3 globals
- 8. Muhit: node, jsdom, happy-dom
- 8.1 Node'da document yo'q
- 8.2 jsdom va happy-dom
- 9. Watch rejimi va --ui
- 9.1 vitest — kuzatib turadi
- 9.2 --ui — brauzerdagi panel
- 10. Vazifalar qadami: hamma testlar bitta vositada (holat 02)
- 10.1 Qaror — o'lchab
- 10.2 Branch va vitest.config.ts
- 10.3 37 ta faylni ko'chirish
- 10.4 test:tarmoq tuzatildi
- 10.5 Natija
- 11. Ko'p uchraydigan xatolar
- 12. Mashqlar
- 1-mashq (oson): bo'sh joylarni to'ldiring
- 2-mashq (o'rta): yetkazib berish narxi
- 3-mashq (qiyin): buyurtma xulosasi
- 4-mashq: vazifalar qadami
- 13. Real ishda
- Xulosa
- Manbalar
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) vaexpect(qiymat).toBe(kutilgan)(tekshiruv) dan iborat. Fayl nomi*.test.jsyoki*.spec.tsbo'lsa,npx vitest rununi 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,expectva asosiy matcherlarni (toBe,toEqual,toStrictEqual,toThrow,resolves/rejects) ishlatasiz.vitest.config.tsvavite.config.tsdagitestbloki farqini,include,globalsvaenvironmentsozlamalarini bilasiz.- jsdom, happy-dom va node muhitini o'lchov bilan taqqoslaysiz; watch rejimi va
--uini bilasiz. vazifalardaginode:testtestlarini 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:testda 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:
npm init -y
npm pkg set type=module
npm i -D -E vitest@5.0.4added 35 packages, and audited 36 packages in 19s
12 packages are looking for funding
run `npm fund` for details
found 0 vulnerabilities35 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:
// «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:
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:testdagidescribebilan 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.expectqiymatni "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
npx vitest run --reporter=verbose 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:
{
"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. Udescribe,test,expect, matcherlar vavining eng ko'p ishlatiladigan qismini takrorlaydi. Xabar matni haqiqiy Vitest'ga o'xshaydi, lekin ayni emas. Haqiqiy chiqish — terminalda: uni har bo'limda pastdagitextblokida 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:
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:
✓ 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?
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:
✓ 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 >):
❯ 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 testham 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:
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:
✓ 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:
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 stringTarjimasi: "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
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:
✓ 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
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:
✓ 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:
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:
✓ 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
awaitshart. 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
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:
✓ 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 (1va2) 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. Lekinonlycommit'ga tushsa, qolgan testlar jim o'tkaziladi. CI'da Vitest buni rad etadi (allowOnly— CI'da sukut bo'yichafalse).
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):
npx vitest run cart -t "chegara" --reporter=verbose ↓ 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:
/// <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:
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):
**/*.{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:
npx vitest run g/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):
export default defineConfig({
test: { globals: true },
});Usiz importsiz fayl yiqiladi:
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:
// src/title.js — sahifa sarlavhasida savatdagi taomlar soni
export function updateTitle(count) {
document.title = count > 0 ? `(${count}) Bahor` : "Bahor";
}Uning testi node muhitida:
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:
// @vitest-environment jsdomShundan keyin test o'tdi. Natija oynasida esa bu test darhol ishlaydi — u yerda haqiqiy brauzer:
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:
✓ 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.
vazifalarda 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:
- 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:
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
git switch -c chore/vitest-hammasiPaket o'rnatilmaydi — Vitest 17-qismdan beri bor. vitest.config.ts kanondan (izohlar telefon uchun bo'lingan):
// 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 umumiyplugins,define,resolvehar loyihaga meros.include— har loyiha o'z andozasi bilan:*.test.js,*.test.tsx,*.tarmoq.js. Oxirgisi sukut andozasiga tushmaydi — shuning uchunnpm testuni ko'rmaydi.setupFiles— har test faylidan oldin bajariladigan fayl (tozalash, soxtafetch, i18n).
package.json skriptlari:
- "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:
-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):
- 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:
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.
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
expectga 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.
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
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:
✓ 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
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:
✓ 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:
npm testni ikki marta ishga tushiring vaDurationni solishtiring.taymer.test.jsdatoFakedan"clearTimeout"ni olib tashlang va testlarni yurgizing.npm run test:kuzatni oching,src/qidiruv.tsga bo'sh qator qo'shib saqlang — qaysi testlar qayta ishladi?
Yechim
- Birinchisi (sovuq) — o'nlab soniya, ikkinchisi — 7–10 soniya. Farq — jsdom muhitini tayyorlash va Vite keshi.
kechiktirtestlaridan biri yiqiladi: haqiqiyclearTimeoutsoxta taymerni bekor qila olmaydi va ishlovchi kutilmaganda chaqiriladi."clearTimeout"ni qaytaring.- Faqat
qidiruv.tsni import qiladigan test fayllari (qidiruv.test.jsva 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.fnalmashtirish (Jest va eski test muhitlari). - Intervyu savollari: "
toBevatoEqualfarqi?", "toThrowga 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 +undefinedmaydonlar va tur.- Xato —
expect(() => f()).toThrow(…); asinxron —await expect(p).resolves/rejects. - Sozlama
vitest.config.tsda (uvite.configdan ustun) yokivite.config.tsdagitestblokida;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
includeandozasi, 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:
vazifalarholat 02 (vitest.config.ts,package.json,tekshiruv/taymer.test.js,api.tarmoq.js),natijalar/02-vaqt.txt,tekshiruv-02.txt(2026-10-19)
Izohlar (0)
Izoh yozish uchun kiring.
- Hozircha izoh yo'q. Birinchi bo'ling!