İletişim

Birim Testi (Unit Test) Nedir?

Kısa tanım

Birim testi (unit test), yazılımın test edilebilir en küçük parçasını, genellikle tek bir fonksiyonu, metodu veya sınıfı, diğer bileşenlerden yalıtarak çalıştıran ve belirli bir girdi için beklenen sonucun üretilip üretilmediğini otomatik olarak kontrol eden testtir. Veritabanına, ağa veya dosya sistemine gitmediği için milisaniyeler içinde biter; bu sayede yüzlerce test her değişiklikte çalıştırılabilir ve hata, ortaya çıktığı anda yakalanır.

Diğer adları: unit test, unit testing, birim testleme

Tek bir fonksiyonun beklenen sonuçları verip vermediğini yalıtılmış olarak kontrol eden iki birim testi ve başarılı test sonucu

Küçük bir fonksiyon, üç test

Bir birim testi genellikle üç adımdan oluşur: hazırlık (arrange), çalıştırma (act) ve doğrulama (assert). Aşağıdaki örnekte net fiyata vergi ekleyen bir fonksiyon ve onu sınayan testler var. Sözdizimi Vitest'e ait; Jest, JUnit veya pytest gibi araçlarda yapı neredeyse aynıdır.

// fiyat.js
export function vergiliFiyat(net, oran = 0.2) {
  if (net < 0) throw new RangeError("Net fiyat negatif olamaz");
  return Math.round(net * (1 + oran) * 100) / 100;
}

// fiyat.test.js
import { describe, it, expect } from "vitest";
import { vergiliFiyat } from "./fiyat.js";

describe("vergiliFiyat", () => {
  it("varsayılan oranı ekler", () => {
    expect(vergiliFiyat(100)).toBe(120);
  });
  it("sonucu kuruşa yuvarlar", () => {
    expect(vergiliFiyat(9.99, 0.1)).toBe(10.99);
  });
  it("negatif fiyatı reddeder", () => {
    expect(() => vergiliFiyat(-1)).toThrow(RangeError);
  });
});

İkinci test tesadüf değildir: 9.99 * 1.1 kayan noktalı sayılarda tam olarak 10,989 etmez. Yuvarlama satırı silinirse test kırmızıya döner ve kuruş farkı faturaya yansımadan yakalanır. Birim testlerinin asıl değeri budur: kimsenin elle denemeyi aklına getirmeyeceği sınır durumlarını kalıcı olarak kayda geçirir.

Yalıtım: mock, stub ve fake

Gerçek kodun çoğu yalnız çalışmaz; veritabanına yazar, bir ödeme servisine istek atar, saati okur. Birim testinde bu dış bağımlılıkların yerine test double denen sahte nesneler konur:

  • Stub: Önceden belirlenmiş bir cevap döner (“kur servisi her zaman 34,50 döndürsün”).
  • Mock: Nasıl çağrıldığını kaydeder; testte “e-posta servisi tam bir kez, şu adresle çağrıldı mı?” diye sorulur.
  • Fake: Basitleştirilmiş ama çalışan bir uygulamadır; bellekte tutulan bir depo gibi.

Yalıtım testleri hızlı ve tekrarlanabilir kılar, ama aşırısı zararlıdır. Her iç çağrıyı mock'layan bir test, kodun ne yaptığını değil nasıl yazıldığını sınar; fonksiyon davranışı hiç değişmeden yeniden düzenlendiğinde bile kırılır. Bu kırılganlık zamanla ekibin testlere güvenini azaltır ve testlerin kendisi teknik borca dönüşür. Genel kural: yalnızca sizin kontrolünüzde olmayan, yavaş veya deterministik olmayan şeyleri (ağ, saat, rastgele sayı, harici API) taklit edin.

İyi bir birim testini ayırt eden özellikler

  • Hızlı: Tüm paket birkaç saniyede bitmeli; yavaş testler çalıştırılmamaya başlar.
  • Deterministik: Aynı kodla her seferinde aynı sonucu vermeli. Tarih, saat dilimi ve rastgelelik sabitlenmeli.
  • Bağımsız: Testler birbirinin bıraktığı duruma güvenmemeli; sıraları değiştiğinde de geçmeli.
  • Tek bir sebeple kırılmalı: Test adı neyin bozulduğunu söylemeli. “test1” değil, “negatif fiyatı reddeder”.
  • Davranışı sınamalı: Özel (private) yardımcıları değil, dışarıya açık arayüzü test etmeli.

Kapsam oranı neyi söyler, neyi söylemez?

Code coverage, testler çalışırken kodun yüzde kaçının en az bir kez yürütüldüğünü gösterir. Düşük kapsam, hiç sınanmayan kod olduğunu güvenilir biçimde işaret eder. Yüksek kapsam ise doğruluğu kanıtlamaz: hiçbir şeyi doğrulamayan, yalnızca fonksiyonu çağıran bir test de satırları “kapsanmış” sayar. Satır kapsamı yerine dal (branch) kapsamına bakmak, her if'in iki yolunun da denendiğini görmenizi sağlar. Testlerin gerçekten hata yakalayıp yakalamadığını merak ediyorsanız mutasyon testi, koda küçük bilinçli hatalar enjekte edip testlerin bunları fark edip etmediğini ölçer. Yüzde 100 hedefi çoğu projede maliyetli ve yanıltıcıdır; kritik iş kurallarını eksiksiz test etmek daha anlamlı bir hedeftir.

Test piramidindeki yeri ve CI ile ilişkisi

Birim testleri test piramidinin geniş tabanını oluşturur: sayıca en çok, en hızlı ve en ucuz olanlardır. Bileşenlerin birlikte çalışıp çalışmadığını ise entegrasyon testleri ve gerçek kullanıcı akışını tarayıcıda sınayan uçtan uca testler gösterir. Birim testi, iki fonksiyonun ayrı ayrı doğru olduğunu söyler; birbirine doğru bağlandıklarını söylemez.

Testlerin değeri her değişiklikte otomatik çalıştıklarında ortaya çıkar. Yaygın düzen, testlerin her pull request'te CI/CD hattında koşturulması ve kırmızı testle birleştirmenin engellenmesidir. Bir hatayı düzeltirken önce o hatayı yeniden üreten bir test yazmak da iyi bir alışkanlıktır: test önce kırılır, düzeltmeyle geçer ve aynı hata bir daha sessizce geri dönemez.

İlgili terimler

← Sözlüğe dön