Menguji Komponen Navigasi

1. Sebelum memulai

Pada codelab sebelumnya, Anda telah mempelajari navigasi menggunakan Komponen Navigasi. Dalam codelab ini, Anda akan mempelajari cara menguji Komponen Navigasi. Perhatikan bahwa cara ini berbeda dengan cara menguji navigasi tanpa menggunakan komponen navigasi.

Prasyarat

  • Anda telah membuat direktori pengujian di Android Studio.
  • Anda telah menulis pengujian unit dan instrumentasi di Android Studio.
  • Anda telah menambahkan dependensi Gradle ke project Android.

Yang akan Anda pelajari

  • Cara menggunakan uji instrumentasi untuk menguji komponen navigasi.
  • Cara menyiapkan pengujian tanpa kode berulang.

Yang Anda perlukan

  • Komputer yang dilengkapi Android Studio.
  • Kode solusi untuk aplikasi Words.

Mendownload kode awal untuk codelab ini

Dalam codelab ini, Anda akan menambahkan uji instrumentasi ke kode solusi untuk aplikasi Words.

  1. Buka halaman repositori GitHub yang disediakan untuk project.
  2. Pastikan nama cabang cocok dengan nama cabang yang ditentukan dalam codelab. Misalnya, dalam screenshot berikut, nama cabang adalah main (utama).

1e4c0d2c081a8fd2.png

  1. Di halaman GitHub project, klik tombol Code yang akan menampilkan pop-up.

1debcf330fd04c7b.png

  1. Pada pop-up, klik tombol Download ZIP untuk menyimpan project di komputer. Tunggu download selesai.
  2. Temukan file di komputer Anda (mungkin di folder Downloads).
  3. Klik dua kali pada file ZIP untuk mengekstraknya. Tindakan ini akan membuat folder baru yang berisi file project.

Membuka project di Android Studio

  1. Mulai Android Studio.
  2. Di jendela Welcome to Android Studio, klik Open.

d8e9dbdeafe9038a.png

Catatan: Jika Android Studio sudah terbuka, pilih opsi menu File > Open.

8d1fda7396afe8e5.png

  1. Di file browser, buka lokasi folder project yang telah diekstrak (kemungkinan ada di folder Downloads).
  2. Klik dua kali pada folder project tersebut.
  3. Tunggu Android Studio membuka project.
  4. Klik tombol Run 8de56cba7583251f.png untuk membangun dan menjalankan aplikasi. Pastikan aplikasi dibangun seperti yang diharapkan.

2. Ringkasan aplikasi awal

Aplikasi Words terdiri dari layar utama yang menampilkan daftar, dengan setiap item daftar berupa huruf alfabet. Mengklik huruf akan membuka layar yang menampilkan daftar kata yang dimulai dengan huruf tersebut.

3. Membuat direktori pengujian

Jika perlu, buat direktori uji instrumentasi untuk aplikasi Words seperti yang telah Anda lakukan di codelab sebelumnya. Jika sudah melakukannya, Anda dapat langsung menambahkan dependensi yang diperlukan.

4. Membuat Class uji instrumentasi

Buat class baru yang bernama NavigationTests.kt di folder androidTest.

b023023a2ccc3813.png

5. Menambahkan dependensi yang diperlukan

Pengujian komponen navigasi memerlukan beberapa dependensi Gradle tertentu. Kita juga akan menyertakan dependensi yang memungkinkan pengujian fragmen dengan cara yang sangat spesifik. Buka file build.gradle modul aplikasi Anda, lalu tambahkan dependensi berikut:

androidTestImplementation 'androidx.test.ext:junit:1.1.3'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
androidTestImplementation 'com.android.support.test.espresso:espresso-contrib:3.4.0'
androidTestImplementation 'androidx.navigation:navigation-testing:2.5.2'

debugImplementation 'androidx.fragment:fragment-testing:1.5.3'

Sekarang sinkronkan project Anda.

