Sparround

Performans, memory leak-lər və testing

Memory leak — lazımsız obyektin GC-dən "gizlənməsi": kimsə ona istinad saxlayır. Android-in klassik leak mənbələri:

  • Static sahədə Activity/Context/View
  • Fragment-də binding-in onDestroyView-da təmizlənməməsi
  • Qeydiyyatdan çıxarılmayan listener/receiver/callback
  • Anonim inner class-ların (Handler, Runnable) xarici class istinadı
  • Singleton-lara ötürülən activity context

Alət: LeakCanary (debug-da avtomatik aşkarlama), Memory Profiler (heap dump analizi). Simptomlar: yavaş-yavaş artan yaddaş, OutOfMemoryError, GC pauzalarından donmalar.

Test piramidası Android-də:

  • Unit testlər (çox, sürətli) — ViewModel, use case, repository məntiqi; JUnit + fake-lər/MockK; coroutine üçün runTest + TestDispatcher; Flow üçün Turbine.
  • Integration — Room DAO (in-memory DB), API qatı (MockWebServer).
  • UI testlər (az, yavaş) — Espresso (View), Compose Testing (composeTestRule); kritik axınlar üçün (login, köçürmə).

DI burada qazanc verir: konstruktor injection sayəsində hər şey fake ilə əvəzlənə bilir.

kotlin
@OptIn(ExperimentalCoroutinesApi::class)
class TransferViewModelTest {

    private val dispatcher = StandardTestDispatcher()

    @Before fun setup() { Dispatchers.setMain(dispatcher) }
    @After fun tearDown() { Dispatchers.resetMain() }

    @Test
    fun `declined transfer surfaces reason`() = runTest {
        val repo = FakeTransferRepository(
            result = TransferResult.Declined("Günlük limit aşılıb")
        )
        val vm = TransferViewModel(repo)

        vm.uiState.test {                      // Turbine
            vm.submit(amount = "5000.00", to = "AZ45...")
            advanceUntilIdle()

            val state = expectMostRecentItem()
            assertEquals("Günlük limit aşılıb", state.error)
            assertFalse(state.isLoading)
        }
    }
}

ViewModel unit testi: TestDispatcher + Turbine

"Nəyi test edirsən?" sualının balanslı cavabı: hər sətri yox, riski test edirik: pul hesablamaları və limit məntiqi — 100%; ViewModel state keçidləri — əsas ssenarilər; mapper-lər — nümunə JSON-larla; UI — yalnız kritik axınlar (login, köçürmə təsdiqi). Coverage rəqəmi məqsəd deyil, nəticədir — "90% coverage amma pul məntiqi testsiz" anti-nümunəsini demək müsahibədə yaxşı işləyir.

🛠 Tapşırıq

Leak yarat və tut:

  • Static sahədə activity context saxlayaraq qəsdən leak yarat, LeakCanary trace-ini oxu və düzəlt.
  • Bir ViewModel üçün unit test yaz: StandardTestDispatcher + runTest, xəta ssenarisini fake repository ilə yoxla.
  • Bir Room DAO testini in-memory DB ilə keç.

Bitdi sayılır: üç testin də yaşıl olduğu və leak trace-ini izah edə bildiyin halda.

📚 Mənbələr və sənədlər