Resource nonaktif mewakili operasi asinkron yang hasilnya memengaruhi operasi selanjutnya dalam pengujian UI. Dengan mendaftarkan resource nonaktif bersama Espresso, Anda dapat memvalidasi operasi asinkron tersebut dengan lebih andal saat menguji aplikasi Anda.
Mengidentifikasi kapan resource nonaktif diperlukan
Espresso memberikan serangkaian kemampuan sinkronisasi yang canggih. Namun, karakteristik framework ini hanya berlaku untuk operasi yang memposting pesan di MessageQueue
, seperti subclass View
yang menggambar kontennya di layar.
Karena tidak mengetahui operasi asinkron lainnya, termasuk yang berjalan di thread latar belakang, Espresso tidak dapat memberikan sinkronisasinya jaminan dalam situasi tersebut. Agar membuat Espresso mengetahui operasi aplikasi yang sudah lama berjalan, Anda harus mendaftarkan masing-masing operasi tersebut sebagai resource nonaktif.
Jika tidak menggunakan resource nonaktif saat menguji hasil pekerjaan asinkron aplikasi, Anda mungkin harus menggunakan salah satu dari solusi tidak baik berikut untuk meningkatkan keandalan pengujian Anda:
- Menambahkan panggilan ke
Thread.sleep()
. Saat menambahkan penundaan buatan ke pengujian, rangkaian pengujian akan membutuhkan waktu lebih lama untuk menyelesaikan eksekusi, dan pengujian mungkin gagal saat dijalankan pada perangkat yang lebih lambat. Selain itu, penundaan tersebut tidak menskala dengan baik, karena aplikasi Anda mungkin harus menjalankan pekerjaan asinkron yang lebih memakan waktu di rilis mendatang. - Mengimplementasikan retry wrapper, yang menggunakan loop untuk memeriksa berulang kali apakah aplikasi Anda masih menjalankan pekerjaan asinkron hingga waktu tunggu habis. Meskipun Anda menentukan jumlah coba ulang maksimum dalam pengujian, setiap eksekusi ulang akan menggunakan resource sistem, terutama CPU.
- Menggunakan instance
CountDownLatch
, yang memungkinkan satu atau beberapa thread menunggu hingga sejumlah operasi tertentu yang dijalankan di thread lainnya selesai. Objek-objek ini mengharuskan Anda untuk menentukan durasi waktu tunggu; jika tidak, aplikasi Anda mungkin akan diblokir tanpa batas. Latch tersebut juga menambah kompleksitas yang tidak diperlukan pada kode Anda, sehingga pemeliharaan akan menjadi lebih sulit.
Dengan Espresso, Anda dapat meninggalkan solusi yang tidak bisa diandalkan dari pengujian Anda dan mendaftarkan pekerjaan asinkron aplikasi sebagai resource nonaktif.
Kasus penggunaan umum
Saat menjalankan operasi yang mirip dengan contoh berikut dalam pengujian, pertimbangkan untuk menggunakan resource nonaktif:
- Memuat data dari internet atau sumber data lokal.
- Membuat koneksi dengan database dan callback.
- Mengelola layanan, baik menggunakan layanan sistem atau instance
IntentService
. - Menjalankan logika bisnis yang kompleks, seperti transformasi bitmap.
Sangat penting untuk mendaftarkan resource nonaktif saat operasi tersebut mengupdate UI yang kemudian akan divalidasi oleh pengujian Anda.
Contoh implementasi resource nonaktif
Daftar berikut menjelaskan beberapa contoh implementasi resource nonaktif yang dapat Anda integrasikan ke dalam aplikasi:
CountingIdlingResource
- Mempertahankan penghitung tugas aktif. Saat penghitung menunjukkan nol, resource yang terkait akan dianggap nonaktif. Fungsionalitas ini sangat mirip dengan
Semaphore
. Umumnya, implementasi ini cukup untuk mengelola pekerjaan asinkron aplikasi Anda selama pengujian. UriIdlingResource
- Mirip dengan
CountingIdlingResource
, tetapi penghitung harus nol selama periode waktu tertentu sebelum resource dianggap nonaktif. Periode tunggu tambahan ini mempertimbangkan permintaan jaringan berturut-turut, saat aplikasi di thread mungkin membuat permintaan baru segera setelah menerima respons terhadap permintaan sebelumnya. IdlingThreadPoolExecutor
- Implementasi kustom
ThreadPoolExecutor
yang melacak jumlah total tugas yang berjalan dalam kumpulan thread yang dibuat. Class ini menggunakanCountingIdlingResource
untuk mempertahankan penghitung tugas aktif. IdlingScheduledThreadPoolExecutor
- Implementasi kustom
ScheduledThreadPoolExecutor
. Dengannya, Anda mendapatkan fungsionalitas dan kemampuan yang sama dengan classIdlingThreadPoolExecutor
, tetapi juga dapat melacak tugas yang dijadwalkan untuk masa mendatang atau dijadwalkan untuk dijalankan secara berkala.
Membuat resource nonaktif sendiri
Saat menggunakan resource nonaktif dalam pengujian aplikasi, Anda mungkin perlu menyediakan pengelolaan atau logging resource kustom. Dalam hal ini, implementasi yang tercantum di bagian sebelumnya mungkin tidak akan cukup. Jika demikian, Anda dapat memperluas salah satu dari implementasi resource nonaktif ini atau membuatnya sendiri.
Jika mengimplementasikan fungsionalitas resource nonaktif Anda sendiri, ikuti beberapa praktik terbaik berikut ini, terutama yang pertama:
- Panggil transisi ke status nonaktif di luar pemeriksaan nonaktif.
- Setelah aplikasi Anda tidak melakukan aktivitas, panggil
onTransitionToIdle()
di luar setiap implementasiisIdleNow()
. Dengan begitu, Espresso tidak melakukan pemeriksaan kedua yang tidak diperlukan untuk menentukan apakah resource nonaktif yang diberikan tidak melakukan aktivitas.
Cuplikan kode berikut mengilustrasikan rekomendasi ini:
Kotlin
fun isIdle() { // DON'T call callback.onTransitionToIdle() here! } fun backgroundWorkDone() { // Background work finished. callback.onTransitionToIdle() // Good. Tells Espresso that the app is idle. // Don't do any post-processing work beyond this point. Espresso now // considers your app to be idle and moves on to the next test action. }
Java
public void isIdle() { // DON'T call callback.onTransitionToIdle() here! } public void backgroundWorkDone() { // Background work finished. callback.onTransitionToIdle() // Good. Tells Espresso that the app is idle. // Don't do any post-processing work beyond this point. Espresso now // considers your app to be idle and moves on to the next test action. }
- Daftarkan resource nonaktif sebelum memerlukannya.
Manfaat sinkronisasi yang terkait dengan resource nonaktif hanya berlaku setelah pemanggilan pertama Espresso terhadap metode
isIdleNow()
resource tersebut.Daftar berikut menunjukkan beberapa contoh properti ini:
- Jika Anda mendaftarkan resource nonaktif dalam metode yang dianotasikan dengan
@Before
, resource nonaktif akan berlaku di baris pertama setiap pengujian. - Jika Anda mendaftarkan dalam suatu pengujian, resource nonaktif akan berlaku hingga tindakan berbasis Espresso berikutnya. Perilaku ini masih terjadi meskipun tindakan selanjutnya berada di dalam pengujian yang sama dengan pernyataan yang mendaftarkan resource nonaktif tersebut.
- Jika Anda mendaftarkan resource nonaktif dalam metode yang dianotasikan dengan
- Batalkan pendaftaran resource nonaktif setelah selesai menggunakannya.
Untuk menghemat resource sistem, Anda harus membatalkan registrasi resource nonaktif segera setelah tidak memerlukannya lagi. Misalnya, jika Anda mendaftarkan resource nonaktif dalam metode yang dianotasikan dengan
@Before
, sebaiknya batalkan pendaftaran resource ini dalam metode terkait yang dianotasikan dengan@After
.- Gunakan registry nonaktif untuk mendaftarkan dan membatalkan pendaftaran resource nonaktif.
Dengan menggunakan container ini untuk resource nonaktif aplikasi, Anda dapat mendaftarkan dan membatalkan pendaftaran resource nonaktif berulang kali sesuai kebutuhan dan masih melihat perilaku yang konsisten.
- Pertahankan hanya status aplikasi sederhana dalam resource nonaktif.
Misalnya, resource nonaktif yang Anda terapkan dan daftarkan tidak boleh berisi referensi ke objek
View
.
Mendaftarkan resource nonaktif
Espresso menyediakan class container tempat Anda dapat menempatkan resource nonaktif aplikasi. Class ini, yang disebut IdlingRegistry
, adalah artefak mandiri yang memperkenalkan overhead minimal ke aplikasi Anda. Class tersebut juga memungkinkan Anda untuk mengambil langkah-langkah berikut guna meningkatkan pemeliharaan aplikasi Anda:
- Membuat referensi ke
IdlingRegistry
, bukan resource nonaktif yang dimuatnya, di pengujian aplikasi Anda. - Mempertahankan perbedaan dalam kumpulan resource nonaktif yang Anda gunakan untuk setiap varian build.
- Menetapkan resource nonaktif di layanan aplikasi Anda, bukan di komponen UI yang merujuk layanan tersebut.
Mengintegrasikan resource nonaktif ke dalam aplikasi
Meskipun bisa untuk menambahkan resource nonaktif ke aplikasi dengan beberapa cara yang berbeda, satu pendekatan secara khusus dapat mempertahankan enkapsulasi untuk aplikasi Anda sambil tetap memungkinkan Anda untuk menentukan operasi tertentu yang diwakili oleh resource nonaktif yang diberikan.
Pendekatan yang direkomendasikan
Saat menambahkan resource nonaktif ke dalam aplikasi, kami sangat merekomendasikan untuk melakukan hanya operasi pendaftaran dan membatalkan pendaftaran dalam pengujian, serta menempatkan logika resource nonaktif itu sendiri di dalam kode produksi aplikasi Anda.
Meskipun membuat situasi yang tidak biasa menggunakan antarmuka khusus pengujian di kode produksi dengan mengikuti pendekatan ini, Anda dapat menggabungkan resource nonaktif di sekitar kode yang sudah dimiliki, mempertahankan ukuran APK, dan jumlah metode aplikasi.
Pendekatan alternatif
Jika lebih memilih untuk tidak memiliki logika resource nonaktif dalam kode produksi aplikasi, ada beberapa strategi integrasi yang patut Anda coba:
- Buat varian build, seperti varian produk Gradle, dan gunakan resource nonaktif hanya dalam build debug aplikasi Anda.
- Gunakan framework injeksi dependensi seperti Dagger untuk memasukkan grafik dependensi resource nonaktif aplikasi ke dalam pengujian Anda. Jika Anda menggunakan Dagger 2, injeksi tersebut harus berasal dari sub-komponen.
Implementasikan resource nonaktif dalam pengujian aplikasi, dan tampilkan bagian dari implementasi aplikasi yang perlu disinkronkan dalam pengujian tersebut.
Perhatian: Meskipun terlihat seperti membuat referensi mandiri untuk resource nonaktif, keputusan desain ini juga memecah enkapsulasi di semua aplikasi kecuali di aplikasi yang paling sederhana.
Referensi lainnya
Untuk informasi selengkapnya tentang menggunakan Espresso dalam pengujian Android, lihat referensi berikut.
Contoh
- IdlingResourceSample: Sinkronisasi dengan tugas latar belakang.