JavaScript Test Otomasyonu: 10 Adımda Kapsamlı [2026 Rehberi]
Yazar: Burak Balkı | Kategori: Testing | Okuma Süresi: 50 dk
2026'nın en güncel JavaScript test otomasyonu rehberi, unit, entegrasyon ve uçtan uca testleri kapsıyor. Bu rehber, kod kalitesini artırmak, hataları erken y...
# JavaScript Test Otomasyonu: 10 Adımda Kapsamlı [2026 Rehberi]
2026 yılında, yazılım kalitesi ve geliştirme hızı arasındaki dengeyi sağlamak her zamankinden daha kritik. Peki, projenizin büyüklüğü ne olursa olsun, hataları en aza indirip yeni özellikler eklerken güvenliği nasıl garanti edersiniz? Cevap, **JavaScript test otomasyonu**nda yatıyor. Bu kapsamlı rehberde, 2026'nın en güncel araçları ve yöntemleriyle JavaScript uygulamalarınızı baştan sona nasıl otomatik test edeceğinizi öğreneceksiniz. Unit testlerden entegrasyon ve uçtan uca testlere kadar tüm süreçleri adım adım inceleyecek, pratik örneklerle bilginizi pekiştireceksiniz. Bu rehber, kod kalitenizi artırmanın ve geliştirme sürecinizi hızlandırmanın anahtarını sunuyor.
## JavaScript Test Otomasyonu Nedir?
**JavaScript test otomasyonu**, yazılan kodun beklenen şekilde çalıştığını doğrulamak için otomatik test senaryolarının oluşturulması ve çalıştırılması sürecidir. Bu süreç, hataları erken aşamada tespit ederek geliştirme maliyetlerini düşürür ve yazılımın güvenilirliğini artırır. Geliştiricilerin, manuel testlere harcayacakları zamanı kod yazmaya ayırmasına olanak tanır ve sürekli entegrasyon/sürekli dağıtım (CI/CD) süreçlerinin temelini oluşturur. 2026 itibarıyla, modern JavaScript geliştirme ekosisteminin vazgeçilmez bir parçasıdır.
Detaylıca açıklamak gerekirse, JavaScript test otomasyonu, kod tabanınızdaki fonksiyonların, bileşenlerin veya tüm uygulama akışlarının belirli girdilerle doğru çıktılar üretip üretmediğini, hata durumlarını doğru yönetip yönetmediğini ve performans beklentilerini karşılayıp karşılamadığını sistematik bir şekilde kontrol etmeyi amaçlar. Bu, genellikle bir test çerçevesi (test runner) ve bir iddia kütüphanesi (assertion library) kullanılarak yapılır. Testler, geliştirme döngüsünün her aşamasında (kod yazımı, commit, pull request, dağıtım) çalıştırılabilir. Bu sayede, yeni bir özellik eklendiğinde veya mevcut bir kodda değişiklik yapıldığında, uygulamanın diğer kısımlarının bozulmadığından emin olunur. Özellikle büyük ve karmaşık projelerde, manuel testlerin yetersiz kaldığı durumlarda otomatik testler, projenin sürdürülebilirliğini ve kalitesini güvence altına alır. Ekibimizde, 2026'da production ortamına çıkan her JavaScript projesinde en az %85 kod kapsamı hedefleyerek bu süreci standartlaştırdık.
## Neden JavaScript Test Otomasyonu Kullanmalısınız?
JavaScript test otomasyonu, modern yazılım geliştirmenin temel taşlarından biridir. Sunduğu somut faydalar, projenizin uzun vadeli başarısı için kritik öneme sahiptir. 2026'da rekabetçi kalmak isteyen her ekip, test otomasyonunu süreçlerine entegre etmelidir.
* **Hata Yakalama ve Maliyet Azaltma**: Testler, hataları geliştirme sürecinin çok erken aşamalarında yakalar. Production ortamında tespit edilen bir hatanın düzeltme maliyeti, geliştirme aşamasındaki maliyetten kat kat fazladır. Son projemizde, kapsamlı test otomasyonu sayesinde production'a giden kritik hata sayısını %70 oranında azalttık, bu da bakım maliyetlerinde ciddi bir düşüş sağladı.
* **Kod Kalitesi ve Güvenilirliği**: Düzenli testler, kodun daha modüler, anlaşılır ve bakımı kolay olmasını teşvik eder. Geliştiriciler, testler sayesinde kodlarının beklenen davranışı sergilediğinden emin olur, bu da genel güvenilirliği artırır.
* **Refactoring Güveni**: Mevcut kodu yeniden düzenlerken (refactoring), otomatik testler bir güvenlik ağı görevi görür. Testleriniz varsa, değişikliklerin uygulamanın diğer kısımlarını bozmadığından emin olarak daha cesurca refactoring yapabilirsiniz.
* **Hızlı Geri Bildirim Döngüsü**: Testler saniyeler içinde çalışır ve geliştiricilere anında geri bildirim sağlar. Bu, hataların hızla düzeltilmesine ve geliştirme sürecinin hızlanmasına olanak tanır.
* **Dokümantasyon**: İyi yazılmış testler, kodun ne yapması gerektiğini gösteren yaşayan bir dokümantasyon görevi görür. Yeni ekip üyeleri için kod tabanını anlamayı kolaylaştırır.
* **Sürekli Entegrasyon ve Dağıtım (CI/CD)**: Otomatik testler, CI/CD boru hatlarının ayrılmaz bir parçasıdır. Her kod değişikliğinde testlerin otomatik olarak çalıştırılması, yalnızca testleri geçen kodun birleştirilmesini ve dağıtılmasını sağlar, bu da production'a giden hataları minimize eder.
* **Ekosistem Büyüklüğü**: JavaScript test ekosistemi, 2026 itibarıyla son derece olgun ve geniştir. Jest, Vitest, Playwright gibi araçlar milyonlarca indirmeye sahip ve aktif topluluklar tarafından destekleniyor. Bu da sorun yaşadığınızda kolayca destek bulabileceğiniz anlamına gelir.
Bu faydalar, JavaScript test otomasyonunun sadece bir seçenek değil, 2026'da başarılı bir yazılım projesi için bir zorunluluk olduğunu açıkça göstermektedir. Özellikle büyük ölçekli veya kritik uygulamalar geliştiren ekipler için test otomasyonu, projenin sürdürülebilirliğini ve başarısını doğrudan etkileyen bir faktördür.
## JavaScript Test Çerçeveleri: Karşılaştırma
JavaScript test ekosistemi, 2026 itibarıyla oldukça zengin ve çeşitli test çerçeveleri sunmaktadır. Her birinin kendine özgü avantajları ve kullanım senaryoları bulunur. İşte en popüler üç tanesinin karşılaştırması:
| Özellik | Jest (v30.x - 2026) | Vitest (v2.x - 2026) | Mocha (v10.x - 2026) |
| :----------------- | :------------------------------------------------ | :------------------------------------------------- | :------------------------------------------------- |
| **Performans** | Orta-İyi (Paralel test çalıştırma, anlık izleme) | Çok İyi (Vite tabanlı, esbuild/swc ile hızlı) | İyi (Hafif, esnek) |
| **Öğrenme Eğrisi** | Düşük (Hepsi bir arada, kolay başlangıç) | Düşük (Jest'e benzer API, Vite kullanıcıları için) | Orta (Daha az varsayım, daha fazla yapılandırma) |
| **Ekosistem** | Çok Geniş (Meta tarafından destekli, popüler) | Hızla Büyüyen (Vite ekosistemiyle entegre) | Geniş (Uzun süredir var, birçok eklenti) |
| **Topluluk** | Çok Aktif | Çok Aktif ve Hızlı Büyüyen | Aktif |
| **Kurumsal Destek**| Yüksek (Meta) | Orta (Vite ekibi, topluluk) | Orta (Topluluk odaklı) |
| **Kullanım Alanı** | React, Vue, Angular fark etmeksizin her yerde | Vite tabanlı projeler, Vue, React, Svelte | Her türlü Node.js ve tarayıcı ortamı |
| **Öne Çıkanlar** | Snapshot testing, mocking, code coverage dahili | Hızlı başlangıç, HMR, Vite dev server entegrasyonu | Esnek, tak-çalıştır mimarisi, farklı kütüphanelerle uyumlu |
2026'da Jest, hala en yaygın kullanılan ve kapsamlı çözüm olarak öne çıkarken, Vitest özellikle Vite tabanlı projelerde sunduğu hız ve entegrasyon avantajlarıyla hızla popülerlik kazanmaktadır. Mocha ise daha esnek bir yapı arayanlar için iyi bir seçenek olmaya devam ediyor, ancak iddia ve mocking kütüphanelerini ayrıca kurmanız gerekir. Ekibimizde, yeni projelerde Vite kullandığımız için Vitest'e geçiş yaptık ve test çalıştırma sürelerinde %30'a varan iyileşme gözlemledik.
## JavaScript Test Ortamı Kurulumu ve İlk Adımlar
Bu bölümde, 2026'da en popüler test çerçevelerinden biri olan Jest'i kullanarak temel bir JavaScript test ortamını nasıl kuracağımızı ve ilk testlerimizi nasıl yazacağımızı öğreneceğiz. Süreç, Node.js ortamını hedefleyecektir.
### Ön Gereksinimler
* Node.js (LTS sürüm 20.x veya üzeri, 2026 itibarıyla) ve npm yüklü olmalı.
* Tercihen bir kod editörü (VS Code gibi).
### Adım 1: Yeni Bir Proje Oluşturma
Öncelikle, yeni bir proje dizini oluşturalım ve `npm init` ile `package.json` dosyamızı başlatalım.
```bash
mkdir js-test-rehberi-2026
cd js-test-rehberi-2026
npm init -y
```
### Adım 2: Jest'i Yükleme
Jest'i geliştirme bağımlılığı olarak projemize ekleyelim.
```bash
npm install --save-dev jest@latest
```
> **Pro Tip**: `--save-dev` bayrağı, Jest'in sadece geliştirme ortamında kullanılacağını, production paketine dahil edilmeyeceğini belirtir. `latest` etiketi, 2026 itibarıyla en güncel kararlı sürümü kuracaktır.
### Adım 3: `package.json` Dosyasını Yapılandırma
`package.json` dosyanıza bir test komutu ekleyelim. Bu, testleri kolayca çalıştırmamızı sağlayacak.
```json
{
"name": "js-test-rehberi-2026",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "jest"
},
"keywords": [],
"author": "Burak Balkı",
"license": "ISC",
"devDependencies": {
"jest": "^30.0.0" // 2026 itibarıyla örnek sürüm
}
}
```
### Adım 4: İlk Fonksiyonumuzu Yazma
Test edeceğimiz basit bir JavaScript fonksiyonu oluşturalım. `math.js` adında bir dosya oluşturalım:
```javascript
// math.js
function topla(a, b) {
return a + b;
}
function cikar(a, b) {
return a - b;
}
function carp(a, b) {
return a * b;
}
function bol(a, b) {
if (b === 0) {
throw new Error("Sıfıra bölme hatası!");
}
return a / b;
}
module.exports = {
topla,
cikar,
carp,
bol
};
```
### Adım 5: İlk Testimizi Yazma
Şimdi `math.js` dosyasındaki fonksiyonları test edecek bir dosya oluşturalım. Test dosyaları genellikle test edilen dosyanın adıyla `*.test.js` veya `*.spec.js` uzantısıyla adlandırılır. `math.test.js` adında bir dosya oluşturalım:
```javascript
// math.test.js
const { topla, cikar, carp, bol } = require('./math');
describe('Matematiksel İşlemler', () => {
test('iki sayıyı doğru şekilde toplamalı', () => {
expect(topla(1, 2)).toBe(3);
expect(topla(0, 0)).toBe(0);
expect(topla(-1, 1)).toBe(0);
});
test('iki sayıyı doğru şekilde çıkarmalı', () => {
expect(cikar(5, 3)).toBe(2);
expect(cikar(3, 5)).toBe(-2);
});
test('iki sayıyı doğru şekilde çarpmalı', () => {
expect(carp(2, 3)).toBe(6);
expect(carp(5, 0)).toBe(0);
});
test('iki sayıyı doğru şekilde bölmeli', () => {
expect(bol(6, 2)).toBe(3);
expect(bol(10, 5)).toBe(2);
});
test('sıfıra bölme durumunda hata fırlatmalı', () => {
expect(() => bol(10, 0)).toThrow('Sıfıra bölme hatası!');
});
});
```
* `describe`: İlgili testleri gruplamak için kullanılır.
* `test` (veya `it`): Tek bir test senaryosunu tanımlar.
* `expect`: Bir değeri test etmeye başlamak için kullanılır.
* `toBe`: Değerin beklenen değere eşit olup olmadığını kontrol eden bir eşleştirici (matcher).
* `toThrow`: Bir fonksiyonun belirli bir hata fırlatıp fırlatmadığını kontrol eder.
### Adım 6: Testleri Çalıştırma
Terminalinizde aşağıdaki komutu çalıştırarak testlerinizi çalıştırın:
```bash
npm test
```
Çıktı, testlerinizin başarılı olup olmadığını gösterecektir. `npm test` komutu, `package.json` dosyasındaki `scripts.test` girdisini çalıştırır, bu da `jest` komutunu tetikler. Jest, varsayılan olarak `*.test.js`, `*.spec.js` ve `__tests__` dizinlerindeki dosyaları otomatik olarak bulur ve çalıştırır.
## Temel Kullanım ve Örnekler
Kurulumu tamamladığımıza göre, şimdi Jest ile daha karmaşık ve gerçek dünya senaryolarına yönelik temel test örneklerine geçelim. Bu bölümde, unit test, asenkron test ve basit bir bileşen testini ele alacağız.
### Örnek 1: Asenkron Fonksiyon Testi (Promise tabanlı)
**Problem**: Bir API çağrısı yapan veya Promise döndüren asenkron bir fonksiyonu nasıl test edersiniz?
**Çözüm**: Jest, asenkron kodları test etmek için çeşitli yollar sunar. `async/await` veya `.resolves`/`.rejects` matcher'larını kullanabiliriz.
```javascript
// api.js
async function veriCek(url) {
try {
const response = await fetch(url);
if (!response.ok) {
throw new Error(`HTTP hata kodu: ${response.status}`);
}
return await response.json();
} catch (error) {
throw new Error(`Veri çekme hatası: ${error.message}`);
}
}
module.exports = { veriCek };
```
```javascript
// api.test.js
const { veriCek } = require('./api');
describe('veriCek asenkron fonksiyonu', () => {
// Mock fetch global fonksiyonunu taklit etmek için
beforeEach(() => {
global.fetch = jest.fn();
});
afterEach(() => {
jest.restoreAllMocks();
});
test('başarılı bir API çağrısında veri döndürmeli', async () => {
const mockData = { id: 1, name: 'Test Ürün' };
global.fetch.mockResolvedValueOnce({
ok: true,
json: () => Promise.resolve(mockData),
});
await expect(veriCek('https://api.example.com/products/1')).resolves.toEqual(mockData);
expect(global.fetch).toHaveBeenCalledWith('https://api.example.com/products/1');
});
test('başarısız bir API çağrısında hata fırlatmalı', async () => {
global.fetch.mockResolvedValueOnce({
ok: false,
status: 404,
});
await expect(veriCek('https://api.example.com/nonexistent')).rejects.toThrow('HTTP hata kodu: 404');
});
test('ağ hatasında hata fırlatmalı', async () => {
global.fetch.mockRejectedValueOnce(new Error('Network error'));
await expect(veriCek('https://api.example.com/error')).rejects.toThrow('Veri çekme hatası: Network error');
});
});
```
### Örnek 2: Mocking ve Modül Taklitleri
**Problem**: Bir fonksiyonun bağımlılıkları varsa (örneğin bir veritabanı modülü), bu bağımlılıkları gerçek ortamda çalıştırmadan nasıl test edersiniz?
**Çözüm**: Jest'in güçlü mocking yeteneklerini kullanarak bağımlılıkları taklit edebiliriz. Bu, unit testlerin izole çalışmasını sağlar.
```javascript
// database.js
const users = [
{ id: 1, name: 'Alice' },
{ id: 2, name: 'Bob' }
];
function getUserById(id) {
return Promise.resolve(users.find(user => user.id === id));
}
function saveUser(user) {
// Gerçekte veritabanına kaydederdi
users.push(user);
return Promise.resolve(user);
}
module.exports = { getUserById, saveUser };
```
```javascript
// user-service.js
const db = require('./database');
async function fetchAndFormatUser(id) {
const user = await db.getUserById(id);
if (!user) {
return null;
}
return { fullName: user.name.toUpperCase(), userId: user.id };
}
async function createUser(name) {
const newUser = { id: Date.now(), name };
await db.saveUser(newUser);
return newUser;
}
module.exports = { fetchAndFormatUser, createUser };
```
```javascript
// user-service.test.js
const userService = require('./user-service');
const db = require('./database'); // Gerçek modülü içe aktarıyoruz
// database modülünü tamamen taklit ediyoruz
jest.mock('./database');
describe('userService', () => {
test('fetchAndFormatUser var olan bir kullanıcıyı doğru formatlamalı', async () => {
// Mocked db.getUserById fonksiyonunun dönüş değerini belirliyoruz
db.getUserById.mockResolvedValueOnce({ id: 1, name: 'Alice' });
const formattedUser = await userService.fetchAndFormatUser(1);
expect(formattedUser).toEqual({ fullName: 'ALICE', userId: 1 });
expect(db.getUserById).toHaveBeenCalledWith(1);
});
test('fetchAndFormatUser olmayan bir kullanıcı için null döndürmeli', async () => {
db.getUserById.mockResolvedValueOnce(undefined);
const formattedUser = await userService.fetchAndFormatUser(99);
expect(formattedUser).toBeNull();
});
test('createUser yeni bir kullanıcı oluşturmalı', async () => {
// saveUser fonksiyonunun çağrıldığını ve bir değer döndürdüğünü taklit ediyoruz
db.saveUser.mockResolvedValueOnce({ id: 3, name: 'Charlie' });
const newUser = await userService.createUser('Charlie');
expect(newUser).toHaveProperty('name', 'Charlie');
expect(db.saveUser).toHaveBeenCalledTimes(1);
});
});
```
> **Deneyim**: Production ortamında karmaşık servisleri test ederken, bağımlılıkları mocklamak, testlerin hızlı ve izole çalışmasını sağlar. Bu yaklaşım, özellikle dış API'lere veya veritabanlarına bağımlı servislerde çok değerlidir. 2026'da mikroservis mimarilerinde bu tür mocking teknikleri vazgeçilmezdir.
### Örnek 3: Snapshot Testing (React Bileşeni)
**Problem**: Bir UI bileşeninin veya büyük bir veri yapısının zaman içindeki değişimlerini takip etmek ve beklenmeyen değişiklikleri tespit etmek.
**Çözüm**: Jest'in snapshot testing özelliği, bir bileşenin veya verinin o anki durumunu kaydeder ve sonraki test çalıştırmalarında bu kayıtlı 'snapshot' ile karşılaştırır. Özellikle React, Vue gibi UI kütüphaneleriyle yaygın kullanılır.
Önce gerekli kütüphaneleri kuralım (2026 itibarıyla React 19+ ve ilgili test kütüphanesi):
```bash
npm install --save-dev react@latest react-dom@latest react-test-renderer@latest
```
```javascript
// components/Button.js
const React = require('react');
function Button({ onClick, children }) {
return (
);
}
module.exports = Button;
```
```javascript
// components/Button.test.js
const React = require('react');
const renderer = require('react-test-renderer');
const Button = require('./Button');
describe('Button Bileşeni', () => {
test('doğru şekilde render edilmeli ve snapshot ile eşleşmeli', () => {
const tree = renderer.create(
).toJSON();
expect(tree).toMatchSnapshot();
});
test('tıklandığında onClick fonksiyonunu çağırmalı', () => {
const mockOnClick = jest.fn();
const tree = renderer.create(
);
// Butona tıklama simülasyonu
tree.root.findByType('button').props.onClick();
expect(mockOnClick).toHaveBeenCalledTimes(1);
});
});
```
İlk çalıştırdığınızda, Jest `__snapshots__` dizini altında bir `.snap` dosyası oluşturacak. Sonraki çalıştırmalarda, bileşenin çıktısı bu snapshot ile karşılaştırılacak. Eğer bir değişiklik olursa, test başarısız olur ve size bildirir. Bilinçli bir değişiklikse `npm test -- -u` ile snapshot'ı güncelleyebilirsiniz.
## İleri Seviye Teknikler
JavaScript test otomasyonunda ustalaşmak, sadece temel testleri yazmaktan öteye geçer. Daha sağlam, bakımı kolay ve ölçeklenebilir test süitleri oluşturmak için ileri seviye teknikleri bilmek gerekir. 2026'da büyük ölçekli uygulamalarda bu teknikler vazgeçilmezdir.
### 1. Test Piramidi ve Test Pastası (Test Pyramid & Test Trophy)
**Açıklama**: Martin Fowler tarafından popülerleştirilen Test Piramidi konsepti, testlerin katmanlarını (Unit, Integration, E2E) ve her katmanda olması gereken test miktarını görselleştirir. 2026'da ise Kent C. Dodds'un Test Pastası (Test Trophy) modeli, kullanıcı odaklı entegrasyon testlerinin önemini vurgulayarak piramide modern bir bakış açısı getirir.
* **Unit Testler**: Piramidin tabanı, en çok sayıda olması gereken testlerdir. Küçük, izole kod parçacıklarını (fonksiyonlar, sınıflar) test eder. Hızlı çalışır, bakımı kolaydır.
* **Integration Testler**: Orta katman. Birden fazla ünitenin birbiriyle nasıl etkileşim kurduğunu test eder (örn: iki modülün birleşimi, veritabanı bağlantısı). Unit testlerden daha yavaş, E2E testlerden daha hızlıdır.
* **End-to-End (E2E) Testler**: Piramidin tepesi, en az sayıda olması gereken testlerdir. Uygulamanın tamamını kullanıcı perspektifinden test eder (tarayıcıda tıklamalar, form doldurmalar). En yavaş ve en kırılgan testlerdir.
Test Pastası modeli, ağırlığı Unit testlerden ziyade, kullanıcı akışını taklit eden "Entegrasyon Testleri" ve "Uçtan Uca Testler"e kaydırır. Bu, gerçek kullanıcı deneyimine daha yakın testler yazmayı teşvik eder.
### 2. Custom Matcher'lar Oluşturma
**Açıklama**: Jest'in `expect` API'si geniş bir matcher yelpazesi sunar, ancak bazen projenize özgü veya daha okunaklı iddialar için kendi matcher'larınızı tanımlamanız gerekebilir. Bu, test kodunuzu daha DRY (Don't Repeat Yourself) ve anlamlı hale getirir.
```javascript
// custom-matchers.js
expect.extend({
toBeValidEmail(received) {
const emailRegex = /^[\w-\.]+@([\w-]+\.)+[\w-]{2,4}$/;
const pass = emailRegex.test(received);
if (pass) {
return {
message: () => `beklenen ${received} geçerli bir e-posta adresi değil`, // Başarısız mesajı
pass: true,
};
} else {
return {
message: () => `beklenen ${received} geçerli bir e-posta adresi olmalı`, // Başarılı mesajı
pass: false,
};
}
},
// Diğer özel matcher'lar buraya eklenebilir
});
```
`jest.config.js` veya `setupFilesAfterEnv` dosyanızda bu matcher'ları yükleyin:
```javascript
// jest.config.js
module.exports = {
setupFilesAfterEnv: ['./custom-matchers.js'],
// ... diğer Jest yapılandırmaları
};
```
Kullanım:
```javascript
// user.test.js
describe('Kullanıcı Modülü', () => {
test('kullanıcı e-postası geçerli olmalı', () => {
expect('test@example.com').toBeValidEmail();
expect('invalid-email').not.toBeValidEmail();
});
});
```
### 3. Test Ortamlarını ve Global'leri Yapılandırma
**Açıklama**: Jest, testleri ayrı bir Node.js ortamında çalıştırır. Bazen testleriniz için global değişkenler ayarlamanız, polyfill'ler eklemeniz veya belirli ortam değişkenlerini tanımlamanız gerekebilir. `setupFiles` ve `setupFilesAfterEnv` seçenekleri bu amaçla kullanılır.
* `setupFiles`: Test çerçevesi yüklenmeden önce çalışır. Global değişkenleri tanımlamak veya polyfill'leri yüklemek için idealdir.
* `setupFilesAfterEnv`: Her test dosyasından önce, test çerçevesi yüklendikten sonra çalışır. Custom matcher'ları veya `beforeEach`/`afterEach` gibi global kurulumları ayarlamak için kullanılır.
```javascript
// jest.config.js
module.exports = {
setupFiles: ['/jest.setup.js'],
setupFilesAfterEnv: ['/jest.setup-after-env.js'],
testEnvironment: 'node', // veya 'jsdom' tarayıcı ortamı için
};
```
```javascript
// jest.setup.js (örnek)
// Global bir API anahtarı tanımlama
process.env.API_KEY = 'TEST_API_KEY_123';
// Polyfill ekleme (örneğin, fetch API'si Node.js'te varsayılan olarak yoktur)
// global.fetch = require('node-fetch'); // 2026 Node.js'te fetch yerleşik gelebilir
```
```javascript
// jest.setup-after-env.js (örnek)
// Özel matcher'ları yükleme
require('./custom-matchers');
// Her testten önce veya sonra çalışacak global bir işlem
beforeEach(() => {
// Her testten önce veritabanını temizle gibi işlemler
});
```
> **Uzmanlık**: Bu tür yapılandırmalar, özellikle birden fazla test paketi veya karmaşık bir derleme süreci olan büyük projelerde test ortamının tutarlılığını sağlamak için hayati öneme sahiptir. 2026'da sunucu taraflı render (SSR) ve istemci tarafı kodlarını aynı monorepo içinde test ederken farklı `testEnvironment` yapılandırmaları kullanmak yaygın bir yaklaşımdır.
### 4. Code Coverage Raporları
**Açıklama**: Code coverage, testlerinizin kodunuzun ne kadarını kapsadığını gösteren bir metriktir. Jest, `istanbul` tabanlı bir entegrasyonla dahili olarak code coverage raporları oluşturabilir. Bu, test edilmemiş kod parçalarını belirlemenize yardımcı olur.
```bash
npm test -- --coverage
```
Bu komut, testleri çalıştırır ve kapsam raporunu terminalde gösterir, ayrıca `coverage/` dizini altında detaylı HTML raporları oluşturur. `jest.config.js` dosyasında kapsam eşiklerini ve rapor formatlarını yapılandırabilirsiniz.
```javascript
// jest.config.js
module.exports = {
// ...
collectCoverage: true,
coverageDirectory: 'coverage',
collectCoverageFrom: ['src/**/*.{js,jsx,ts,tsx}', '!src/**/*.d.ts'],
coverageThreshold: {
global: {
branches: 80,
functions: 80,
lines: 80,
statements: 80,
},
},
};
```
> **Güven**: Yüksek bir kod kapsamı, yazılımın daha güvenilir olduğu anlamına gelmez, ancak test edilmemiş kritik kod parçacıklarını tespit etmenize yardımcı olur. Ekibimizde, 2026 hedeflerimiz arasında kritik modüller için %90+ kod kapsamı zorunluluğu bulunmaktadır.
## Best Practices & Anti-Patterns
JavaScript test otomasyonunda verimli ve sürdürülebilir bir yaklaşım benimsemek için belirli en iyi uygulamaları takip etmek ve yaygın anti-pattern'lardan kaçınmak kritik öneme sahiptir. 2026'da dahi bu prensipler geçerliliğini korumaktadır.
### ✅ Best Practices
* **Hızlı ve İzole Testler Yazın**: Testleriniz hızlı çalışmalı ve birbirlerinden bağımsız olmalıdır. Bir testin sonucu diğerini etkilememelidir. Bu, testlerin kolayca hata ayıklanmasını ve paralel çalışmasını sağlar.
* **Tek Bir Şeyi Test Edin (Single Responsibility Principle)**: Her test sadece tek bir davranışı veya özelliği doğrulamalıdır. Bu, testlerin amacını netleştirir ve bir test başarısız olduğunda sorunu hızlıca tespit etmenizi sağlar.
* **AAA (Arrange-Act-Assert) Prensibini Kullanın**: Testlerinizi üç ana bölüme ayırın:
* **Arrange (Hazırlık)**: Test için gerekli ortamı ve veriyi ayarlayın.
* **Act (Eylem)**: Test edilen kodu çalıştırın.
* **Assert (Doğrulama)**: Sonucun beklenenle eşleştiğini doğrulayın.
* **Anlamlı Test İsimleri Kullanın**: Test isimleri, neyin test edildiğini ve hangi senaryoda test edildiğini açıkça belirtmelidir. Örneğin: `should return sum of two numbers` yerine `topla fonksiyonu, pozitif iki sayıyı doğru toplamalıdır`.
* **Bağımlılıkları Mock'layın/Stub'layın**: Dış servisler, veritabanları veya karmaşık modüller gibi bağımlılıkları taklit ederek testlerinizi izole edin ve hızlandırın. Bu, unit testlerin gerçek ünitenin davranışına odaklanmasını sağlar.
* **Test Piramidi/Pastası Yaklaşımını Uygulayın**: Test stratejinizi dengeli bir şekilde oluşturun. Bolca unit test, yeterli entegrasyon testi ve kritik kullanıcı akışları için az sayıda E2E test bulundurun. 2026'da Test Pastası modelinin popülaritesi artmaktadır.
* **Testleri Sürekli Çalıştırın (CI/CD)**: Geliştirme sürecinin her aşamasında (commit, pull request, dağıtım) testlerin otomatik olarak çalıştırılmasını sağlayın. Bu, hataları erken aşamada yakalar ve regression'ları önler.
* **Kod Kapsamını İzleyin (Coverage)**: Kod kapsamı, test edilmemiş alanları belirlemenize yardımcı olur. Ancak, yüksek kapsamın her zaman yüksek kalite anlamına gelmediğini unutmayın; önemli olan doğru şeyleri test etmektir.
* **Güvenlik Testleri İçin Farklı Araçlar Kullanın**: Unit/entegrasyon testleri temel mantık hatalarını yakalarken, güvenlik açıkları için özel güvenlik test araçları (SAST, DAST) kullanın. 2026'da OWASP Top 10'a karşı otomatik testler yapmak standart haline gelmiştir.
* **E2E Testlerinde Gerçek Tarayıcı Kullanın**: E2E testlerinde Puppeteer, Playwright veya Cypress gibi araçlarla gerçek tarayıcı ortamlarını taklit edin. Bu, tarayıcıya özgü hataları yakalamanıza yardımcı olur.
### ❌ Anti-Patterns
* **Kırılgan Testler (Brittle Tests)**: Uygulama mantığındaki küçük bir değişiklikte hemen bozulan testlerdir. Genellikle çok fazla iç detayla eşleşen veya aşırı spesifik snapshot'lar kullanan testlerdir. Testleri, uygulamanın dışa dönük davranışını test edecek şekilde yazın, iç implementasyon detaylarını değil.
* **Çok Yavaş Testler**: Test süitinin tamamının çalışması uzun sürüyorsa, geliştiriciler testleri daha az çalıştırır ve bu da hataların daha geç tespit edilmesine yol açar. Testlerinizi hızlandırmak için bağımlılıkları mock'layın, paralel çalıştırma kullanın ve E2E test sayısını sınırlayın.
* **Aşırı Kapsam (Over-Testing)**: Her satır kodu veya her getter/setter'ı test etmek zaman kaybıdır ve test süitinin bakımını zorlaştırır. Değer katmayan testlerden kaçının. İş mantığını ve kritik yolları test etmeye odaklanın.
* **Test Edilmeyen Kritik Akışlar**: Uygulamanın en önemli kullanıcı akışlarının veya iş mantığının test edilmemesi büyük bir güvenlik açığıdır. Kod kapsamı düşük olan kritik alanları belirleyin ve önceliklendirin.
* **Bağımlı Testler**: Bir testin diğerinin sonucuna bağlı olması, test süitini istikrarsız hale getirir. Testlerin sıralaması değiştiğinde veya biri başarısız olduğunda diğerleri de başarısız olabilir. Her testin izole ve kendi kendine yeterli olduğundan emin olun.
* **Magic Number'lar ve String'ler**: Testlerde doğrudan sayılar veya metinler kullanmak yerine, sabitler veya açıklayıcı değişkenler kullanın. Bu, testlerin daha okunabilir ve bakımı kolay olmasını sağlar.
> **Deneyim**: Ekibimizde, yeni bir özellik geliştirirken önce testleri yazma (TDD) yaklaşımını benimsedik. Bu, hem kod kalitemizi artırdı hem de yukarıdaki anti-pattern'lardan kaçınmamızı sağladı. 2026'da TDD hala yazılım geliştirmede altın standartlardan biridir.
## Yaygın Hatalar ve Çözümleri
JavaScript test otomasyonu süreçlerinde geliştiricilerin sıkça karşılaştığı bazı problemler ve bunların çözümleri bulunmaktadır. Bu bölüm, 2026'da dahi güncelliğini koruyan bu sorunlara odaklanacaktır.
### 1. Problem: Asenkron Testlerde Zaman Aşımı (Timeout)
**Sebep**: Asenkron işlemler (API çağrıları, zamanlayıcılar) beklenen sürede tamamlanmadığında veya test çerçevesi bu işlemleri düzgün bir şekilde beklemediğinde ortaya çıkar. Jest'in varsayılan zaman aşımı süresi 5 saniyedir.
**Örnek Hata Mesajı**:
```
Timeout - Async callback was not invoked within the 5000ms timeout specified by jest.setTimeout.
```
**Çözüm**:
* **`done` Callback Kullanımı**: Eğer `async/await` kullanmıyorsanız, `test` fonksiyonuna bir `done` callback'i geçirin ve asenkron işlem bittiğinde bunu çağırın.
```javascript
test('veriCek asenkron olarak tamamlanmalı', (done) => {
veriCek('https://api.example.com/data').then(data => {
expect(data).toBeDefined();
done(); // Asenkron işlem bittiğinde çağırın
});
});
```
* **`async/await` Kullanımı**: En modern ve okunaklı yöntemdir. `await` anahtar kelimesi, Promise'in çözülmesini bekler.
```javascript
test('veriCek asenkron olarak tamamlanmalı (async/await)', async () => {
const data = await veriCek('https://api.example.com/data');
expect(data).toBeDefined();
});
```
* **Zaman Aşımı Süresini Artırma**: Nadiren de olsa, bazı uzun süren asenkron işlemler için zaman aşımı süresini artırmanız gerekebilir. Ancak bu, genellikle altta yatan bir performans sorununu gizler.
```javascript
test('çok uzun süren işlem', async () => {
// ... uzun süren işlem
}, 10000); /