Jest Rehberi: Modern JavaScript Uygulamalarında Test Otomasyonu
Yazar: Burak Balkı | Kategori: Testing | Okuma Süresi: 9 dk
Bu kapsamlı rehberde, Jest test çatısının kurulumundan başlayarak mock'lama, asenkron testler, snapshot testing ve performans optimizasyonuna kadar tüm süreç...
## Jest Nedir ve Neden Tercih Edilmelidir?
**Jest**, Facebook tarafından geliştirilen ve özellikle JavaScript ekosistemi için tasarlanmış, açık kaynaklı bir test çatısıdır (framework). Minimal konfigürasyon gereksinimi, hızı ve kapsamlı araç setiyle modern web geliştirme süreçlerinin vazgeçilmez bir parçası haline gelmiştir. React, Vue, Angular gibi kütüphanelerin yanı sıra saf JavaScript ve TypeScript projelerinde de yüksek performans sergiler.
Jest'in tercih edilme nedenlerinin başında **"Zero Config"** felsefesi gelir. Çoğu projede herhangi bir ayar yapmadan doğrudan çalıştırılabilir. Ayrıca, yerleşik gelen mock mekanizması, kod kapsama (coverage) raporları ve snapshot test özellikleri, ek kütüphanelere duyulan ihtiyacı ortadan kaldırarak geliştirici deneyimini (DX) maksimize eder.
## Geliştirme Ortamının Hazırlanması ve Jest Kurulumu
Bir projede Jest kullanmaya başlamak için Node.js ortamının kurulu olması gerekmektedir. Sıfırdan bir proje oluşturarak kurulum adımlarını inceleyelim.
1. Proje klasörünü oluşturun ve initialize edin:
```bash
mkdir jest-tutorial && cd jest-tutorial
npm init -y
```
2. Jest'i geliştirme bağımlılığı (development dependency) olarak yükleyin:
```bash
npm install --save-dev jest
```
3. `package.json` dosyasındaki `scripts` bölümünü güncelleyin:
```json
{
"scripts": {
"test": "jest"
}
}
```
Artık terminalde `npm test` komutunu çalıştırarak testleri başlatabilirsiniz.
## İlk Test Senaryosunun Yazılması: Temel Sözdizimi
Jest'te testler genellikle `.test.js` veya `.spec.js` uzantılı dosyalarda tutulur. Basit bir matematiksel fonksiyonu test ederek süreci başlatalım.
`math.js` dosyasını oluşturun:
```javascript
function add(a, b) {
return a + b;
}
module.exports = add;
```
`math.test.js` dosyasını oluşturun:
```javascript
const add = require('./math');
test('iki sayıyı doğru şekilde toplamalı', () => {
expect(add(1, 2)).toBe(3);
});
```
> **Not:** `test` fonksiyonu iki parametre alır: Testin açıklaması ve test kodunu içeren callback fonksiyonu. `expect` ise kontrol edilecek değeri sarmalar.
## Jest Matchers (Eşleştiriciler) ile Veri Doğrulama
Jest, değerleri farklı şekillerde doğrulamak için "matchers" adı verilen fonksiyonlar sunar. En yaygın kullanılan eşleştiriciler şunlardır:
| Matcher | Kullanım Amacı |
| :--- | :--- |
| `.toBe()` | Tam eşitlik (Object.is) kontrolü yapar. |
| `.toEqual()` | Nesne veya dizilerin içeriğini derinlemesine kontrol eder. |
| `.toBeNull()` | Değerin null olup olmadığını kontrol eder. |
| `.toBeDefined()` | Değerin tanımlı olup olmadığını kontrol eder. |
| `.toBeTruthy()` | Değerin boolean bağlamda doğru (true) olup olmadığını kontrol eder. |
| `.toContain()` | Bir dizinin belirli bir öğeyi içerip içermediğini kontrol eder. |
Örnek kullanım:
```javascript
test('nesne eşitliği kontrolü', () => {
const data = { one: 1 };
data['two'] = 2;
expect(data).toEqual({ one: 1, two: 2 });
});
```
## Asenkron Kodların Test Edilmesi: Promises ve Async/Await
Modern JavaScript uygulamalarında API çağrıları gibi asenkron işlemler kritik öneme sahiptir. Jest, asenkron kodları test etmek için üç ana yöntem sunar.
### Async/Await Kullanımı
En temiz ve okunabilir yöntem `async/await` yapısıdır:
```javascript
test('veriler asenkron olarak gelmeli', async () => {
const data = await fetchData();
expect(data).toBe('peanut butter');
});
```
### Promises Kullanımı
`resolves` ve `rejects` yardımcıları ile promise durumları kontrol edilebilir:
```javascript
test('promise çözülmeli', () => {
return expect(fetchData()).resolves.toBe('peanut butter');
});
```
## Setup ve Teardown İşlemleri: Test Yaşam Döngüsü Yönetimi
Testlerden önce veritabanı bağlantısı kurmak veya testlerden sonra temizlik yapmak gerekebilir. Jest bu durumlar için yaşam döngüsü kancaları sunar.
- `beforeEach()`: Her bir testten önce çalışır.
- `afterEach()`: Her bir testten sonra çalışır.
- `beforeAll()`: Dosyadaki tüm testlerden önce bir kez çalışır.
- `afterAll()`: Tüm testler bittikten sonra bir kez çalışır.
```javascript
beforeEach(() => {
initializeDatabase();
});
afterEach(() => {
clearDatabase();
});
```
## Mocking ve Spies: Bağımlılıkların İzole Edilmesi
Unit test yazarken dış bağımlılıkları (API'lar, modüller) izole etmek gerekir. Jest, **Mocking** yetenekleriyle bu süreci kolaylaştırır.
### Fonksiyon Mocklama
```javascript
test('mock 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 Mocklama
Bir modülü tamamen taklit etmek için `jest.mock()` kullanılır:
```javascript
const axios = require('axios');
const Users = require('./users');
jest.mock('axios');
test('kullanıcıları çekmeli', async () => {
const users = [{name: 'Bob'}];
const resp = {data: users};
axios.get.mockResolvedValue(resp);
return Users.all().then(data => expect(data).toEqual(users));
});
```
## Snapshot Testing ile UI ve Veri Yapısı Kontrolü
Snapshot testleri, bir veri yapısının veya UI bileşeninin zaman içindeki değişimini izlemek için kullanılır. İlk çalıştırmada bir referans dosyası oluşturulur, sonraki testlerde mevcut durum bu referansla karşılaştırılır.
```javascript
test('render doğru gerçekleşmeli', () => {
const tree = renderer.create(Google).toJSON();
expect(tree).toMatchSnapshot();
});
```
## Test Coverage (Kapsam) Raporlaması ve Analizi
Kodunuzun ne kadarının test edildiğini görmek için Jest dahili bir kapsama raporu sunar. Hiçbir ek araç kurmadan şu komutu çalıştırabilirsiniz:
```bash
npm test -- --coverage
```
Bu komut, projenizde hangi satırların, fonksiyonların ve dalların (branches) test edildiğini gösteren detaylı bir tablo ve `coverage` klasörü içinde bir HTML raporu oluşturur.
## Jest Konfigürasyonu: jest.config.js Özelleştirmeleri
Proje büyüdükçe Jest'in davranışını özelleştirmek gerekebilir. Bunun için kök dizinde bir `jest.config.js` dosyası oluşturulur.
```javascript
module.exports = {
verbose: true,
testEnvironment: 'node',
collectCoverage: true,
coverageThreshold: {
global: {
branches: 80,
functions: 80,
lines: 80
}
}
};
```
## Kurumsal Projelerde Best Practices
1. **AAA Deseni (Arrange, Act, Assert):** Testlerinizi hazırlık, işlem ve doğrulama bölümlerine ayırın.
2. **Anlamlı İsimlendirme:** Test açıklamaları, fonksiyonun ne yapması gerektiğini açıkça belirtmelidir.
3. **Bağımsız Testler:** Her test dosyası ve fonksiyonu birbirinden bağımsız olmalı, global state kullanımından kaçınılmalıdır.
4. **Yüksek Kapsama Değil, Kaliteli Test:** %100 kapsama her zaman hatasız kod anlamına gelmez; uç durumları (edge cases) test etmeye odaklanın.
## Yaygın Hatalar ve Çözüm Yolları
- **Asenkron Testlerde Beklememek:** `async/await` kullanmamak testin sonucunu beklemeden geçmesine neden olur. Daima asenkron işlemleri `await` edin.
- **Mock'ları Temizlememek:** `jest.clearAllMocks()` kullanılmadığında, mock fonksiyonlarının çağrılma sayıları testler arasında taşınabilir.
- **Global State Kirliliği:** Testlerde kullanılan global değişkenlerin her testten önce sıfırlandığından emin olun.
## Sık Sorulan Sorular (FAQ)
**1. Jest sadece React projeleri için mi?**
Hayır, Jest her türlü JavaScript ve TypeScript projesinde kullanılabilir. Node.js backend projeleri için de oldukça popülerdir.
**2. Mocha veya Jasmine'den farkı nedir?**
Jest; assertion kütüphanesi, mock araçları ve test koşucusunu (runner) bir arada sunar. Mocha genellikle Chai veya Sinon gibi ek kütüphanelere ihtiyaç duyar.
**3. Testler neden çok yavaş çalışıyor?**
Testleriniz birbirine bağımlı olabilir veya `--runInBand` bayrağı olmadan paralel çalışırken kaynak tüketiyor olabilir. `maxWorkers` ayarını kontrol edin.
**4. Snapshot testleri neden hata veriyor?**
UI veya veri yapınızda bilinçli bir değişiklik yaptıysanız snapshot'ı `npm test -- -u` komutuyla güncellemeniz gerekir.
**5. TypeScript ile nasıl kullanılır?**
`ts-jest` paketini yükleyerek ve `jest.config.js` dosyasında gerekli transform ayarlarını yaparak TypeScript desteği sağlayabilirsiniz.
## Özet ve Sonuç
Jest, modern JavaScript dünyasında test süreçlerini standartlaştıran güçlü bir araçtır. Kolay kurulumu, zengin eşleştirici kütüphanesi ve gelişmiş mock yetenekleriyle yazılım kalitesini artırmada kritik rol oynar. Bu rehberde öğrendiğiniz temel ve ileri seviye teknikleri projelerinize uygulayarak daha güvenilir ve bakımı kolay kod tabanları oluşturabilirsiniz.