farkmt2official 1
farkmt2official
kralhakan2009 1
kralhakan2009
Vahsi Uzman 1
Vahsi Uzman
Bvural41 1
Bvural41
Hikaye Ekle

[NODE JS] Test Coverage Raporu Oluşturma

nodejs.png


[NODE JS] Test Coverage Raporu Oluşturma

Merhaba arkadaşlar, bugün test yazmanın bir adım ötesine geçip, test coverage yani test kapsama raporu oluşturmayı öğreneceğiz. Test yazmak güzel de, yazdığınız testler kodunuzun yüzde kaçını kapsıyor biliyor musunuz? İşte coverage raporu tam olarak bunu gösterir. İlk kez coverage raporu çıkardığımda yüzde 30 görmüştüm, utanmıştım doğrusu.

Test coverage, yazdığınız testlerin kaynak kodunuzu ne kadar kapsadığını gösteren bir metriktir. Dört farklı coverage metriği vardır. Statement coverage, kodunuzdaki her ifadenin en az bir kez çalıştırılıp çalıştırılmadığını gösterir. Branch coverage, her koşulun her dalının (if/else) test edilip edilmediğini gösterir. Function coverage, her fonksiyonun en az bir kez çağrılıp çağrılmadığını kontrol eder. Line coverage ise her satırın en az bir kez çalıştırılıp çalıştırılmadığını gösterir.

Jest'te coverage raporu almak inanılmaz kolaydır. Sadece --coverage flag'ini eklersiniz ve Jest otomatik olarak Istanbul/NYC kütüphanesini kullanarak detaylı bir rapor üretir. Terminal çıktısı yanı sıra HTML formatında görsel bir rapor da oluşturur. Bu HTML raporu browser'da açtığınızda hangi satırların test edildiğini, hangilerinin edilmediğini renkli olarak görürsünüz. Yeşil satırlar test edilmiş, kırmızı satırlar test edilmemiş demektir.

Mocha kullanıyorsanız Istanbul'un CLI aracı olan NYC'yi kullanmanız gerekir. npx nyc mocha komutu ile testlerinizi coverage ile çalıştırabilirsiniz. NYC de benzer şekilde terminal çıktısı ve HTML raporu üretir.

Coverage eşik değerleri belirlemenizi öneririm. Jest'te coverageThreshold konfigürasyonu ile minimum coverage yüzdelerini belirleyebilirsiniz. Eğer testler bu eşiğin altında kalırsa build başarısız olur. Bu özellikle CI/CD pipeline'larında çok önemlidir. Genellikle yüzde 80 iyi bir hedef olarak kabul edilir ama bu projeye göre değişir.

Coverage raporunda dikkat etmeniz gereken önemli bir nokta var. Yüzde 100 coverage hedefiniz olmasın. Evet, yanlış duymadınız. Yüzde 100 coverage peşinde koşmak sizi anlamsız testler yazmaya iter. Getter/setter'lar, basit wrapper fonksiyonlar için test yazmak zaman kaybıdır. Kritik iş mantığınızın iyi test edilmiş olması daha önemlidir.

Coverage raporunu CI/CD pipeline'ınıza entegre edin. GitHub Actions, GitLab CI gibi araçlarda coverage badge'i gösterebilirsiniz. Bu hem motivasyon sağlar hem de PR review'larda coverage düşüşünü yakalamanıza yardımcı olur. Codecov veya Coveralls gibi servislerle de entegre edebilirsiniz.

Kod:
// calculator.js - Coverage analizi yapılacak modül
class Calculator {
  constructor() {
    this.gecmis = [];
  }

  topla(a, b) {
    const sonuc = a + b;
    this.gecmis.push({ islem: 'toplama', a, b, sonuc });
    return sonuc;
  }

  cikar(a, b) {
    const sonuc = a - b;
    this.gecmis.push({ islem: 'cikarma', a, b, sonuc });
    return sonuc;
  }

  carp(a, b) {
    const sonuc = a * b;
    this.gecmis.push({ islem: 'carpma', a, b, sonuc });
    return sonuc;
  }

  bol(a, b) {
    if (b === 0) {
      throw new Error('Sıfıra bölme hatası');
    }
    const sonuc = a / b;
    this.gecmis.push({ islem: 'bolme', a, b, sonuc });
    return sonuc;
  }

