Mobil geliştirmede birim testi: nedir, yöntemler ve çerçeveler

Yazar: IT Sectr Yayınlanma: 2026-04-06 Okuma süresi: 9 dk

Birim testi, sistemin geri kalanından yalıtılmış olarak tek tek modüllerin veya kod işlevlerinin doğruluğunu test eden bir yazılım doğrulama yöntemidir. Martin Fowler, 2026'ya göre, birim testler CI/CD ve yeniden düzenlemenin temelidir ve kodun çalışabilirliği hakkında hızlı geri bildirim sağlar. Modül testi, geliştirmenin erken aşamalarında hataları tespit etmeye yardımcı olur ve düzeltme maliyetini kat kat azaltır.

Önemli Noktalar

  • Birim testi — harici bağımlılıklardan yalıtılmış tek bir modülün (işlev, yöntem, sınıf) doğrulanması
  • FIRST ilkeleri — Fast, Isolated, Repeatable, Self-validating, Timely — kaliteli testlerin temeli
  • Mock'lar ve stub'lar — harici bağımlılıkların (DB, API, dosya sistemi) yerine geçenler, test yalıtımını sağlar
  • TDD (Test-Driven Development) — test odaklı geliştirme metodolojisi: kırmızı-yeşil-yeniden düzenleme
  • Test piramidi — birim testler piramidin %70'ini oluşturur, her commit'te hızlı geri bildirim sağlar

Birim testi nedir?

Birim testi, kaynak kodun bireysel birimlerinin (işlevler, yöntemler, sınıflar) programın geri kalanından yalıtılarak doğrulanması sürecidir. Her test, modülün belirli bir kullanım senaryosunu çalıştırır ve sonucun beklenenle eşleşip eşleşmediğini kontrol eder. Birim testler, ana kodla aynı programlama dilinde yazılır ve geliştirme ortamında veya CI/CD hattında otomatik olarak çalıştırılır. Entegrasyon testlerinin aksine, birim testler gerçek veritabanları, dosya sistemleri veya ağ hizmetleriyle etkileşime girmez.

Birim testleri neden gereklidir?

