Ketika mendesain strategi pengujian untuk elemen atau sistem, ada tiga aspek pengujian yang terkait:
- Cakupan: Berapa banyak kode yang disentuh pengujian? Pengujian dapat memverifikasi satu metode, seluruh aplikasi, atau di antaranya. Cakupan yang diuji adalah sedang diuji dan biasanya menyebutnya sebagai Subjek Dalam Pengujian, meskipun juga sebagai Sistem Dalam Pengujian atau Unit Dalam Pengujian.
- Kecepatan: Seberapa cepat pengujian berjalan? Kecepatan pengujian dapat bervariasi dari milidetik hingga beberapa menit.
- Fidelitas: Seberapa "dunia nyata" dalam pengujiannya? Misalnya, jika bagian dari kode yang Anda uji perlu membuat permintaan jaringan, apakah kode pengujian benar-benar membuat permintaan jaringan ini, atau apakah hasilnya memalsukan hasilnya? Jika pengujian benar-benar terhubung dengan jaringan, berarti pengujian memiliki fidelitas yang lebih tinggi. Konsekuensinya, pengujian dapat memerlukan waktu lebih lama untuk dijalankan, dapat mengakibatkan error jika jaringan tidak aktif, atau dapat menjadi mahal untuk digunakan.
Lihat hal yang harus diuji untuk mempelajari cara mulai menentukan strategi pengujian.
Isolasi dan dependensi
Saat menguji elemen atau sistem elemen, Anda melakukannya secara terpisah. Misalnya, untuk menguji ViewModel, Anda tidak perlu memulai emulator dan meluncurkan UI karena tidak (atau tidak seharusnya) bergantung pada framework Android.
Namun, subjek yang diuji mungkin bergantung pada subjek lain agar berfungsi. Misalnya, ViewModel mungkin bergantung pada repositori data agar dapat berfungsi.
Jika Anda perlu memberikan dependensi ke subjek yang sedang diuji, praktik yang umum adalah membuat pengujian ganda (atau objek pengujian). Ganda pengujian adalah objek yang terlihat dan berfungsi sebagai komponen dalam aplikasi Anda, tetapi dibuat dalam pengujian untuk memberikan perilaku atau data tertentu. Keuntungan utamanya adalah membuat pengujian Anda lebih cepat dan sederhana.
Jenis pengujian ganda
Ada berbagai jenis pengujian ganda:
Palsu | Pengujian ganda yang memiliki implementasi class yang "berfungsi", tetapi diterapkan sedemikian rupa sehingga cocok untuk pengujian, tetapi tidak cocok untuk produksi.
Contoh: database dalam memori. Produk palsu tidak memerlukan framework tiruan dan ringan. Fungsi tersebut lebih disarankan. |
---|---|
Tiruan | Pengujian ganda yang berperilaku bagaimana Anda memprogram perilakunya dan yang memiliki ekspektasi tentang interaksinya. Tiruan akan gagal dalam pengujian jika interaksinya tidak cocok dengan persyaratan yang Anda tentukan. Tiruan biasanya dibuat dengan framework tiruan untuk mencapai semua ini.
Contoh: Memverifikasi bahwa metode dalam database dipanggil hanya sekali. |
Konfirmasi | Pengujian ganda yang berperilaku bagaimana Anda memprogram perilakunya, tetapi tidak memiliki ekspektasi terkait interaksinya. Biasanya dibuat dengan framework tiruan. Yang palsu lebih disukai daripada stub agar lebih praktis. |
Dummy | Pengujian ganda yang diteruskan tetapi tidak digunakan, seperti jika Anda hanya perlu menyediakannya sebagai parameter.
Contoh: fungsi kosong yang diteruskan sebagai callback klik. |
Mata-mata | Wrapper di atas objek sungguhan yang juga melacak beberapa informasi tambahan, mirip dengan tiruan. Mereka biasanya dihindari karena menambah kerumitan. Karena itu, palsu atau tiruan lebih disukai daripada mata-mata. |
Bayangan | Palsu digunakan di Robolectric. |
Contoh penggunaan palsu
Misalkan Anda ingin menguji unit ViewModel yang bergantung pada antarmuka
yang disebut UserRepository
dan mengekspos nama pengguna pertama ke UI. Anda dapat
membuat pengujian ganda palsu dengan mengimplementasikan antarmuka dan menampilkan data
yang diketahui.
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 sumber data lokal dan jarak jauh
yang akan digunakan oleh versi produksi. File ini berada dalam set sumber
pengujian dan tidak akan dikirimkan dengan aplikasi produksi.
![Dependensi palsu dapat mengembalikan data yang diketahui tanpa bergantung pada sumber data jarak jauh](https://developer.android.google.cn/static/training/testing/fundamentals/fake-deps.png?authuser=19&hl=id)
Pengujian berikut memverifikasi bahwa ViewModel mengekspos nama pengguna pertama ke tampilan dengan benar.
@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, mengganti elemen arbitrer dalam pengujian yang lebih besar mungkin akan sulit.
Mengganti komponen dan injeksi dependensi
Jika pengujian tidak memiliki kontrol atas pembuatan sistem yang sedang diuji, penggantian komponen untuk duplikat pengujian akan lebih rumit dan memerlukan arsitektur aplikasi untuk mengikuti desain yang dapat diuji.
Bahkan pengujian end-to-end yang besar pun dapat memperoleh manfaat dari penggunaan pengujian ganda, seperti pengujian UI berinstrumen yang menavigasi seluruh alur pengguna di aplikasi Anda. Dalam hal ini, Anda mungkin ingin membuat pengujian menjadi hermetis. Pengujian hermetic menghindari semua dependensi eksternal, seperti mengambil data dari internet. Hal ini meningkatkan keandalan dan performa.
![](https://developer.android.google.cn/static/training/testing/fundamentals/bigtest.png?authuser=19&hl=id)
Anda dapat mendesain aplikasi untuk mencapai fleksibilitas ini secara manual, tetapi sebaiknya gunakan framework injeksi dependensi seperti Hilt untuk mengganti komponen dalam aplikasi Anda pada waktu pengujian. Lihat Panduan pengujian Hilt.
Robolectric
Di Android, Anda dapat menggunakan framework Robolectric, yang menyediakan jenis pengujian ganda khusus. Dengan Robolectric, Anda dapat menjalankan pengujian di workstation atau di lingkungan continuous integration Anda. Metode ini menggunakan JVM biasa, tanpa emulator atau perangkat. Fitur ini menyimulasikan perluasan tampilan, pemuatan resource, dan bagian lain dari framework Android dengan duplikat pengujian yang disebut shadows.
Robolectric adalah simulator sehingga tidak boleh menggantikan pengujian unit sederhana atau digunakan untuk melakukan pengujian kompatibilitas. Hal ini memberikan kecepatan dan mengurangi biaya dengan mengorbankan fidelitas yang lebih rendah dalam beberapa kasus. Pendekatan yang baik untuk pengujian UI adalah membuatnya kompatibel dengan pengujian Robolectric dan uji instrumentasi, serta memutuskan kapan akan menjalankannya, bergantung pada kebutuhan untuk menguji fungsionalitas atau kompatibilitas. Pengujian Espresso dan Compose dapat berjalan di Robolectric.