Unit test'in amacı
Unit test, yazılımın en küçük test edilebilir parçasını (genelde bir function veya class) izole şekilde test eder. AIOR projelerinde unit test sayesinde refactor güvenli olur, regression yakalanır, dokümantasyon olarak iş görür. Ancak unit test "her satır kapsa" yarışı değil — yanlış uygulanan unit test maliyet üretir.Neyi test ederiz, neyi etmeyiz
AIOR projelerinde uyguladığımız kural: business logic her zaman, infrastructure code seçici şekilde, framework boilerplate hiç. Bir fatura hesaplama function'ı test edilmeli; getter/setter test edilmemeli. Bir authentication validator test edilmeli; framework'ün constructor injection'ı test edilmemeli (zaten framework testleri ile garanti).AAA pattern
Her unit test üç fazdan oluşur:- Arrange — test verisini ve mock'ları hazırla.
- Act — test edilen kodu çağır.
- Assert — sonucu doğrula.
Mock kullanımı — pragmatik yaklaşım
Mock'lar test isolation için gerekli ama aşırı kullanım test'i kırılgan yapar:- External system'lar (DB, API, file system) mock'lanır.
- Same module içindeki dependency'leri mock'lamak çoğu zaman gereksiz.
- Pure function'ları mock'lamak yanlış.
- Mock setup'ı 10+ satır olunca tasarım kokusu.
AIOR'da MockK (Kotlin), Mockito (Java), Sinon (JS), Mock (Python) gibi standart araçlar kullanıyoruz.
Test naming convention
Test isminden ne test ettiğini anlamak gerek:- `testCalculateTotal()` — kötü, ne yaptığı net değil.
- `calculateTotal_withEmptyCart_returnsZero()` — iyi, beklenti net.
- `should return zero when cart is empty` — BDD stili, en okunabilir.
Code coverage — sayı değil hedef
Coverage %100 fetiş değildir. Pragmatik hedef: critical business logic %90+, edge case'ler kapsanmış. AIOR'da CI'da coverage threshold %70-80 — bunun altına düşerse build fail. Ancak coverage gaming (anlamsız test ekleyerek coverage artırmak) anti-pattern.Test sürdürülebilirlik kuralları
- Test'ler bağımsız olmalı — birinin başarısızlığı diğerini etkilememeli.
- Test sırasından bağımsız çalışmalı — random order'da geçmeli.
- Hızlı olmalı — toplam test suite < 30 saniye unit test için ideal.
- Deterministik olmalı — flaky testler güveni öldürür.
- Test'ler de refactor edilir — production kod ile aynı kalite standartı.
Property-based testing
Modern test yaklaşımı: input örnekleri yazmak yerine input'un özelliklerini tanımla, framework rastgele input üretir. AIOR'da Jest fast-check (JS), Hypothesis (Python), Kotest property testing kullanıyoruz. Özellikle data validation ve algoritma test için güçlü.Mutation testing
Test kalitesini ölçmenin gerçek yolu. Production kodda küçük değişiklikler yapıp test'lerin yakaladığını kontrol eder. Düşük mutation score, coverage yüksek olsa bile test kalitesinin düşük olduğunu gösterir. AIOR'da PIT (Java), Stryker (JS) gibi araçlar critical projelerde standart.Sonuç
Unit test 2026'da hâlâ yazılım kalitesinin temel taşı. Doğru naming, AAA pattern, pragmatik mock kullanımı ve sürdürülebilir test kodu ile yıllarca yaşayan test suite'leri kurulabilir. AIOR olarak müşteri projelerinde test disiplinini standart paket halinde uyguluyoruz. Sizin unit test pratiğinizde en sık karşılaştığınız problem ne — flaky test, mock complexity, yoksa coverage hedefleri mi?The purpose of unit testing
Unit tests verify the smallest testable piece of software (usually a function or class) in isolation. On AIOR projects, unit tests make refactoring safe, catch regressions, and act as documentation. But they're not a race for "every line covered" — misapplied unit testing produces cost.What we test, what we don't
The rule we apply on AIOR projects: business logic always, infrastructure code selectively, framework boilerplate never. A billing calculation function must be tested; getters/setters must not. An authentication validator must be tested; a framework's constructor injection must not (it's already guaranteed by framework tests).AAA pattern
Every unit test has three phases:- Arrange — set up test data and mocks.
- Act — call the code under test.
- Assert — verify the result.
Mocking — a pragmatic approach
Mocks are necessary for test isolation, but overuse makes tests brittle:- External systems (DB, API, file system) get mocked.
- Mocking dependencies inside the same module is usually unnecessary.
- Mocking pure functions is wrong.
- Mock setup longer than 10 lines is a design smell.
AIOR uses standard tools: MockK (Kotlin), Mockito (Java), Sinon (JS), Mock (Python).
Test naming convention
The test name should reveal what it tests:- `testCalculateTotal()` — bad, what it does is unclear.
- `calculateTotal_withEmptyCart_returnsZero()` — good, expectation clear.
- `should return zero when cart is empty` — BDD style, most readable.
Code coverage — a target, not a number
100% coverage isn't a fetish. Pragmatic target: critical business logic 90%+, edge cases covered. AIOR's CI coverage threshold is 70–80% — below that, build fails. But coverage gaming (adding meaningless tests to lift coverage) is an anti-pattern.Test sustainability rules
- Tests must be independent — one failing must not affect another.
- They must run regardless of order — pass in random order.
- They must be fast — total unit test suite under 30 seconds ideal.
- They must be deterministic — flaky tests destroy trust.
- Tests are also refactored — same quality standard as production code.