Test yazdırmaq: unit və Compose UI
Test yazmaq agentin ən çox fayda verdiyi sahələrdən biridir: iş mexanikidir, nəticə dərhal yoxlanıla bilir (test ya keçir, ya yox), və insanların ən çox təxirə saldığı işdir.
Amma bir tələ var: agent testi keçirmək üçün yaza bilər, davranışı yoxlamaq üçün yox. Tipik təzahürləri:
- Test kodun implementasiyasını təkrarlayır — yəni kod dəyişsə test də dəyişməlidir, halbuki davranış eynidir.
- Assertion zəifdir:
assertNotNull(result)— nəticənin doğruluğunu yoxlamır. - Xəta və sərhəd halları yoxdur, yalnız "hər şey yaxşıdır" ssenarisi.
- Mock-lar o qədər çoxdur ki, test əslində mock-ları yoxlayır, kodu yox.
// WEAK TEST — what the agent writes by default
@Test
fun testGetOrders() = runTest {
val repo = mockk<OrderRepository>()
coEvery { repo.getOrders() } returns listOf(mockk())
val vm = OrderViewModel(repo)
vm.load()
assertNotNull(vm.uiState.value) // what does this check? essentially nothing
}
// STRONG TEST — verifies behaviour
@Test
fun `load - ui state becomes error when the repository fails`() = runTest {
val repo = FakeOrderRepository(
result = Result.failure(IOException("no network"))
)
val vm = OrderViewModel(repo, testDispatcher)
vm.load()
val state = vm.uiState.value
assertTrue(state is OrderUiState.Error)
assertEquals(ErrorType.NETWORK, (state as OrderUiState.Error).type)
assertTrue(state.isRetryable)
}Fərq assertion-un gücündədir. İkinci test kodun *nə etməli olduğunu* təsvir edir; birincisi sadəcə çağırışın crash vermədiyini yoxlayır.
| Tapşırıqda yazın | Nəyin qarşısını alır |
|---|---|
| "Xəta və boş halları da əhatə et" | Yalnız happy path testləri |
| "Assertion konkret dəyəri yoxlasın, null olmamağı yox" | Praktiki olaraq heç nə yoxlamayan testlər |
| "Mock yerinə fake işlət" | Mock-ları yoxlayan testlər |
| "Testlər implementasiyaya yox, davranışa bağlansın" | Refaktor zamanı qırılan testlər |
| "Mətn yerinə `testTag` işlət" (UI testləri) | Lokalizasiya dəyişəndə qırılan testlər |
Compose UI testləri üçün əsas API-lər:
- `createComposeRule()` — Activity lazım olmayan hallar üçün.
- `createAndroidComposeRule<T>()` — Activity-yə çıxış lazım olduqda.
- Asılılıqlar:
androidx.compose.ui:ui-test-junit4(androidTest) vəandroidx.compose.ui:ui-test-manifest(debug). - Finder-lər:
onNodeWithText,onNodeWithTag,onNode. - Hərəkət və assertion:
performClick(),assertIsDisplayed().
Compose test qaydası avtomatik sinxronizasiya edir — UI boş olana qədər gözləyir. Ona görə Thread.sleep işlətmək həm lazımsız, həm zərərlidir: testi yavaşladır və kövrək edir.
Agentə test yazdırmağın ən güclü tərəfi — mövcud kod üçün geriyə dönük test yazmaqdır. Test olmayan legacy kod refaktordan qorxu yaradır. Agent əvvəlcə mövcud davranışı təsbit edən testlər yazır (characterization tests), sonra refaktor təhlükəsiz olur. Bu, agentin ən yüksək dəyər verdiyi ssenarilərdən biridir.
📚 Mənbələr və sənədlər
- Jetpack Compose testlərirəsmideveloper.android.com
`createComposeRule`, finder-lər, assertion-lar və asılılıqlar.
- Android-də testrəsmideveloper.android.com
- Test dublyorları (fake, mock)rəsmideveloper.android.com
Fake-in mock-dan nə vaxt üstün olduğu üzrə rəsmi tövsiyə.