Unit Test Yazma Rehberi (Python & JS): TDD'e Giriş ve Örnekler

Yazılım Test ve Hata Ayıklama

Unit Test Yazma Rehberi (Python & JS): TDD'e Giriş ve Örnekler

Bu rehber, unit testlerin ne olduğunu, TDD yaklaşımını ve hem Python hem JavaScript için çalıştırılabilir örneklerle test yazma adımlarını açıklar.
Unit Test Yazma Rehberi (Python & JS): TDD'e Giriş ve Örnekler

Giriş

Unit testler, yazılımın en küçük parçalarını (fonksiyonlar, metotlar, sınıfların birimleri) izole biçimde sınayan testlerdir. Unit testlerin amacı küçük birimin beklenen davranışı gösterip göstermediğini doğrulamaktır; Python'un resmi dokümantasyonu da unittest modülünü bu amaçla açıklar.

Unit Test ve TDD: Kısa Tanımlar

Unit test nedir?

Unit test birimlerin beklenen çıktıyı verdiğini kontrol eden otomatik testlerdir. Küçük ve deterministik olmaları beklenir; bir test çalıştığında sonuçlar koşullara bağlı olarak tutarlı olmalıdır.

Test-Driven Development (TDD) nedir?

TDD, öncelikle bir test yazıp bu testin başarısız olduğunu görmek (red), ardından testin geçmesi için en basit kodu yazmak (green) ve son olarak kodu temizlemek (refactor) adımlarını yineleyen bir yaklaşımdır. Bu yaklaşımın mantığı ve pratikleri birim test yazımını geliştirmek için sıkça önerilir.

TDD: Red → Green → Refactor Adımları

TDD döngüsü basittir ama disiplini gerektirir. Aşağıdaki kontrol listesi yeni başlayanlar için pratik bir rehber sağlar:

  • Yeni bir özellik için önce başarısız bir test yazın (Red).
  • Testi geçecek en basit kodu yazın (Green).
  • Tekrar eden kodu temizleyin, isimlendirmeleri düzeltin (Refactor).
  • Tüm testleri çalıştırın; her şeyin yeşilde olduğundan emin olun.

Python ile Basit Bir Örnek (unittest)

Bu bölümde Python'un standart unittest modülünü kullanarak basit bir TDD döngüsü gösteriyorum. Proje yapısı önerisi:

  • add.py (uygulama kodu)
  • tests/test_add.py (testler)

add.py

def add(a, b):
return a + b

tests/test_add.py

import unittest
from add import add

class TestAdd(unittest.TestCase):
def test_adds_two_numbers(self):
self.assertEqual(add(1, 2), 3)

if __name__ == '__main__':
unittest.main()

İlk adımda test yazılır; test çalıştırıldığında başarısız (kırmızı) olacaktır eğer add fonksiyonu yoksa veya yanlışsa. Ardından add fonksiyonunu en basit haliyle yazar ve testi tekrar çalıştırırsınız. Testleri çalıştırmak için yaygın komutlar:

  • Tek dosya test çalıştırma: python -m unittest tests/test_add.py
  • Tüm testleri keşfetme: python -m unittest discover -v

setUp / tearDown ve Mocklama

unittest modülü setUp ve tearDown metodlarıyla test başına hazırlık/temizlik yapmaya izin verir. Dış bağımlılıkları izole etmek için unittest.mock kullanılır. Örnek:

weather.py

import requests

def get_temperature(city):
resp = requests.get(f"https://api.example.com/temp?city={city}")
return resp.json()["temp"]

tests/test_weather.py

import unittest
from unittest.mock import patch, Mock
import weather

class TestWeather(unittest.TestCase):
@patch('weather.requests.get')
def test_get_temperature(self, mock_get):
mock_resp = Mock()
mock_resp.json.return_value = {'temp': 20}
mock_get.return_value = mock_resp
self.assertEqual(weather.get_temperature('Istanbul'), 20)

Bu yapı, gerçek HTTP çağrılarını yapmadan fonksiyonun davranışını test etmenizi sağlar.

JavaScript ile Basit Bir Örnek (Jest)

JavaScript ekosisteminde birçok test kütüphanesi vardır; modern projelerde sık kullanılanlardan biri Jest'tir. Basit bir örnek:

Proje dizini:
- add.js
- __tests__/add.test.js

add.js

function add(a, b) {
return a + b
}
module.exports = add

__tests__/add.test.js

const add = require('../add')

test('adds 1 + 2 to equal 3', () => {
expect(add(1, 2)).toBe(3)
})

Kurulum ve çalıştırma (örnek):

  • npm init -y
  • npm install --save-dev jest
  • package.json içinde "test": "jest" script'i ekleyin
  • npm test (veya npx jest)

Jest aynı zamanda asenkron testleri, mocklamayı ve snapshot testlerini destekler; basit fonksiyonel testler için jest kolay bir başlangıç sağlar.

Jest ile Mocklama (kısa örnek)

Eğer modülünüz http isteği yapıyorsa, jest.mock ile bağımlılığı taklit edebilirsiniz. Örneğin axios kullanan bir weather modülünü test ederken axios'u mock'layabilirsiniz.

İyi Test Yazma Pratikleri

  • Testler küçük ve tek bir sorumluluk taşımalı (single assertion ya da tek davranış odağı).
  • Deterministik olmalı: dış koşullara bağlı olmamalı (ör. gerçek ağ çağrıları, tarih/saat).
  • Hızlı çalışmalı: birim testler süratli olmalı; yavaş testler gelişimi yavaşlatır.
  • Anlaşılır isimlendirme: test isimleri davranışı anlatmalı (ör. test_adds_two_numbers).
  • Refactor yaparken testleri güncelleyin; testler tasarımın bir belgesi gibi davranır.

TDD'e Geçiş İçin Pratik Stratejiler

  1. Küçük bir özellik seçin ve ekip olarak TDD döngüsünü uygulamaya başlayın.
  2. İlk sprintte sadece yeni kodlar için test yazmayı zorunlu kılın; eski kodu aşamalı olarak test kapsamına alın.
  3. Sürekli Entegrasyon (CI) pipeline'ınızda testleri çalıştırın; her PR'da testlerin geçmesi zorunlu olsun.
  4. Pair programming ve kod incelemeleri ile test kalitesini artırın.

Sık Yapılan Hatalar ve Kaçınma Yolları

  • Çok geniş kapsamlı "bütün sistemi" test eden unit testler yazmak yerine, integration testleri ayrı tutun.
  • Flaky (rassal/sıkıcı) testlerden kaçının: neden flaky olduğunu bulun ve izole edin.
  • Over-mocking: Fazla bağımlılık taklidi testlerin anlamını azaltabilir; mümkünse daha yüksek seviyede entegrasyon testi ekleyin.

Özet ve Sonraki Adımlar

Unit testler ve TDD küçük adımlarla güvenilirlik ve sürdürülebilirlik sağlar. Python için unittest modülü başlangıçta yeterlidir; farklı ihtiyaçlar için Python wiki'de farklı test framework'leri hakkında bilgi bulabilirsiniz: Python Testing Frameworks. JavaScript tarafında Jest hızlı bir başlangıç sunar. Rehberi uygularken küçük, sık ve gösterilebilir hedeflerle başlayın.

Kaynaklar