6. Menulis Pengujian Komponen Navigasi

Menguji Komponen Navigasi berbeda dengan menguji navigasi reguler. Saat menguji navigasi reguler, kita memicu navigasi untuk dijalankan di perangkat atau emulator. Saat menguji Komponen Navigasi, kita tidak benar-benar membuat perangkat atau emulator melakukan navigasi secara jelas. Sebagai gantinya, kita memaksa pengontrol navigasi untuk melakukan navigasi tanpa benar-benar mengubah komponen yang terlihat di perangkat atau emulator, lalu memeriksanya untuk memastikan pengontrol navigasi sampai di tujuan yang benar.

  1. Buat fungsi pengujian bernama navigate_to_words_nav_component().
  2. Pengujian menggunakan Komponen Navigasi memerlukan beberapa penyiapan. Pada metode navigate_to_words_nav_component(), buat instance pengujian dari pengontrol navigasi.
val navController = TestNavHostController(
   ApplicationProvider.getApplicationContext()
)
  1. Komponen Navigasi menjalankan UI menggunakan Fragment. Ada fragmen yang setara dengan ActivityScenarioRule yang dapat digunakan untuk mengisolasi fragmen pengujian, dan inilah alasan diperlukannya dependensi khusus fragmen. Fungsi ini dapat sangat berguna untuk menguji fragmen yang harus menjangkau banyak navigasi karena fragmen dapat diluncurkan tanpa kode tambahan untuk menangani navigasi ke fragmen tersebut.
val letterListScenario = launchFragmentInContainer<LetterListFragment>(themeResId =
R.style.Theme_Words)

Di sini kita menentukan bahwa kita ingin meluncurkan LetterListFragment. Kita harus meneruskan tema aplikasi agar komponen UI mengetahui tema yang akan digunakan atau pengujian dapat mengalami error.

  1. Terakhir, kita harus secara eksplisit mendeklarasikan grafik navigasi mana yang ingin digunakan oleh pengontrol navigasi untuk fragmen yang diluncurkan.
letterListScenario.onFragment { fragment ->

   navController.setGraph(R.navigation.nav_graph)

   Navigation.setViewNavController(fragment.requireView(), navController)
}
  1. Sekarang picu peristiwa yang meminta navigasi.
onView(withId(R.id.recycler_view))
   .perform(RecyclerViewActions
       .actionOnItemAtPosition<RecyclerView.ViewHolder>(2, click()))

Saat menggunakan metode launchFragmentInContainer(), navigasi yang sebenarnya tidak mungkin dilakukan karena penampung tidak mengetahui fragmen atau aktivitas lain yang mungkin dijelajahi. Penampung hanya mengetahui fragmen yang telah ditentukan untuk diluncurkan di dalamnya. Oleh karena itu, saat menjalankan pengujian ini pada perangkat atau emulator, Anda tidak akan melihat navigasi yang sebenarnya. Hal ini mungkin tampak tidak intuitif, tetapi memungkinkan kita membuat lebih banyak pernyataan langsung mengenai tujuan saat ini. Daripada mencari komponen UI yang sudah pasti ditampilkan pada layar tertentu, kita dapat memeriksa apakah tujuan pengontrol navigasi saat ini memiliki ID fragmen yang diharapkan ada di dalamnya. Pendekatan ini secara signifikan lebih andal daripada pendekatan yang disebutkan di atas.

assertEquals(navController.currentDestination?.id, R.id.wordListFragment)

Pengujian Anda akan terlihat seperti ini: 78b4a72f75134ded.png

7. Kode solusi

8. Menghindari pengulangan kode dengan anotasi

Di Android, uji instrumentasi dan pengujian unit memiliki fitur yang memungkinkan kita menyiapkan konfigurasi yang sama untuk setiap pengujian di class tanpa mengulangi kode.

Misalnya, kita memiliki fragmen dengan 10 tombol. Setiap tombol akan mengarah ke fragmen yang unik saat diklik.

