Jest, JavaScript ve TypeScript ekosisteminin en popüler test framework''üdür. Zero-config başlar, built-in assertion, mocking ve coverage ile gelir. Bu yazı Jest''in tüm temel özelliklerini ve modern test pratiklerini anlatır.

Kurulum

İlgili rehberler: Yazılım geliştirme süreçleri · PostgreSQL optimizasyonu · Git ileri seviye komutlar · Redis nedir, nasıl kullanılır · Docker ile deploy

npm i -D jest @types/jest
npm i -D ts-jest typescript  # TS projesi için

# package.json
{
  "scripts": {
    "test": "jest",
    "test:watch": "jest --watch",
    "test:coverage": "jest --coverage"
  }
}

# TypeScript için
npx ts-jest config:init

İlk Test

// math.js
function add(a, b) { return a + b; }
module.exports = { add };

// math.test.js
const { add } = require('./math');

describe('add()', () => {
    it('iki pozitif sayıyı toplar', () => {
        expect(add(2, 3)).toBe(5);
    });

    it('negatif sayıları toplar', () => {
        expect(add(-1, -2)).toBe(-3);
    });

    it('sıfır ile çalışır', () => {
        expect(add(0, 5)).toBe(5);
    });
});
npm test
# PASS  ./math.test.js
#   add()
#     ✓ iki pozitif sayıyı toplar (2 ms)
#     ✓ negatif sayıları toplar
#     ✓ sıfır ile çalışır

Matcher''lar

// Eşitlik
expect(x).toBe(5);                // primitive === 
expect(obj).toEqual({ a: 1 });    // deep eşitlik
expect(obj).toStrictEqual({ a: 1 });  // + tip kontrolü

// Truthy/Falsy
expect(x).toBeTruthy();
expect(x).toBeNull();
expect(x).toBeDefined();

// Sayı
expect(x).toBeGreaterThan(3);
expect(x).toBeCloseTo(0.3);       // float

// String / Array
expect(s).toMatch(/error/i);
expect(arr).toContain('apple');
expect(arr).toHaveLength(3);

// Object
expect(user).toHaveProperty('email');
expect(user).toMatchObject({ name: 'Ali' });  // subset

// Exception
expect(() => throwError()).toThrow('Bad input');

// Negate
expect(x).not.toBe(0);

Setup ve Teardown

describe('User service', () => {
    let db;

    beforeAll(async () => {
        db = await connectDB();
    });

    afterAll(async () => {
        await db.close();
    });

    beforeEach(async () => {
        await db.clear();
    });

    it('creates user', async () => {
        const user = await createUser(db, { email: 'a@b.com' });
        expect(user.id).toBeDefined();
    });
});

Async Test

// Promise ile
it('fetches user', () => {
    return getUser(1).then(user => {
        expect(user.name).toBe('Ali');
    });
});

// async/await (tercih edilen)
it('fetches user', async () => {
    const user = await getUser(1);
    expect(user.name).toBe('Ali');
});

// Reject bekle
it('throws on invalid id', async () => {
    await expect(getUser(-1)).rejects.toThrow('Invalid');
});

// Resolve bekle
it('resolves with data', async () => {
    await expect(getUser(1)).resolves.toEqual(expect.objectContaining({ name: 'Ali' }));
});

Mock Functions

// Jest mock
const logger = jest.fn();
logger('hello');
logger('world');

expect(logger).toHaveBeenCalled();
expect(logger).toHaveBeenCalledTimes(2);
expect(logger).toHaveBeenCalledWith('hello');
expect(logger).toHaveBeenNthCalledWith(1, 'hello');

// Mock return value
const fetchUser = jest.fn().mockResolvedValue({ id: 1, name: 'Ali' });
const errFetch = jest.fn().mockRejectedValue(new Error('Network'));

// Implementation
const add = jest.fn((a, b) => a + b);
expect(add(2, 3)).toBe(5);

Module Mock

// __mocks__/axios.js
module.exports = {
    get: jest.fn(),
    post: jest.fn()
};

// user.test.js
jest.mock('axios');
const axios = require('axios');

it('fetches user', async () => {
    axios.get.mockResolvedValue({ data: { name: 'Ali' } });
    const user = await getUser(1);
    expect(user).toEqual({ name: 'Ali' });
    expect(axios.get).toHaveBeenCalledWith('/users/1');
});

Spy

// Var olan fonksiyonu izle, çağırmaya devam et
const spy = jest.spyOn(console, 'log');
myFunction();
expect(spy).toHaveBeenCalledWith('doing work');
spy.mockRestore();  // orijinale dön

Snapshot Testing

it('renders correctly', () => {
    const { container } = render(<Button label="Save" />);
    expect(container).toMatchSnapshot();
});
// İlk çalıştırmada snapshot oluşturur
// Sonraki çalıştırmada karşılaştırır — fark varsa fail
// Kabul etmek için: jest -u (update)
Bilgi
Snapshot''ları git''e commit edin. Review edilebilir olmalı; büyük snapshot''lar (1000+ satır) test kokusudur — daha dar assertion yapın.

Coverage

npm test -- --coverage

# jest.config.js
module.exports = {
    coverageDirectory: 'coverage',
    collectCoverageFrom: ['src/**/*.{js,ts}', '!**/*.test.{js,ts}'],
    coverageThreshold: {
        global: { branches: 80, functions: 80, lines: 80, statements: 80 }
    }
};

Test Driven Development (TDD)

  • Red: Failing test yaz (fonksiyon daha yok)
  • Green: En basit kodu yaz, test geçsin
  • Refactor: Kodu temizle, test hâlâ geçer
  • Tekrar

Vitest Alternatifi

Vite projesi kullanıyorsanız Jest yerine Vitest''i düşünün. API %95 Jest uyumlu, 3-5x hızlı, ESM native, TS first-class.

Yaygın Hatalar

  • Async test''te await unutmak → false positive
  • Her testte DB clear etmemek → flaky tests
  • Snapshot''ları büyük tutmak → review imkansız
  • Implementation detail test etmek → refactor''da kırılır
  • Test izolasyonu yok → test sırası sonucu etkiler

Modern Yazılım Geliştirme ve DevOps Pratikleri

Profesyonel yazılım geliştirme süreci üç pillar üzerine kuruludur: kaynak kontrolü (Git + GitHub/GitLab pull request akışı, code review zorunlu), CI/CD pipeline (otomatik test + lint + build + deploy), ve gözlemlenebilirlik (Sentry/Datadog/Grafana ile log, metric, trace toplama). Test piramidi (unit > integration > e2e) ile kod kalitesini garantilemek, mikroservis mimarisinde Docker container ve Kubernetes orkestrasyonu kullanmak, REST veya GraphQL API tasarımında OpenAPI/GraphQL Schema sözleşmesi tutmak modern standardlardır. Yazılım geliştirme yaşam döngüsü boyunca (gereksinim → tasarım → implementasyon → test → deploy → bakım) Agile/Scrum sprintleri 1-2 hafta, DevOps takımları sürekli teslim (continuous delivery) prensibiyle çalışır.

Test altyapısı kurulumu

Jest, Vitest veya Playwright ile test piramidi ve CI entegrasyonu için iletişime geçin

WhatsApp