Menggunakan dummy pengujian di Android

Saat merancang strategi pengujian untuk elemen atau sistem, ada tiga aspek pengujian terkait:

  • Cakupan: Seberapa banyak kode yang disentuh pengujian? Pengujian dapat memverifikasi satu seluruh aplikasi, atau di antara keduanya. Tujuan cakupan yang diuji sedang diuji dan biasanya menyebutnya sebagai Subjek Dalam Uji, melalui juga Sistem Dalam Pengujian atau Unit Dalam Pengujian.
  • Kecepatan: Seberapa cepat pengujian berjalan? Kecepatan pengujian dapat bervariasi mulai dari milidetik hingga beberapa menit.
  • Fidelitas: Bagaimana "dunia nyata" apakah tesnya? Misalnya, jika sebagian kode Anda perlu membuat permintaan jaringan, apakah kode pengujian benar-benar membuat permintaan jaringan ini, atau memalsukan hasilnya? Jika pengujian benar-benar berbicara dengan jaringan, ini berarti ia memiliki fidelitas yang lebih tinggi. Konsekuensinya, pengujian dapat memakan waktu lebih lama untuk dijalankan, dapat mengakibatkan kesalahan jika jaringan mati, atau mungkin mahal untuk digunakan.

Lihat apa yang harus diuji untuk mempelajari cara mulai menetapkan strategi pengujian.

Isolasi dan dependensi

Saat menguji elemen atau sistem elemen, Anda melakukannya secara isolasi. Sebagai misalnya, untuk menguji ViewModel, Anda tidak perlu memulai emulator dan meluncurkan UI karena tidak (atau tidak seharusnya) bergantung pada framework Android.

Namun, subjek yang sedang diuji mungkin bergantung pada orang lain agar dapat berfungsi. Sebagai di instance tertentu, ViewModel mungkin bergantung pada repositori data agar berfungsi.

Saat Anda perlu menyediakan dependensi pada subjek yang diuji, adalah membuat test double (atau objek pengujian). Pengujian ganda adalah objek yang terlihat dan bertindak sebagai komponen dalam aplikasi Anda, tetapi mereka dibuat dalam pengujian Anda untuk menyediakan perilaku atau data tertentu. Keuntungan utamanya adalah bahwa mereka memberikan pengujian lebih cepat dan mudah.

Jenis pengujian ganda

Ada berbagai jenis pengujian ganda:

Palsu Pengujian ganda yang memiliki status "berfungsi" class lama, tetapi diterapkan sedemikian rupa sehingga cocok untuk pengujian, tetapi tidak cocok untuk produksi.

Contoh: database dalam memori.

Produk palsu tidak memerlukan framework tiruan dan bersifat ringan. Keduanya lebih disukai.

Tiruan Pengujian ganda yang berperilaku bagaimana Anda memprogram perilakunya dan yang memiliki ekspektasi tentang interaksinya. Simulasi akan gagal dalam pengujian jika interaksinya tidak sesuai dengan persyaratan yang Anda tentukan. Simulasi biasanya dibuat dengan framework tiruan untuk mencapai semua ini.

Contoh: Memverifikasi bahwa metode dalam database dipanggil tepat satu kali.

Konfirmasi Pengujian ganda yang berperilaku bagaimana Anda memprogram perilakunya, tetapi tidak memiliki harapan tentang interaksinya. Biasanya dibuat dengan framework tiruan. Yang palsu lebih disukai daripada stub agar lebih mudah.
Dummy Pengujian ganda yang diteruskan tetapi tidak digunakan, misalnya jika Anda hanya perlu menyediakannya sebagai parameter.

Contoh: fungsi kosong yang diteruskan sebagai callback klik.

Mata-mata Wrapper pada objek nyata yang juga melacak beberapa informasi tambahan, mirip dengan tiruan. Mereka biasanya dihindari untuk menambah kerumitan. Oleh karena itu, rekayasa palsu lebih disukai daripada mata-mata.
Bayangan Palsu digunakan dalam Robolectric.