  mod(a, b) {
    if (b === 0) {
      throw new Error('Sıfıra mod alma hatası');
    }
    return a % b;
  }

  us(taban, us) {
    if (us < 0) {
      throw new Error('Negatif üs desteklenmiyor');
    }
    return Math.pow(taban, us);
  }

  gecmisiGetir() {
    return [...this.gecmis];
  }

  gecmisiTemizle() {
    this.gecmis = [];
  }

  sonIslem() {
    if (this.gecmis.length === 0) {
      return null;
    }
    return this.gecmis[this.gecmis.length - 1];
  }
}

module.exports = Calculator;

// calculator.test.js - Coverage icin detayli test
const Calculator = require('./calculator');

describe('Calculator - Coverage Odaklı Test', () => {
  let calc;

  beforeEach(() => {
    calc = new Calculator();
  });

  describe('Temel İşlemler', () => {
    test('toplama doğru çalışmalı', () => {
      expect(calc.topla(5, 3)).toBe(8);
      expect(calc.topla(-1, 1)).toBe(0);
    });

    test('çıkarma doğru çalışmalı', () => {
      expect(calc.cikar(10, 4)).toBe(6);
    });

    test('çarpma doğru çalışmalı', () => {
      expect(calc.carp(3, 7)).toBe(21);
    });

    test('bölme doğru çalışmalı', () => {
      expect(calc.bol(20, 4)).toBe(5);
    });

    test('sıfıra bölmede hata fırlatmalı', () => {
      expect(() => calc.bol(10, 0)).toThrow('Sıfıra bölme hatası');
    });

    test('mod işlemi doğru çalışmalı', () => {
      expect(calc.mod(10, 3)).toBe(1);
    });

    test('sıfıra mod almada hata fırlatmalı', () => {
      expect(() => calc.mod(10, 0)).toThrow('Sıfıra mod alma hatası');
    });

    test('üs alma doğru çalışmalı', () => {
      expect(calc.us(2, 3)).toBe(8);
    });

    test('negatif üste hata fırlatmalı', () => {
      expect(() => calc.us(2, -1)).toThrow('Negatif üs desteklenmiyor');
    });
  });

  describe('Geçmiş İşlemleri', () => {
    test('geçmiş kaydedilmeli', () => {
      calc.topla(1, 2);
      calc.cikar(5, 3);
      const gecmis = calc.gecmisiGetir();
      expect(gecmis).toHaveLength(2);
    });

    test('geçmiş temizlenmeli', () => {
      calc.topla(1, 2);
      calc.gecmisiTemizle();
      expect(calc.gecmisiGetir()).toHaveLength(0);
    });

    test('son işlemi döndürmeli', () => {
      calc.topla(3, 4);
      const son = calc.sonIslem();
      expect(son.islem).toBe('toplama');
      expect(son.sonuc).toBe(7);
    });

    test('geçmiş boşsa null döndürmeli', () => {
      expect(calc.sonIslem()).toBeNull();
    });
  });
});

// package.json - Coverage konfigürasyonu
// {
//   "scripts": {
//     "test": "jest",
//     "test:coverage": "jest --coverage"
//   },
//   "jest": {
//     "collectCoverageFrom": ["src/**/*.js", "!src/index.js"],
//     "coverageThreshold": {
//       "global": {
//         "branches": 80,
//         "functions": 80,
//         "lines": 80,
//         "statements": 80
//       }
//     },
//     "coverageReporters": ["text", "text-summary", "html", "lcov"]
//   }
// }

// Komut satırından çalıştırma:
// npx jest --coverage
// npx jest --coverage --coverageReporters="text-summary"
// Rapor dosyası: coverage/index.html

Coverage raporu yazmak, kodunuzun kalitesini artırmak için atılacak ilk adımdır. Ama unutmayın, yüksek coverage her zaman kaliteli test anlamına gelmez. Coverage bir rehberdir, amaç değil. Kritik iş mantığınızın iyi test edildiğinden emin olun, gerisini takıntı haline getirmeyin. Kolay gelsin!
 

Şu an konuyu görüntüleyenler (Toplam : 0, Üye: 0, Misafir: 0)

Geri
Üst