Jika mengikuti pola dalam pengujian di atas, kita harus mengulang kode seperti ini untuk setiap 10 pengujian (perhatikan bahwa kode ini hanya contoh dan tidak akan dikompilasi dalam aplikasi yang digunakan dalam codelab ini):

val navController = TestNavHostController(
    ApplicationProvider.getApplicationContext()
)

val exampleFragmentScenario = launchFragmentInContainer<ExampleFragment>(themeResId =
R.style.Theme_Example)

exampleFragmentScenario.onFragment { fragment ->

   navController.setGraph(R.navigation.example_nav_graph)

   Navigation.setViewNavController(fragment.requireView(), navController)
}

Begitu banyak kode untuk diulang 10 kali. Namun, dalam kasus ini, kita dapat menghemat waktu dengan menggunakan anotasi @Before yang disediakan oleh JUnit. Kita menggunakannya dengan memberi anotasi pada metode yang memungkinkan kita menyediakan kode yang diperlukan untuk menyiapkan pengujian. Kita bisa memberi nama metode sesuai keinginan, tetapi harus relevan. Daripada menyiapkan fragmen yang sama sebanyak 10 kali, kita dapat menulis kode penyiapan satu kali seperti ini:

lateinit var navController: TestNavHostController

lateinit var exampleFragmentScenario: FragmentScenario<ExampleFragment>

@Before
fun setup(){
    navController = TestNavHostController(
        ApplicationProvider.getApplicationContext()
    )

    exampleFragmentScenario =  launchFragmentInContainer(themeResId=R.style.Theme_Example)

    exampleFragmentScenario.onFragment { fragment ->

       navController.setGraph(R.navigation.example_nav_graph)

       Navigation.setViewNavController(fragment.requireView(),  navController)
    }
}

Sekarang metode ini berjalan untuk setiap pengujian yang kita tulis di class ini, dan kita dapat mengakses variabel yang diperlukan dari salah satu pengujian.

Demikian pula, jika ada kode yang harus dieksekusi setelah setiap pengujian, kita dapat menggunakan anotasi @After. Misalnya, @After dapat digunakan untuk membersihkan resource yang digunakan untuk pengujian, atau jika untuk uji instrumentasi, kita dapat menggunakannya untuk mengembalikan perangkat ke status tertentu.

JUnit juga menyediakan anotasi @BeforeClass dan @AfterClass. Perbedaannya di sini adalah metode dengan anotasi ini dieksekusi satu kali, tetapi kode yang dieksekusi masih berlaku untuk setiap metode. Jika metode penyiapan atau penguraian memuat operasi yang mahal, mungkin sebaiknya gunakan anotasi ini. Metode yang dianotasi dengan @BeforeClass dan @AfterClass harus ditempatkan di objek pendamping dan dianotasi dengan @JvmStatic. Untuk menunjukkan urutan eksekusi anotasi ini, mari kita lihat kode berikut:

5157ab00a9b7fb84.png

Ingat, @BeforeClass berjalan untuk class, @Before berjalan sebelum fungsi, @After berjalan setelah fungsi, dan @AfterClass berjalan untuk class. Dapatkah Anda memprediksi tampilan output ini?

39c04aa2ba7b8348.png

Urutan eksekusi fungsinya adalah setupClass(), setupFunction(), test_a(), tearDownFunction(), setupFunction(), test_b(), tearDownFunction(), setupFunction(), test_c(), tearDownFunction(), tearDownClass(). Urutan ini masuk akal karena @Before dan @After masing-masing berjalan sebelum dan setelah setiap metode. @BeforeClass berjalan satu kali sebelum elemen yang ada di class berjalan dan @AfterClass berjalan satu kali setelah semua elemen di class berjalan.

9. Selamat

Dalam codelab ini, Anda telah:

  • Mempelajari cara menguji Komponen Navigasi.
  • Mempelajari cara menghindari kode berulang dengan anotasi @Before, @BeforeClass, @After, dan @AfterClass.