Contoh penggunaan kode palsu

Misalkan Anda ingin menguji unit ViewModel yang bergantung pada antarmuka yang disebut UserRepository dan menampilkan nama pengguna pertama ke UI. Anda dapat membuat pengujian palsu ganda dengan mengimplementasikan antarmuka dan menampilkan layanan otomatis dan data skalabel.

object FakeUserRepository : UserRepository {
    fun getUsers() = listOf(UserAlice, UserBob)
}

val const UserAlice = User("Alice")
val const UserBob = User("Bob")

UserRepository palsu ini tidak perlu bergantung pada data lokal dan jarak jauh sumber yang akan digunakan dalam versi produksi. File berada di sumber pengujian telah disetel dan tidak akan dikirimkan bersama aplikasi produksi.

Dependensi palsu dapat menampilkan data yang diketahui tanpa bergantung pada sumber data jarak jauh
Gambar 1: Dependensi palsu dalam pengujian unit.

Pengujian berikut memverifikasi bahwa ViewModel mengekspos pengguna pertama dengan benar nama ke tampilan.

@Test
fun viewModelA_loadsUsers_showsFirstUser() {
    // Given a VM using fake data
    val viewModel = ViewModelA(FakeUserRepository) // Kicks off data load on init

    // Verify that the exposed data is correct
    assertEquals(viewModel.firstUserName, UserAlice.name)
}

Mengganti UserRepository dengan yang palsu mudah dilakukan dalam pengujian unit, karena ViewModel dibuat oleh penguji. Namun demikian, bisa saja sulit untuk mengganti elemen arbitrer dalam pengujian yang lebih besar.

Mengganti komponen dan injeksi dependensi

Ketika pengujian tidak memiliki kendali atas pembuatan sistem yang sedang diuji, penggantian komponen untuk duplikasi pengujian menjadi lebih rumit dan membutuhkan aplikasi Anda untuk mengikuti desain yang dapat diuji.

Bahkan pengujian besar yang menyeluruh bisa mendapatkan manfaat dari penggunaan ganda pengujian, seperti pengujian UI berinstrumen yang menavigasi seluruh alur pengguna di aplikasi Anda. Di beberapa Jika demikian, sebaiknya buat pengujian menjadi hermetik. Pengujian kedap udara menghindari semua dependensi eksternal, seperti mengambil data dari internet. Ini meningkatkan keandalan dan performa.

Gambar 2: Pengujian besar yang mencakup sebagian besar aplikasi dan memalsukan data jarak jauh.

Anda dapat mendesain aplikasi untuk mencapai fleksibilitas ini secara manual, tetapi sebaiknya menggunakan framework injeksi dependensi seperti Hilt untuk menggantikan komponen di aplikasi Anda pada waktu pengujian. Lihat Panduan pengujian Hilt.

Robolectric

Di Android, Anda dapat menggunakan framework Robolectric, yang menyediakan jenis pengujian ganda khusus. Robolectric memungkinkan Anda menjalankan pengujian pada workstation, atau di lingkungan continuous integration Anda. Proses ini menggunakan JVM reguler, tanpa emulator atau perangkat. Model ini menyimulasikan inflation of view, pemuatan resource, dan bagian lain dari framework Android dengan pengujian ganda disebut shadows.

Robolectric adalah simulator sehingga tidak boleh menggantikan pengujian unit sederhana atau digunakan untuk melakukan pengujian kompatibilitas. Cara ini memberikan kecepatan dan mengurangi biaya dengan fidelitas rendah dalam beberapa kasus. Pendekatan yang baik untuk pengujian UI adalah dengan membuatnya kompatibel dengan uji Robolectric dan uji instrumentasi serta memutuskan kapan harus menjalankannya mereka tergantung pada kebutuhan untuk menguji fungsionalitas atau kompatibilitas. Kedua Espresso dan pengujian Compose dapat berjalan di Robolectric.