Jest ile Test Otomasyonu: Modern Yazılım Testi Rehberi
Yazar: Burak Balkı | Kategori: Backend Development | Okuma Süresi: 8 dk
Jest framework'ünün iç yapısını, kurulumunu, mocking tekniklerini ve backend projelerindeki ileri düzey kullanım senaryolarını inceleyen kapsamlı teknik rehber.
## Jest Nedir ve Neden Tercih Edilmelidir?
**Jest**, Meta (Facebook) tarafından geliştirilen ve JavaScript ekosisteminde en çok tercih edilen test framework'lerinden biridir. Özellikle 'sıfır yapılandırma' (zero-config) felsefesiyle öne çıkan Jest, geliştiricilere hızlı, güvenilir ve genişleyebilir bir test ortamı sunar. Backend geliştirmede, özellikle Node.js tabanlı projelerde, kodun doğruluğunu ve regresyon hatalarının önlenmesini sağlamak için kritik bir rol oynar.
Jest'in popülaritesinin arkasında yatan temel nedenler şunlardır:
- **Hız:** Testleri paralel olarak çalıştırarak zaman kazandırır.
- **Snapshot Testing:** Büyük veri yapılarını veya UI bileşenlerini kolayca doğrular.
- **Dahili Mocking:** Ek kütüphanelere ihtiyaç duymadan fonksiyon ve modülleri taklit edebilir.
- **Code Coverage:** Tek bir komutla testlerin kodun ne kadarını kapsadığını raporlar.
## Jest'in Mimari Yapısı ve Çalışma Prensibi
Jest, rakiplerinden farklı olarak testleri izole edilmiş ortamlarda çalıştırır. Her test dosyası kendi **sandbox** (kum havuzu) ortamında yürütülür, bu da global değişkenlerin veya testlerin birbirini etkilemesini engeller.
### Çalışma Mekanizması
1. **Dosya Keşfi:** Jest, proje dizinindeki `.test.js` veya `.spec.js` uzantılı dosyaları tarar.
2. **Paralel Yürütme:** Worker pool kullanarak test dosyalarını farklı CPU çekirdeklerine dağıtır.
3. **Transpilasyon:** Babel veya TypeScript entegrasyonu ile modern JavaScript kodunu anlaşılır hale getirir.
4. **Raporlama:** Sonuçları terminalde veya HTML formatında sunar.
## Kurulum ve Yapılandırma Adımları
Jest'i bir projeye dahil etmek oldukça basittir. npm veya yarn kullanarak hızlıca kurulum yapabilirsiniz.
```bash
npm install --save-dev jest
```
`package.json` dosyanızdaki `scripts` bölümüne test komutunu ekleyin:
```json
{
"scripts": {
"test": "jest"
}
}
```
Eğer TypeScript kullanıyorsanız, `ts-jest` ve `@types/jest` paketlerini de kurmanız gerekecektir.
## Temel Test Yazımı ve Matcher Fonksiyonları
Jest'te testler `test()` veya `it()` blokları içinde tanımlanır. Beklenen sonuçları doğrulamak için `expect()` fonksiyonu ve **matchers** (eşleştiriciler) kullanılır.
```javascript
// math.js
const sum = (a, b) => a + b;
module.exports = sum;
// math.test.js
const sum = require('./math');
test('iki sayıyı doğru şekilde toplar', () => {
expect(sum(1, 2)).toBe(3);
});
```
### Sık Kullanılan Matcher Örnekleri
| Matcher | Açıklama |
|---------|----------|
| `toBe()` | Tam eşitlik (referans kontrolü) |
| `toEqual()` | Nesne veya dizi içeriği kontrolü |
| `toBeNull()` | Değerin null olduğunu kontrol eder |
| `toContain()` | Dizinin bir elemanı içerip içermediğini kontrol eder |
| `toThrow()` | Bir fonksiyonun hata fırlatıp fırlatmadığını kontrol eder |
## Asenkron İşlemlerin Test Edilmesi
Backend dünyasında veritabanı sorguları veya API çağrıları asenkrondur. Jest, asenkron kodları test etmek için üç ana yöntem sunar.
### 1. Promises Kullanımı
```javascript
test('veriyi başarıyla getirir', () => {
return fetchData().then(data => {
expect(data).toBe('success');
});
});
```
### 2. Async/Await Kullanımı (Önerilen)
```javascript
test('async/await ile veri kontrolü', async () => {
const data = await fetchData();
expect(data).toEqual({ id: 1 });
});
```
## Mocking Teknikleri: Fonksiyonlar ve Modüller
**Mocking**, test edilen birimin bağımlılıklarını (örneğin bir veritabanı servisi) izole etmek için kullanılır. Jest, `jest.fn()` ve `jest.mock()` ile güçlü bir mocking altyapısı sunar.
### Fonksiyon Mock'lama
```javascript
test('callback fonksiyonu çağrılmalı', () => {
const mockCallback = jest.fn(x => 42 + x);
[0, 1].forEach(mockCallback);
expect(mockCallback.mock.calls.length).toBe(2);
expect(mockCallback.mock.results[0].value).toBe(42);
});
```
### Modül Mock'lama
Eğer bir API servisini mock'lamak isterseniz:
```javascript
const axios = require('axios');
const Users = require('./users');
jest.mock('axios');
test('kullanıcıları getirmeli', async () => {
const users = [{name: 'Ahmet'}];
const resp = {data: users};
axios.get.mockResolvedValue(resp);
return Users.all().then(data => expect(data).toEqual(users));
});
```
## Snapshot Testing: Veri Yapısı Doğrulama
Snapshot testleri, bir veri yapısının zaman içindeki değişimini izlemek için harikadır. İlk çalışmada bir 'snapshot' dosyası oluşturulur, sonraki çalışmalarda çıktı bu dosya ile karşılaştırılır.
```javascript
test('config objesi değişmemeli', () => {
const config = {
port: 3000,
host: 'localhost',
db: 'test_db'
};
expect(config).toMatchSnapshot();
});
```
## Code Coverage: Test Kapsamı Analizi
Jest, projenizin ne kadarının test edildiğini ölçmek için yerleşik bir kapsama raporu sunar. `--coverage` bayrağı ile bu raporu alabilirsiniz.
```bash
npm test -- --coverage
```
Bu komut sonucunda hangi satırların, fonksiyonların ve dalların (branch) test edildiğini gösteren detaylı bir tablo oluşturulur.
## Jest ile Backend (Express.js) Entegrasyonu
Backend API testlerinde genellikle `supertest` kütüphanesi ile birlikte kullanılır.
```javascript
const request = require('supertest');
const app = require('./app');
describe('GET /api/users', () => {
it('200 status kodu ve kullanıcı listesi dönmeli', async () => {
const res = await request(app).get('/api/users');
expect(res.statusCode).toEqual(200);
expect(res.body).toHaveProperty('users');
});
});
```
## Best Practices ve Performans Optimizasyonu
- **Test İzolasyonu:** Testler birbirine bağımlı olmamalıdır. Her test sıfırdan başlamalıdır.
- **Setup ve Teardown:** `beforeEach` ve `afterEach` bloklarını kullanarak veritabanı temizliği gibi işlemleri yönetin.
- **Tanımlayıcı İsimler:** Test başlıkları (it/test) neyin test edildiğini açıkça belirtmelidir.
- **Hızlı Testler:** Ağır işlemleri (I/O, network) mutlaka mock'layın.
```javascript
beforeEach(() => {
initializeDatabase();
});
afterEach(() => {
clearDatabase();
});
```
## Sık Yapılan Hatalar ve Çözümleri
1. **Asenkron Testlerde `done()` veya `return` Unutmak:** Testin sonucunu beklemeden bitmesine neden olur.
2. **Yanlış Matcher Kullanımı:** `toBe` ile `toEqual` arasındaki farkı (referans vs değer) karıştırmak.
3. **Global State Kirliliği:** Mock'ları temizlememek. `jest.clearAllMocks()` kullanın.
## Sık Sorulan Sorular (SSS)
1. **Jest sadece React projeleri için mi?** Hayır, Jest tüm JavaScript ve TypeScript projelerinde (Node.js, Vue, Angular, Vanilla JS) kullanılabilir.
2. **Mocha ve Chai'den farkı nedir?** Jest, assertion ve mocking araçlarını dahili olarak sunar, ek kütüphane gerektirmez.
3. **Testler neden yavaş çalışıyor?** Genellikle mock'lanmamış ağır bağımlılıklardan kaynaklanır. `--runInBand` komutu ile seri çalıştırmayı deneyebilirsiniz.
4. **Private fonksiyonları test etmeli miyim?** Genel kural olarak sadece public API'ları ve modül çıktılarını test etmelisiniz.
5. **Snapshot dosyalarını Git'e eklemeli miyim?** Evet, snapshot dosyaları kodun bir parçasıdır ve versiyon kontrol sistemine dahil edilmelidir.
## Sonuç
Jest, modern yazılım geliştirme süreçlerinde güven inşa etmenin en etkili yollarından biridir. Güçlü özellikleri, hızı ve geniş topluluk desteği ile backend projelerinizde hata payını minimize eder. Bu rehberde öğrendiğiniz teknikleri uygulayarak daha sürdürülebilir ve hatasız kod tabanları oluşturabilirsiniz.