Temel amaç, değişikliklerden sonra kodun doğruluğu hakkında hızlı geri bildirim sağlamaktır. Bir geliştirici bir yöntemi yeniden düzenlerse, birim test paketi davranışın bozulmadığını onaylar. Google Testing Blog (2025)'e göre, birim test kapsamı %60'ın üzerinde olan projelerde üretim olayları 2,5 kat daha az görülür. Ek faydalar: kod dokümantasyonu (testler API'nin nasıl kullanılacağını gösterir), yeniden düzenlemenin basitleştirilmesi (davranışı korurken uygulama değiştirilebilir) ve hızlı regresyon teşhisi.

Birim testi olarak kabul edilen nedir?

Her otomatik test bir birim testi değildir. Kriterler: tek bir modül (sınıf veya işlev) test edilir, harici bağımlılıklar mock veya stub ile değiştirilir, test milisaniyeler içinde çalışır ve bir sunucu veya veritabanı başlatılmasını gerektirmez. Gerçek bir veritabanına erişen test bir entegrasyon testidir. Tarayıcı açan bir test E2E testidir. Test türleri arasındaki sınırları anlamak, test piramidinde çabaların doğru dağıtılması için önemlidir.

FIRST ilkeleri ve AAA yapısı

Kaliteli birim testler, Robert C. Martin tarafından formüle edilen FIRST ilkelerini takip eder. Her test Fast (hızlı — milisaniye), Isolated (yalıtılmış — diğer testlere bağlı değil), Repeatable (tekrarlanabilir — her makinede aynı sonuç), Self-validating (kendi kendini doğrulayan — sonuç "geçti" veya "kaldı", manuel kontrol yok) ve Timely (zamanında — koddan önce veya aynı anda yazılmış) olmalıdır. Herhangi bir ilkeyi ihlal etmek testin değerini azaltır.

AAA yapısı (Arrange-Act-Assert)

Birim testleri yazmak için standart bir şablon. Arrange — veri ve bağımlılıkların hazırlanması: nesneler oluşturma, mock'ları yapılandırma, giriş parametrelerini ayarlama. Act — test edilen eylemin gerçekleştirilmesi: bir yöntem veya işlev çağırma. Assert — sonucun doğrulanması: gerçek değerin beklenen değerle karşılaştırılması. Üç bloğa bölme, testi okunabilir ve anlaşılır kılar. Assert bloğu karmaşık mantık gerektiriyorsa, test muhtemelen aynı anda çok fazla şeyi kontrol ediyordur.

kotlin
// Kotlin'de JUnit 5 ile AAA desenini kullanan birim testi örneği
class CalculatorTest {

    private lateinit var calculator: Calculator

    @BeforeEach
    fun setUp() {
        // ARRANGE — test nesnesini oluştur
        calculator = Calculator()
    }

    @Test
    fun addition_shouldReturnCorrectSum() {
        // ACT — eylemi gerçekleştir
        val result = calculator.add(2, 3)

        // ASSERT — sonucu doğrula
        Assertions.assertEquals(5, result)
    }
}

Test adlandırma

Test adı, neyin test edildiğini ve hangi sonucun beklendiğini açıklamalıdır. Biçim: [methodName]_[scenario]_[expectedResult]. Örnek: calculateTotal_whenDiscountApplied_shouldReturnDiscountedTotal. İyi bir test adı, bir yorumun yerini alır ve başarısız olduğunda hangi işlevselliğin bozulduğunu hemen gösterir. test1, checkSomething veya verify gibi adlardan kaçının — bilgi taşımazlar ve teşhisi zorlaştırırlar.

Mock, stub ve fake: ne ve ne zaman kullanılmalı

Test edilen modülü harici bağımlılıklardan yalıtmak için test çiftleri (test doubles) kullanılır. Ana türler: mock'lar — belirli bir yöntemin beklenen parametrelerle çağrıldığını doğrular; stub'lar — bir yöntem çağrıldığında önceden tanımlanmış değerler döndürür; fake'ler — gerçek bileşenlerin basitleştirilmiş uygulamaları (örneğin, bir veritabanıyla çalışan UserRepository yerine InMemoryUserRepository). Seçim, neyin doğrulanması gerektiğine bağlıdır: durum (stub) veya etkileşim (mock).

ÇiftNe doğrularÖrnek
MockDoğru parametrelerle yöntem çağrısıuserRepository.save(user) tam olarak 1 kez çağrıldı
StubDönüş değerirepository.findById(1) User(id=1, name="Test") döndürür
FakeBasitleştirilmiş uygulama yoluyla mantıkDB yerine HashMap ile InMemoryMapUserRepository
SpyGerçek bir nesnenin kısmi mock'lanmasıspy(repo).when(findById).thenReturn(user)

Mockito: Java/Kotlin'de mock örneği

Mockito, Java ve Kotlin için en popüler mock'lama çerçevesidir. mock() ile mock oluşturma, when().thenReturn() ile dönüş değerlerini yapılandırma ve verify() ile çağrıları doğrulama imkanı sağlar. Mockito'nun (5.x) modern sürümleri, statik mock'ları (mockStatic) ve BDDMockito (given-willReturn) aracılığıyla basitleştirilmiş sözdizimini destekler. Önemli bir kural: size ait olmayanı mock'lamayın — değer nesneleri ve standart kütüphaneler için mock oluşturmayın.

kotlin
// Kotlin'de Mockito ile birim testi örneği
class OrderServiceTest {

    @Mock
    private lateinit var paymentGateway: PaymentGateway

    @Mock
    private lateinit var userRepository: UserRepository

    private lateinit var orderService: OrderService

    @BeforeEach
    fun init() {
        MockitoAnnotations.openMocks(this)
        orderService = OrderService(paymentGateway, userRepository)
    }

    @Test
    fun processOrder_whenPaymentFails_shouldThrowException() {
        // given
        val user = User(id = 1, balance = 100.0)
        val order = Order(amount = 200.0)
        Mockito.`when`(paymentGateway.charge(any())).thenReturn(false)
        Mockito.`when`(userRepository.findById(1)).thenReturn(user)

        // when & then
        assert Throws<PaymentException> {
            orderService.processOrder(user.id, order)
        }

        // verify
        Mockito.verify(paymentGateway).charge(any())
    }
}

TDD: test odaklı geliştirme

TDD (Test-Driven Development), kod uygulamasından önce testin yazıldığı bir metodolojidir. "Kırmızı-Yeşil-Yeniden Düzenleme" döngüsü: başarısız olan bir test yazın (Kırmızı), testi geçmek için minimum kodu yazın (Yeşil), davranışı değiştirmeden kodu iyileştirin (Yeniden Düzenleme). TDD, tüm kodun testlerle kapsandığını (uygulanan işlevsellik için kapsam = %100) ve kodun test edilebilir olduğunu garanti eder — kod test etmesi zorsa, mimarinin iyileştirilmesi gerekir.

TDD'nin faydaları

IBM (2006-2026, boylamsal çalışma) araştırmasına göre, TDD kullanan ekipler, testleri koddan sonra yazan ekiplere kıyasla üretimde %40-80 daha az hata yapar. TDD ayrıca mimariyi iyileştirir: geliştirici, uygulamadan önce API tasarımı hakkında düşünmek zorunda kalır ve bu da gevşek bağlantı (loose coupling) ve yüksek uyum (high cohesion) sağlar. Ek bir etki de canlı dokümantasyondur: testler, her zaman güncel olan modül davranışının bir spesifikasyonu olarak hizmet eder.

TDD ne zaman uygun değildir?

TDD her zaman optimal değildir. UI bileşenlerini yalıtarak test etmek zordur — onlar için anlık görüntü testleri veya görsel regresyon testleri (Percy, Chromatic) daha etkilidir. Prototipleme ve araştırma (spike çözümler) test gerektirmez. Testleri olmayan eski kodu TDD ile kapsamak zordur — burada önce karakterizasyon testleri (yeniden düzenlemeden önce mevcut davranışı yakalayan testler) gereklidir. Bu durumlarda, TDD tamamen terk edilmez, uyarlanır — tüm eski kod için değil, değiştirilen işlevsellik için testler yazılır.

Mobil uygulamalarda birim testi

Mobil geliştirmenin kendine özgü yönleri vardır: iş mantığı genellikle UI koduyla (Activity, ViewController, ViewModel) karışır ve bu da birim testini zorlaştırır. En iyi uygulama ince View'lar, kalın ViewModel'lerdir: tüm mantığı UI bileşenlerinden ayrı sınıflara (UseCase, Repository, ViewModel) çıkarın ve bunlar öykünücü olmadan kolayca test edilebilir. Android ve iOS, bir cihaz başlatmadan JVM/Native üzerinde çalışan yerel birim test çerçevelerine sahiptir.

Android'de birim testleri (JUnit + Mockito/Robolectric)

Android birim testleri öykünücü olmadan yerel JVM'de çalışır ve yürütme hızı sağlar — tipik bir test 100ms'den kısa sürer. JUnit 5 ana çalıştırıcıdır. ViewModel testleri için, eşyordam testi için kotlinx-coroutines-test ve StateFlow testi için Turbine kullanın. Robolectric, gölge sınıfları yükleyerek öykünücü olmadan Android bağımlı bileşenleri (Context, Resources) test etmeye olanak tanır. Compose testleri için Compose UI Test kullanın — ancak bunlar UI testleridir, birim testleri değil.

iOS'ta birim testleri (XCTest + Quick/Nimble)

iOS birim testleri, XCTest (Xcode'da yerleşik) ile Swift'te yazılır. Quick + Nimble, daha okunabilir testler (describe/context/it) için BDD çerçeveleridir. Mock'lama için Cuckoo (mock oluşturma) veya SwiftyMocky kullanın. Swift, protokolleri ve bağımlılık enjeksiyonunu destekleyerek bağımlılıkların değiştirilmesini kolaylaştırır. Kilit nokta: iOS birim testleri gerçek bir cihazda değil, macOS simülatöründe çalışır. Donanım özellikleri (kamera, Bluetooth) gerektiren testler entegrasyon testleridir.

Flutter'da birim testleri (flutter_test + Mockito)

Flutter birim testleri flutter_test paketini kullanır ve öykünücü olmadan Dart VM'de çalışır. Mock'lama için, kod oluşturma (build_runner) ile birlikte mockito paketini kullanın. Widget testleri (aynı pakette) bireysel widget'ları test eder ancak işleme gerektirir ve daha yavaştır — bunları yalnızca UI mantığı doğrulaması için kullanın. Saf Dart mantığı (modeller, depolar, bloklar) flutter_test içe aktarılmadan normal Dart testleri olarak test edilir.

dart
// Flutter'da mockito ile birim testi örneği
import 'package:flutter_test/flutter_test.dart';
import 'package:mockito/mockito.dart';
import 'package:mockito/annotations.dart';

@GenerateMocks([ApiClient])
import 'user_repository_test.mocks.dart';

void main() {
    late MockApiClient mockApi;
    late UserRepository repository;

    setUp(() {
        mockApi = MockApiClient();
        repository = UserRepository(mockApi);
    });

    test('fetchUser returns user when API succeeds', () async {
        // Arrange
        final expectedUser = User(id: 1, name: 'Test');
        when(mockApi.getUser(1))
            .thenAnswer((_) async => expectedUser);

        // Act
        final result = await repository.fetchUser(1);

        // Assert
        expect(result, expectedUser);
        verify(mockApi.getUser(1)).called(1);
    });
}

En iyi uygulamalar ve yaygın hatalar

Etkili birim testi disiplin gerektirir. Ana kural: davranışı test edin, uygulamayı değil. Test, modülün dahili olarak nasıl uygulandığını (hangi özel yöntemlerin hangi sırayla çağrıldığını) bilmemelidir. Bir test uygulamaya bağlıysa, her yeniden düzenlemede kırılır ve değerini kaybeder. Test sözleşmeyi doğrular: X girdisinde, Y çıktısı olmalıdır. İstisna, çağrı sırasının önemli olduğu kritik performansa sahip algoritmaların testleridir.

  • Test başına bir doğrulama — bir mantıksal doğrulama için bir assert veya ilgili assert grubu
  • Tekrardan kaçının — ortak başlatma için @BeforeEach / setUp kullanın, farklı girdi verileri için parametreli testler kullanın
  • Özel yöntemleri test etmeyin — genel API aracılığıyla test edin. Özel bir yöntem kapsanmamışsa, mantığı dışarıdan görünmez
  • Sınır durumlarını kapsayın — boş koleksiyonlar, null/undefined, negatif sayılar, maksimum değerler
  • Testlerde Thread.sleep kullanmayın — testleri yavaş ve kararsız yapar. Test zaman aşımları ve eşyordamlar kullanın

Hangi kapsam yeterli kabul edilir?

%100 kapsam ulaşılamaz ve gereksiz bir hedeftir. Google Testing Blog (2025)'e göre, birim testleri için optimal kapsam seviyesi kod satırlarının %70-80'idir. %100 kapsam genellikle getter, setter ve yapıcıları test ederek elde edilir ve bu değer katmaz. Kritik iş mantığına odaklanın: karmaşık hesaplamalar, doğrulama, hata işleme, uç durumlar. Ölçüm için JaCoCo (Java), Coverage.py (Python), Istanbul (JS) kullanın ve CI'da bir eşik belirleyin — kapsam %60'ın altındayken derleme hatası.

CI/CD ve birim testleri

Birim testleri, herhangi bir CI/CD hattının ilk aşamasıdır. Derleme ve dağıtımdan önce, depoya her push'ta çalıştırılırlar. Ortalama birim test paketi çalışma süresi 5 dakikayı geçmemelidir — daha uzun olursa, testler "hızlı" olmaktan çıkar ve geliştiriciler onları yerel olarak çalıştırmayı bırakır. Testleri hızlı (birim) ve yavaş (entegrasyon) olarak ayırın ve hattın farklı aşamalarında çalıştırın. Hız için paralel yürütme ve hızlı başarısızlık kullanın.

Sıkça Sorulan Sorular

Birim testi ile entegrasyon testi arasındaki fark nedir?

Birim testi, harici bağımlılıkları mock'larla değiştirerek tek bir modülü yalıtarak doğrular. Entegrasyon testi, birden çok gerçek bileşen (DB, API, dosya sistemi) arasındaki etkileşimi doğrular. Birim testler milisaniyeler içinde, entegrasyon testleri saniyeler içinde çalışır. Test piramidinde birim testler %70'i oluşturur.

Birim testleri için hangi çerçeve seçilmeli?

Seçim platforma bağlıdır: Java/Kotlin için JUnit 5, iOS/Swift için XCTest, Python için pytest, JavaScript/TypeScript için Jest/Vitest, Flutter için flutter_test. Mock'lama için Mockito (Java), Cuckoo (iOS), unittest.mock (Python) veya vitest.mock (JS) kullanın. Tüm modern çerçeveler parametreli testleri, yerleşik iddiaları ve paralel yürütmeyi destekler.

F.I.R.S.T. test ilkeleri nelerdir?

Fast — test milisaniyeler içinde çalışır. Isolated — diğer testlere veya harici sistemlere bağlı değildir. Repeatable — her makinede aynı sonucu verir. Self-validating — sonucu otomatik olarak doğrular. Timely — koddan önce veya aynı anda yazılır. Tek bir ilkenin ihlali bile test etkinliğini azaltır.

Android/iOS'te ViewModel için birim testi yazmak gerekli mi?

Evet, kesinlikle. ViewModel iş mantığı içerir — olay işleme, veri dönüşümü, durum yönetimi. Android'de, eşyordamlar için kotlinx-coroutines-test ve StateFlow testi için Turbine kullanın. iOS'ta, ViewModel'de Combine Publishers veya async/await test edin. ViewModel testleri, öykünücü olmadan JVM/macOS'te çalışan saf birim testleridir.

Ağ istekleri olan kod nasıl test edilir?

Birim testlerinde ağ istekleri yürütülmez — HTTP istemci mock'larıyla değiştirilir. Android'de MockWebServer (OkHttp) kullanın — yerel bir HTTP sunucusu başlatır, gerçek ağ etkileşimini yeniden ürettiği için mock'lardan daha iyidir. MockWebServer, gerçekçiliği kaybetmeden yalıtım sağlar. iOS için — yanıtları kesmek ve değiştirmek için OHHTTPStubs veya URLProtocol kullanın.

Özet

  • Birim testi — hızlı geri bildirimle harici bağımlılıklardan yalıtılmış bireysel modüllerin doğrulanması
  • AAA yapısı — Arrange (hazırlık), Act (eylem), Assert (doğrulama) — standart test şablonu
  • Mock'lar ve stub'lar — yalıtım için test çiftleri: mock'lar çağrıları doğrular, stub'lar değer döndürür
  • TDD — test odaklı geliştirme (Kırmızı-Yeşil-Yeniden Düzenleme) hataları %40-80 azaltır
  • FIRST ilkeleri — Fast, Isolated, Repeatable, Self-validating, Timely — kaliteli testlerin temeli
  • Platform araçları — JUnit 5 (Android), XCTest (iOS), flutter_test (Flutter), Jest (React Native)
  • %70-80 kapsam — kritik iş mantığı için optimal seviye, getter ve setter test gerektirmez

Anahtar teslim bir mobil uygulama geliştireceğiz

IT Sectr, 2017'den beri girişimler ve işletmeler için iOS ve Android uygulamaları oluşturmaktadır. Size danışmanlık yapacak ve en iyi çözümü önereceğiz.

Projeyi tartış

Ayrıca okuyun