1. Pengantar
Di codelab Menavigasi antarlayar dengan Compose, Anda telah mempelajari cara menambahkan navigasi ke aplikasi Compose menggunakan komponen Jetpack Navigation Compose.
Aplikasi Cupcake memiliki beberapa layar untuk dinavigasi dan berbagai tindakan yang dapat dilakukan pengguna. Aplikasi ini memberikan peluang besar untuk mengasah keterampilan pengujian otomatis Anda. Dalam codelab ini, Anda akan menulis sejumlah pengujian UI untuk aplikasi Cupcake dan mempelajari cara melakukan pendekatan untuk memaksimalkan cakupan pengujian.
Prasyarat
- Pemahaman tentang bahasa Kotlin, termasuk jenis fungsi, lambda, dan fungsi cakupan
- Menyelesaikan codelab Menavigasi antarlayar dengan Compose
Yang akan Anda pelajari
- Menguji komponen Jetpack Navigation dengan Compose.
- Membuat status UI yang konsisten untuk setiap pengujian UI.
- Membuat fungsi bantuan untuk pengujian.
Yang akan Anda bangun
- Pengujian UI untuk aplikasi Cupcake
Yang Anda butuhkan
- Versi terbaru Android Studio
- Koneksi internet untuk mendownload kode awal
2. Mendownload kode awal
- Di Android Studio, buka folder
basic-android-kotlin-compose-training-cupcake
. - Buka kode aplikasi Cupcake di Android Studio.
3. Menyiapkan Cupcake untuk pengujian UI
Menambahkan dependensi androidTest
Alat build Gradle memungkinkan Anda menambahkan dependensi untuk modul tertentu. Fungsi ini mencegah dependensi agar tidak dikompilasi. Anda sudah terbiasa dengan konfigurasi implementation
saat menyertakan dependensi dalam sebuah project. Anda telah menggunakan kata kunci ini untuk mengimpor dependensi dalam file build.gradle.kts
modul aplikasi. Menggunakan kata kunci implementation
akan membuat dependensi tersebut tersedia untuk semua set sumber dalam modul tersebut; pada tahap ini, Anda telah mendapatkan pengalaman dengan set sumber main
, test
, dan androidTest
.
Pengujian UI terdapat dalam set sumbernya sendiri yang disebut androidTest
. Dependensi yang hanya diperlukan untuk modul ini tidak perlu dikompilasi untuk modul lain, seperti modul main
, tempat kode aplikasi berada. Saat menambahkan dependensi yang hanya digunakan oleh pengujian UI, gunakan kata kunci androidTestImplementation
untuk mendeklarasikan dependensi dalam file build.gradle.kts
modul aplikasi. Tindakan ini akan memastikan bahwa dependensi pengujian UI dikompilasi hanya saat Anda menjalankan pengujian UI.
Selesaikan langkah-langkah berikut untuk menambahkan dependensi yang diperlukan untuk menulis pengujian UI:
- Buka file
build.gradle.kts(Module :app)
. - Tambahkan dependensi berikut ke bagian
dependencies
pada file:
androidTestImplementation(platform("androidx.compose:compose-bom:2023.05.01"))
androidTestImplementation("androidx.compose.ui:ui-test-junit4")
androidTestImplementation("androidx.navigation:navigation-testing:2.6.0")
androidTestImplementation("androidx.test.espresso:espresso-intents:3.5.1")
androidTestImplementation("androidx.test.ext:junit:1.1.5")
Membuat direktori pengujian UI
- Klik kanan direktori
src
pada tampilan project lalu pilih New > Directory.
- Pilih opsi androidTest/java.
Membuat paket pengujian
- Klik kanan direktori
androidTest/java
di jendela project, lalu pilih New > Package.
- Beri nama paket com.example.cupcake.test.
Membuat class pengujian navigasi
Di direktori test
, buat class Kotlin baru bernama CupcakeScreenNavigationTest
.
4. Menyiapkan host navigasi
Pada codelab sebelumnya, Anda telah mempelajari bahwa pengujian UI di Compose memerlukan aturan pengujian Compose. Hal yang sama berlaku untuk pengujian Jetpack Navigation. Namun, navigasi pengujian memerlukan beberapa penyiapan tambahan melalui aturan pengujian Compose.
Saat menguji Navigasi Compose, Anda tidak akan memiliki akses ke NavHostController
yang sama dengan yang Anda lakukan di kode aplikasi. Namun, Anda dapat menggunakan TestNavHostController
dan mengonfigurasi aturan pengujian dengan pengontrol navigasi ini. Di bagian ini, Anda akan mempelajari cara mengonfigurasi dan menggunakan kembali aturan pengujian untuk pengujian navigasi.
- Di
CupcakeScreenNavigationTest.kt
, buat aturan pengujian menggunakancreateAndroidComposeRule
dan teruskanComponentActivity
sebagai parameter jenis.
import androidx.activity.ComponentActivity
import androidx.compose.ui.test.junit4.createAndroidComposeRule
import org.junit.Rule
@get:Rule
val composeTestRule = createAndroidComposeRule<ComponentActivity>()
Untuk memastikan aplikasi Anda menuju ke tempat yang benar, Anda perlu mereferensikan instance TestNavHostController
untuk memeriksa rute navigasi host navigasi saat aplikasi mengambil tindakan untuk melakukan navigasi.
- Buat instance
TestNavHostController
sebagai variabellateinit
. Di Kotlin, kata kuncilateinit
digunakan untuk mendeklarasikan properti yang dapat diinisialisasi setelah objek dideklarasikan.
import androidx.navigation.testing.TestNavHostController
private lateinit var navController: TestNavHostController
Berikutnya, tentukan composable yang ingin Anda gunakan untuk pengujian UI.
- Buat metode yang disebut
setupCupcakeNavHost()
. - Dalam metode
setupCupcakeNavHost()
, panggil metodesetContent()
pada aturan pengujian Compose yang Anda buat. - Di dalam lambda yang diteruskan ke metode
setContent()
, panggil composableCupcakeApp()
.
import com.example.cupcake.CupcakeApp
fun setupCupcakeNavHost() {
composeTestRule.setContent {
CupcakeApp()
}
}
Sekarang Anda perlu membuat objek TestNavHostContoller
di class pengujian. Anda menggunakan objek ini nanti untuk menentukan status navigasi, karena aplikasi menggunakan pengontrol untuk menavigasi berbagai layar di aplikasi Cupcake.
- Siapkan host navigasi menggunakan lambda yang Anda buat sebelumnya. Lakukan inisialisasi pada variabel
navController
yang Anda buat, daftarkan navigator, lalu teruskanTestNavHostController
tersebut ke composableCupcakeApp
.
import androidx.compose.ui.platform.LocalContext
fun setupCupcakeNavHost() {
composeTestRule.setContent {
navController = TestNavHostController(LocalContext.current).apply {
navigatorProvider.addNavigator(ComposeNavigator())
}
CupcakeApp(navController = navController)
}
}
Setiap pengujian di class CupcakeScreenNavigationTest
melibatkan pengujian aspek navigasi. Oleh karena itu, setiap pengujian bergantung pada objek TestNavHostController
yang Anda buat. Daripada harus memanggil fungsi setupCupcakeNavHost()
secara manual untuk setiap pengujian guna menyiapkan pengontrol nav, Anda dapat melakukannya secara otomatis menggunakan anotasi @Before
yang disediakan oleh library junit. Jika metode dianotasi dengan @Before
, metode tersebut akan berjalan sebelum setiap metode yang dianotasi dengan @Test
.
- Tambahkan anotasi
@Before
ke metodesetupCupcakeNavHost()
.
import org.junit.Before
@Before
fun setupCupcakeNavHost() {
composeTestRule.setContent {
navController = TestNavHostController(LocalContext.current).apply {
navigatorProvider.addNavigator(ComposeNavigator())
}
CupcakeApp(navController = navController)
}
}
5. Menulis pengujian navigasi
Memverifikasi tujuan awal
Ingat bahwa saat membangun aplikasi Cupcake, Anda membuat class enum
bernama CupcakeScreen
yang berisi konstanta untuk mendikte navigasi aplikasi.
CupcakeScreen.kt
/**
* enum values that represent the screens in the app
*/
enum class CupcakeScreen(@StringRes val title: Int) {
Start(title = R.string.app_name),
Flavor(title = R.string.choose_flavor),
Pickup(title = R.string.choose_pickup_date),
Summary(title = R.string.order_summary)
}
Semua aplikasi yang memiliki UI memiliki layar utama. Untuk Cupcake, layar tersebut adalah Layar Mulai Pesanan. Pengontrol navigasi dalam composable CupcakeApp
menggunakan item Start
dari enum CupcakeScreen
untuk menentukan kapan harus membuka layar ini. Saat aplikasi dimulai, jika rute tujuan belum ada, rute tujuan host navigasi diatur ke CupcakeScreen.Start.name
.
Anda harus menulis pengujian terlebih dahulu untuk memverifikasi bahwa Layar Mulai Pesanan adalah rute tujuan saat ini ketika aplikasi dimulai.
- Buat fungsi dengan nama
cupcakeNavHost_verifyStartDestination()
dan anotasikan dengan@Test
.
import org.junit.Test
@Test
fun cupcakeNavHost_verifyStartDestination() {
}
Sekarang Anda harus mengonfirmasi bahwa rute tujuan awal pengontrol navigasi adalah Layar Mulai Pesanan.
- Nyatakan bahwa nama rute yang diharapkan (dalam hal ini,
CupcakeScreen.Start.name
) sama dengan rute tujuan entri data sebelumnya dari pengontrol navigasi saat ini.
import org.junit.Assert.assertEquals
...
@Test
fun cupcakeNavHost_verifyStartDestination() {
assertEquals(CupcakeScreen.Start.name, navController.currentBackStackEntry?.destination?.route)
}
Membuat metode bantuan
Pengujian UI sering kali mengharuskan pengulangan langkah untuk menempatkan UI dalam status saat bagian UI tertentu dapat diuji. UI kustom juga dapat memerlukan pernyataan kompleks yang memerlukan beberapa baris kode. Pernyataan yang Anda tulis di bagian sebelumnya memerlukan banyak kode, dan Anda menggunakan pernyataan yang sama berkali-kali saat menguji navigasi di aplikasi Cupcake. Dalam situasi ini, menulis metode bantuan dalam pengujian menghindarkan Anda dari menulis kode duplikat.
Untuk setiap pengujian navigasi yang Anda tulis, Anda menggunakan properti name
dari item enum CupcakeScreen
untuk memeriksa apakah rute tujuan saat ini dari pengontrol navigasi sudah benar. Anda menulis fungsi bantuan yang dapat Anda panggil setiap kali Anda ingin membuat pernyataan tersebut.
Selesaikan langkah-langkah berikut untuk membuat fungsi bantuan ini:
- Buat file Kotlin kosong di direktori
test
bernamaScreenAssertions
.
- Tambahkan fungsi ekstensi ke class
NavController
yang disebutassertCurrentRouteName()
dan teruskan string untuk nama rute yang diharapkan dalam tanda tangan metode.
fun NavController.assertCurrentRouteName(expectedRouteName: String) {
}
- Dalam fungsi ini, nyatakan bahwa
expectedRouteName
sama dengan rute tujuan entri data sebelumnya dari pengontrol navigasi saat ini.
import org.junit.Assert.assertEquals
...
fun NavController.assertCurrentRouteName(expectedRouteName: String) {
assertEquals(expectedRouteName, currentBackStackEntry?.destination?.route)
}
- Buka file CupcakeScreenNavigationTest dan ubah fungsi
cupcakeNavHost_verifyStartDestination()
untuk menggunakan fungsi ekstensi baru Anda, bukan pernyataan yang panjang.
@Test
fun cupcakeNavHost_verifyStartDestination() {
navController.assertCurrentRouteName(CupcakeScreen.Start.name)
}
Sejumlah pengujian juga memerlukan interaksi dengan komponen UI. Dalam codelab ini, komponen tersebut sering ditemukan menggunakan string resource. Anda dapat mengakses composable berdasarkan string resource-nya dengan metode Context.getString()
, yang dapat Anda baca di sini. Saat menulis pengujian UI di Compose, menerapkan metode ini akan terlihat seperti ini:
composeTestRule.onNodeWithText(composeTestRule.activity.getString(R.string.my_string)
Ini adalah petunjuk panjang dan dapat disederhanakan dengan penambahan fungsi ekstensi.
- Buat file baru dalam paket
com.example.cupcake.test
bernama ComposeRuleExtensions.kt. Pastikan file ini adalah file Kotlin kosong.
- Tambahkan kode berikut ke file tersebut.
import androidx.activity.ComponentActivity
import androidx.annotation.StringRes
import androidx.compose.ui.test.SemanticsNodeInteraction
import androidx.compose.ui.test.junit4.AndroidComposeTestRule
import androidx.compose.ui.test.onNodeWithText
import androidx.test.ext.junit.rules.ActivityScenarioRule
fun <A : ComponentActivity> AndroidComposeTestRule<ActivityScenarioRule<A>, A>.onNodeWithStringId(
@StringRes id: Int
): SemanticsNodeInteraction = onNodeWithText(activity.getString(id))
Fungsi ekstensi ini memungkinkan Anda mengurangi jumlah kode yang Anda tulis saat menemukan komponen UI dengan resource string-nya. Daripada menulis ini:
composeTestRule.onNodeWithText(composeTestRule.activity.getString(R.string.my_string)
Sekarang Anda dapat menggunakan petunjuk berikut:
composeTestRule.onNodeWithStringId(R.string.my_string)
Memastikan layar Mulai tidak memiliki tombol Atas
Desain awal aplikasi Cupcake tidak memiliki tombol Up (Atas) di toolbar layar Mulai.
Layar Mulai tidak memiliki tombol karena tidak ada navigasi ke Atas (Up) dari layar ini, karena layar ini adalah layar awal. Ikuti langkah-langkah berikut untuk membuat fungsi yang mengonfirmasi bahwa layar Mulai tidak memiliki tombol Atas:
- Buat metode dengan nama
cupcakeNavHost_verifyBackNavigationNotShownOnStartOrderScreen()
dan anotasikan dengan@Test
.
@Test
fun cupcakeNavHost_verifyBackNavigationNotShownOnStartOrderScreen() {
}
Di Cupcake, tombol Atas memiliki deskripsi konten yang diatur ke string dari resource R.string.back_button
.
- Buat variabel dalam fungsi pengujian dengan nilai resource
R.string.back_button
.
@Test
fun cupcakeNavHost_verifyBackNavigationNotShownOnStartOrderScreen() {
val backText = composeTestRule.activity.getString(R.string.back_button)
}
- Nyatakan bahwa node dengan deskripsi konten ini tidak ada di layar.
@Test
fun cupcakeNavHost_verifyBackNavigationNotShownOnStartOrderScreen() {
val backText = composeTestRule.activity.getString(R.string.back_button)
composeTestRule.onNodeWithContentDescription(backText).assertDoesNotExist()
}
Memverifikasi navigasi ke layar Rasa
Mengklik salah satu tombol di layar Mulai akan memicu metode yang menginstruksikan pengontrol navigasi untuk membuka layar Flavor (Rasa).
Dalam pengujian ini, Anda akan menulis perintah untuk mengklik tombol guna memicu navigasi ini dan memverifikasi bahwa rute tujuannya adalah layar Flavor (Rasa).
- Buat fungsi dengan nama
cupcakeNavHost_clickOneCupcake_navigatesToSelectFlavorScreen()
dan anotasikan dengan@Test
.
@Test
fun cupcakeNavHost_clickOneCupcake_navigatesToSelectFlavorScreen(){
}
- Temukan tombol One Cupcake berdasarkan ID resource string dan lakukan tindakan klik pada tombol tersebut.
import com.example.cupcake.R
...
@Test
fun cupcakeNavHost_clickOneCupcake_navigatesToSelectFlavorScreen() {
composeTestRule.onNodeWithStringId(R.string.one_cupcake)
.performClick()
}
- Nyatakan bahwa nama rute saat ini adalah nama layar Rasa.
@Test
fun cupcakeNavHost_clickOneCupcake_navigatesToSelectFlavorScreen() {
composeTestRule.onNodeWithStringId(R.string.one_cupcake)
.performClick()
navController.assertCurrentRouteName(CupcakeScreen.Flavor.name)
}
Menulis metode bantuan lainnya
Aplikasi Cupcake memiliki alur navigasi yang sebagian besar linear. Setelah mengklik tombol Cancel, Anda hanya dapat membuka aplikasi melalui satu arah. Oleh karena itu, saat menguji layar yang lebih lanjut pada aplikasi, Anda dapat mengulangi kode untuk membuka area yang ingin diuji. Situasi ini membutuhkan penggunaan lebih banyak metode bantuan sehingga Anda hanya perlu menulis kode tersebut sekali.
Setelah menguji navigasi ke layar Rasa, buat metode yang menavigasi ke layar Rasa sehingga Anda tidak perlu mengulangi kode tersebut untuk pengujian mendatang.
- Buat metode yang disebut
navigateToFlavorScreen()
.
private fun navigateToFlavorScreen() {
}
- Tulis perintah untuk menemukan tombol One Cupcake dan lakukan tindakan klik pada tombol tersebut, seperti yang Anda lakukan di bagian sebelumnya.
private fun navigateToFlavorScreen() {
composeTestRule.onNodeWithStringId(R.string.one_cupcake)
.performClick()
}
Ingat bahwa tombol Next di layar Rasa tidak akan dapat diklik hingga rasa dipilih Metode ini hanya dimaksudkan untuk menyiapkan UI bagi navigasi. Setelah Anda memanggil metode ini, UI harus dalam status yang memungkinkan tombol Next dapat diklik.
- Temukan node di UI dengan string
R.string.chocolate
dan lakukan tindakan klik pada node tersebut untuk memilihnya.
private fun navigateToFlavorScreen() {
composeTestRule.onNodeWithStringId(R.string.one_cupcake)
.performClick()
composeTestRule.onNodeWithStringId(R.string.chocolate)
.performClick()
}
Lihat apakah Anda dapat menulis metode bantuan yang membuka layar Pengambilan dan layar Ringkasan. Cobalah latihan ini sendiri sebelum melihat solusinya.
Gunakan kode berikut untuk melakukannya:
private fun getFormattedDate(): String {
val calendar = Calendar.getInstance()
calendar.add(java.util.Calendar.DATE, 1)
val formatter = SimpleDateFormat("E MMM d", Locale.getDefault())
return formatter.format(calendar.time)
}
private fun navigateToPickupScreen() {
navigateToFlavorScreen()
composeTestRule.onNodeWithStringId(R.string.next)
.performClick()
}
private fun navigateToSummaryScreen() {
navigateToPickupScreen()
composeTestRule.onNodeWithText(getFormattedDate())
.performClick()
composeTestRule.onNodeWithStringId(R.string.next)
.performClick()
}
Saat menguji layar di luar layar Mulai, Anda harus menguji fungsi tombol Atas untuk memastikan layar mengarahkan navigasi ke layar sebelumnya. Pertimbangkan untuk membuat fungsi bantuan untuk menemukan dan mengklik tombol Atas.
private fun performNavigateUp() {
val backText = composeTestRule.activity.getString(R.string.back_button)
composeTestRule.onNodeWithContentDescription(backText).performClick()
}
Memaksimalkan cakupan pengujian
Rangkaian pengujian aplikasi harus menguji fungsi aplikasi sebanyak mungkin. Dalam lingkungan yang sempurna, rangkaian pengujian UI akan mencakup 100% fungsi UI. Dalam praktiknya, jumlah cakupan pengujian ini sulit dicapai karena ada banyak faktor di luar aplikasi yang dapat memengaruhi UI, seperti perangkat dengan ukuran layar unik, versi sistem operasi Android yang berbeda, dan aplikasi pihak ketiga yang dapat memengaruhi aplikasi lain di ponsel.
Salah satu cara untuk memaksimalkan cakupan pengujian adalah dengan menulis pengujian bersama fitur saat Anda menambahkannya. Dengan demikian, Anda tidak akan terlalu jauh membuat fitur baru dan harus kembali untuk mengingat semua kemungkinan skenario. Cupcake adalah aplikasi yang cukup kecil untuk saat ini, dan Anda sudah menguji sebagian besar navigasi aplikasi. Namun, masih banyak status navigasi yang perlu diuji.
Lihat apakah Anda dapat menulis pengujian untuk memverifikasi status navigasi berikut. Coba implementasikan sendiri sebelum melihat solusinya.
- Membuka layar Mulai dengan mengklik tombol Atas dari layar Rasa
- Membuka layar Mulai dengan mengklik tombol Cancel dari layar Rasa
- Membuka layar Pengambilan
- Membuka layar Rasa dengan mengklik tombol Atas dari layar Pengambilan
- Membuka layar Mulai dengan mengklik tombol Cancel dari layar Pengambilan
- Membuka layar Ringkasan
- Membuka layar Mulai dengan mengklik tombol Cancel dari layar Ringkasan
@Test
fun cupcakeNavHost_clickNextOnFlavorScreen_navigatesToPickupScreen() {
navigateToFlavorScreen()
composeTestRule.onNodeWithStringId(R.string.next)
.performClick()
navController.assertCurrentRouteName(CupcakeScreen.Pickup.name)
}
@Test
fun cupcakeNavHost_clickBackOnFlavorScreen_navigatesToStartOrderScreen() {
navigateToFlavorScreen()
performNavigateUp()
navController.assertCurrentRouteName(CupcakeScreen.Start.name)
}
@Test
fun cupcakeNavHost_clickCancelOnFlavorScreen_navigatesToStartOrderScreen() {
navigateToFlavorScreen()
composeTestRule.onNodeWithStringId(R.string.cancel)
.performClick()
navController.assertCurrentRouteName(CupcakeScreen.Start.name)
}
@Test
fun cupcakeNavHost_clickNextOnPickupScreen_navigatesToSummaryScreen() {
navigateToPickupScreen()
composeTestRule.onNodeWithText(getFormattedDate())
.performClick()
composeTestRule.onNodeWithStringId(R.string.next)
.performClick()
navController.assertCurrentRouteName(CupcakeScreen.Summary.name)
}
@Test
fun cupcakeNavHost_clickBackOnPickupScreen_navigatesToFlavorScreen() {
navigateToPickupScreen()
performNavigateUp()
navController.assertCurrentRouteName(CupcakeScreen.Flavor.name)
}
@Test
fun cupcakeNavHost_clickCancelOnPickupScreen_navigatesToStartOrderScreen() {
navigateToPickupScreen()
composeTestRule.onNodeWithStringId(R.string.cancel)
.performClick()
navController.assertCurrentRouteName(CupcakeScreen.Start.name)
}
@Test
fun cupcakeNavHost_clickCancelOnSummaryScreen_navigatesToStartOrderScreen() {
navigateToSummaryScreen()
composeTestRule.onNodeWithStringId(R.string.cancel)
.performClick()
navController.assertCurrentRouteName(CupcakeScreen.Start.name)
}
6. Menulis pengujian untuk layar Pesanan
Navigasi hanyalah salah satu aspek dari fungsi aplikasi Cupcake. Pengguna juga berinteraksi dengan setiap layar aplikasi. Anda harus memverifikasi apa yang muncul di layar tersebut dan tindakan yang dilakukan di layar tersebut memberikan hasil yang benar. SelectOptionScreen adalah bagian penting dari aplikasi.
Di bagian ini, Anda menulis pengujian untuk memverifikasi bahwa konten di layar ini ditetapkan dengan benar.
Menguji konten layar Pilih Rasa
- Buat class baru di dalam direktori
app/src/androidTest
yang disebutCupcakeOrderScreenTest
, tempat file pengujian lainnya berada.
- Di class ini, buat
AndroidComposeTestRule
.
@get:Rule
val composeTestRule = createAndroidComposeRule<ComponentActivity>()
- Buat fungsi dengan nama
selectOptionScreen_verifyContent()
dan anotasikan dengan@Test
.
@Test
fun selectOptionScreen_verifyContent() {
}
Dalam fungsi ini, pada akhirnya Anda menetapkan konten aturan Compose ke SelectOptionScreen
. Tindakan ini memastikan bahwa composable SelectOptionScreen
diluncurkan secara langsung sehingga navigasi tidak diperlukan. Namun, layar ini memerlukan dua parameter: daftar opsi rasa dan subtotal.
- Buat daftar opsi rasa dan subtotal untuk diteruskan ke layar.
@Test
fun selectOptionScreen_verifyContent() {
// Given list of options
val flavors = listOf("Vanilla", "Chocolate", "Hazelnut", "Cookie", "Mango")
// And subtotal
val subtotal = "$100"
}
- Setel konten ke composable
SelectOptionScreen
menggunakan nilai yang baru saja Anda buat.
Perhatikan bahwa pendekatan ini mirip dengan meluncurkan composable dari MainActivity
. Satu-satunya perbedaan adalah MainActivity
memanggil composable CupcakeApp
, dan di sini Anda memanggil composable SelectOptionScreen
. Kemampuan untuk mengubah composable yang diluncurkan dari setContent()
memungkinkan Anda meluncurkan composable tertentu, bukan meminta pengujian secara eksplisit untuk menelusuri aplikasi agar dapat sampai ke area yang ingin diuji. Pendekatan ini membantu mencegah pengujian gagal di area kode yang tidak terkait dengan pengujian Anda saat ini.
@Test
fun selectOptionScreen_verifyContent() {
// Given list of options
val flavors = listOf("Vanilla", "Chocolate", "Hazelnut", "Cookie", "Mango")
// And subtotal
val subtotal = "$100"
// When SelectOptionScreen is loaded
composeTestRule.setContent {
SelectOptionScreen(subtotal = subtotal, options = flavors)
}
}
Pada tahap pengujian ini, aplikasi akan meluncurkan composable SelectOptionScreen
dan kemudian Anda dapat berinteraksi dengannya melalui petunjuk pengujian.
- Lakukan iterasi melalui daftar
flavors
dan pastikan setiap item string dalam daftar ditampilkan di layar. - Gunakan metode
onNodeWithText()
untuk menemukan teks di layar dan gunakan metodeassertIsDisplayed()
untuk memverifikasi bahwa teks ditampilkan di aplikasi.
@Test
fun selectOptionScreen_verifyContent() {
// Given list of options
val flavors = listOf("Vanilla", "Chocolate", "Hazelnut", "Cookie", "Mango")
// And subtotal
val subtotal = "$100"
// When SelectOptionScreen is loaded
composeTestRule.setContent {
SelectOptionScreen(subtotal = subtotal, options = flavors)
}
// Then all the options are displayed on the screen.
flavors.forEach { flavor ->
composeTestRule.onNodeWithText(flavor).assertIsDisplayed()
}
}
- Dengan menggunakan teknik yang sama untuk memverifikasi bahwa aplikasi menampilkan teks, verifikasi bahwa aplikasi menampilkan string subtotal yang benar di layar. Telusuri ID resource
R.string.subtotal_price
dan nilai subtotal yang benar di layar, lalu nyatakan bahwa aplikasi menampilkan nilai.
import com.example.cupcake.R
...
@Test
fun selectOptionScreen_verifyContent() {
// Given list of options
val flavors = listOf("Vanilla", "Chocolate", "Hazelnut", "Cookie", "Mango")
// And subtotal
val subtotal = "$100"
// When SelectOptionScreen is loaded
composeTestRule.setContent {
SelectOptionScreen(subtotal = subtotal, options = flavors)
}
// Then all the options are displayed on the screen.
flavors.forEach { flavor ->
composeTestRule.onNodeWithText(flavor).assertIsDisplayed()
}
// And then the subtotal is displayed correctly.
composeTestRule.onNodeWithText(
composeTestRule.activity.getString(
R.string.subtotal_price,
subtotal
)
).assertIsDisplayed()
}
Ingat bahwa tombol Next tidak diaktifkan hingga item dipilih. Pengujian ini hanya memverifikasi konten layar, sehingga hal terakhir yang perlu diuji adalah tombol Next dinonaktifkan.
- Temukan tombol Next dengan menggunakan pendekatan yang sama untuk menemukan node berdasarkan ID resource string. Namun, gunakan metode
assertIsNotEnabled()
, bukan memverifikasi bahwa aplikasi menampilkan node.
@Test
fun selectOptionScreen_verifyContent() {
// Given list of options
val flavors = listOf("Vanilla", "Chocolate", "Hazelnut", "Cookie", "Mango")
// And subtotal
val subtotal = "$100"
// When SelectOptionScreen is loaded
composeTestRule.setContent {
SelectOptionScreen(subtotal = subtotal, options = flavors)
}
// Then all the options are displayed on the screen.
flavors.forEach { flavor ->
composeTestRule.onNodeWithText(flavor).assertIsDisplayed()
}
// And then the subtotal is displayed correctly.
composeTestRule.onNodeWithText(
composeTestRule.activity.getString(
R.string.subtotal_price,
subtotal
)
).assertIsDisplayed()
// And then the next button is disabled
composeTestRule.onNodeWithStringId(R.string.next).assertIsNotEnabled()
}
Memaksimalkan cakupan pengujian
Pengujian konten layar Choose Flavor hanya menguji satu aspek dari satu layar. Ada sejumlah pengujian tambahan yang dapat Anda tulis untuk meningkatkan cakupan kode. Coba tulis pengujian berikut sendiri sebelum mendownload kode solusi.
- Verifikasi konten layar Mulai.
- Verifikasi konten layar Ringkasan.
- Pastikan tombol Next diaktifkan saat opsi dipilih di layar Pilih Rasa.
Saat menulis pengujian, perhatikan setiap fungsi bantuan yang dapat mengurangi jumlah kode yang Anda tulis.
7. Mendapatkan kode solusi
Guna mendownload kode untuk codelab yang sudah selesai, Anda dapat menggunakan perintah git ini:
$ git clone https://github.com/google-developer-training/basic-android-kotlin-compose-training-cupcake.git
Atau, Anda dapat mendownload repositori sebagai file ZIP, lalu mengekstraknya, dan membukanya di Android Studio.
Jika Anda ingin melihat kode solusi, lihat di GitHub.
8. Ringkasan
Selamat! Anda telah mempelajari cara menguji komponen Jetpack Navigation. Anda juga telah mempelajari beberapa keterampilan dasar untuk menulis pengujian UI, seperti menulis metode bantuan yang dapat digunakan kembali, cara memanfaatkan setContent()
untuk menulis pengujian yang ringkas, cara menyiapkan pengujian dengan anotasi @Before
, dan cara mempertimbangkan nilai maksimum cakupan pengujian. Saat melanjutkan membangun aplikasi Android, jangan lupa untuk terus menulis pengujian bersama kode fitur Anda.