Test Coverage — istanbul bilan

~15 daq · Express · Testing

Muammodan boshlaylik

Testlar yozdingiz. Lekin savol tug'iladi: "Kodimning qanchasini testladim? Qaysi qismlari hali testlanmagan?"

Bitta if shart — ikki yo'l. Siz faqat bittasini testladingiz. Ikkinchisi — testlanmagan. Lekin siz bilmaysiz.

Coverage — testlar qaysi kod qatorlarini "bosib o'tganini" ko'rsatadi.


Coverage nima?

Coverage — testlar bajarilganda kodingizning qaysi qismi ishga tushdi, qaysi qismi ishga tushmadi.

utils/math.js:
─────────────────────────────────────────
export const qo'sh = (a, b) => a + b;     ← ✅ testlandi
                                           
export const bo'l = (a, b) => {            ← ✅ testlandi
  if (b === 0) throw new Error('Nol!');   ← ❌ bu qator testlanmadi
  return a / b;
};

Siz bo'l(10, 2) ni testladingiz — nol holati testlanmadi.


Hayotiy o'xshatma

Binoni tekshirish. Inspektör har xonaga kirdi — tekshirildi. Kirilmagan xona — tekshirilmadi. Coverage hisoboti: "12 xonadan 9 tasi tekshirildi. 3 tasi — kirilmadi."

Testlanmagan kod — inspektör kirmagan xona. U yerda nima bor — bilmaysiz.


Jest bilan coverage

Jest ichida Istanbul o'rnatilgan — alohida paket kerak emas:

npx jest --coverage

Yoki package.json:

{
  "scripts": {
    "test": "jest",
    "test:coverage": "jest --coverage"
  }
}

Hisobot

----------|---------|----------|---------|---------|
File      | % Stmts | % Branch | % Funcs | % Lines |
----------|---------|----------|---------|---------|
math.js   |   85.71 |    66.67 |     100 |   85.71 |
user.js   |   100   |    100   |     100 |   100   |
----------|---------|----------|---------|---------|
  • Statements — bajariladigan qatorlar (%)
  • Branches — if/else, ternary shartlarining yo'llari (%)
  • Functions — chaqirilgan funksiyalar (%)
  • Lines — kod qatorlari (%)

💡 Branch coverage eng muhimi — if/else ning ikki yo'li ham testlanganmi?


HTML hisobot

npx jest --coverage --coverageReporters=html

coverage/lcov-report/index.html — brauzerde oching. Har qator yashil (testlandi) yoki qizil (testlanmadi) ko'rsatiladi.


Coverage chegarasi qo'yish

jest.config.js:

export default {
  coverageThreshold: {
    global: {
      statements: 80, // ← 80% dan past bo'lsa — test muvaffaqiyatsiz
      branches:   75,
      functions:  80,
      lines:      80,
    },
  },
};

CI/CD da bu foydali: test o'tsa ham coverage past bo'lsa — deploy to'xtatiladi.


Qaysi fayllarni o'lchash

// jest.config.js
export default {
  collectCoverageFrom: [
    'src/**/*.js',        // ← src ichidagi barcha JS fayllar
    '!src/server.js',     // ← server.js o'lchangilmasin
    '!src/**/*.test.js',  // ← test fayllar o'lchangilmasin
  ],
};

100% coverage yaxshimi?

Ko'pchilik yangi boshlovchilar 100% ga intiladi. Bu to'g'ri emas.

// Bu qatorni testlash qiyin va ahamiyati kam
app.listen(3000, () => console.log('Server ishga tushdi'));

Amaliy standart:

Qism Tavsiya
Utils / helpers 90–100%
Service funksiyalar 80–90%
Route handlerlar 70–80%
Server/config fayllar o'lchangilmasin

💡 "80% coverage yomon testlarga qaraganda yaxshiroq 60%". Sifatli test — ko'p holatni tekshiradigan test, qator bosib o'tadigan test emas.


Amaliy misol

// utils/validator.js
export const emailTekshir = (email) => {
  if (!email) return false;                       // ← holat 1
  return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email); // ← holat 2
};
// utils/validator.test.js
import { emailTekshir } from './validator.js';

test('bo\'sh email — false', () => {
  expect(emailTekshir('')).toBe(false);   // ← holat 1 testlandi
  expect(emailTekshir(null)).toBe(false);
});

test('to\'g\'ri email — true', () => {
  expect(emailTekshir('ali@test.com')).toBe(true); // ← holat 2 testlandi
});

test('noto\'g\'ri email — false', () => {
  expect(emailTekshir('ali')).toBe(false);
});

Coverage: Statements 100%, Branches 100%.


Tez-tez uchraydigan xatolar

1. Coverage ni yaxshilash uchun yolg'on test yozish

// ❌ — faqat qatorni "bosib o'tish" uchun
test('bo\'l funksiyasi', () => {
  bo'l(10, 2); // expect yo'q — hech narsa tekshirilmaydi!
});

// ✅ — natija tekshirilsin
test('bo\'l funksiyasi', () => {
  expect(bo'l(10, 2)).toBe(5);
  expect(() => bo'l(10, 0)).toThrow('Nol!');
});

2. Test fayllarni coverage ga qo'shib qo'yish

// jest.config.js
collectCoverageFrom: [
  'src/**/*.js',
  '!src/**/*.test.js', // ← test fayllarni o'lchangilmasin
]

Xulosa

  • Coverage — testlar qaysi kod qatorini ishlatganini ko'rsatadi
  • jest --coverage — hisobot; HTML versiyasi vizual
  • Branch coverage eng muhimi — if/else ikki yo'li ham testlansinmi
  • 80% — amaliy standart; 100% ga intilish kerak emas
  • coverageThreshold — CI da past coverage bo'lsa deploy to'xtatiladi

Keyingi dars: 56-dars: Compression — gzip, brotli