Pengujian antarmuka pengguna (UI) yang melibatkan interaksi pengguna di beberapa aplikasi memungkinkan Anda memverifikasi bahwa aplikasi Anda berperilaku dengan benar saat alur pengguna melewati aplikasi lain atau UI sistem. Contoh alur pengguna tersebut adalah aplikasi pesan yang memungkinkan pengguna memasukkan pesan teks, meluncurkan pemilih kontak Android sehingga pengguna dapat memilih penerima yang akan dikirimi pesan, lalu menampilkan kontrol ke aplikasi asli yang digunakan pengguna untuk mengirim pesan.
Tutorial ini membahas cara menulis pengujian UI menggunakan framework pengujian UI Automator yang disediakan oleh AndroidX Test.
UI Automator API memungkinkan Anda berinteraksi dengan elemen yang terlihat di perangkat, terlepas dari Activity
mana yang menjadi fokus. Pengujian Anda bisa mencari komponen UI dengan menggunakan deskriptor sederhana seperti teks yang ditampilkan dalam komponen itu atau deskripsi kontennya. Pengujian UI Automator bisa dijalankan pada perangkat yang menjalankan Android 4.3 (API level 18) atau yang lebih tinggi.
Framework pengujian UI Automator adalah API berbasis instrumentasi dan berfungsi dengan runner pengujian
AndroidJUnitRunner
.
Anda juga harus membaca Referensi UI Automator API dan mencoba Contoh Kode UI Automator.
Menyiapkan UI Automator
Sebelum membuat pengujian UI dengan UI Automator, pastikan untuk mengonfigurasi lokasi kode sumber pengujian dan dependensi project Anda, seperti yang dijelaskan dalam Menyiapkan project untuk AndroidX Test.
Dalam file build.gradle
modul aplikasi Android, Anda harus menentukan referensi dependensi ke library UI Automator:
dependencies { ... androidTestImplementation 'androidx.test.uiautomator:uiautomator:2.2.0' }
Untuk mengoptimalkan pengujian UI Automator, langkah pertama yang harus Anda lakukan adalah memeriksa komponen UI aplikasi target dan memastikannya dapat diakses. Tips pengoptimalan ini dijelaskan dalam dua bagian berikutnya.
Memeriksa UI pada perangkat
Sebelum mendesain pengujian Anda, periksa komponen UI yang terlihat pada perangkat. Untuk memastikan bahwa pengujian UI Automator Anda dapat mengakses komponen ini, pastikan komponen tersebut memiliki label teks yang terlihat, nilai
android:contentDescription
, atau keduanya.
Fitur uiautomatorviewer
menyediakan antarmuka visual yang nyaman untuk memeriksa hierarki tata letak dan melihat properti komponen UI yang terlihat di latar depan perangkat.
Dengan informasi ini, Anda dapat membuat lebih banyak pengujian lebih terperinci menggunakan UI Automator. Misalnya, Anda dapat membuat pemilih UI yang cocok dengan properti terlihat tertentu.
Untuk meluncurkan fitur uiautomatorviewer
:
- Luncurkan aplikasi target di perangkat fisik.
- Hubungkan perangkat ke mesin pengembangan Anda.
- Buka jendela terminal dan buka direktori
<android-sdk>/tools/
. - Jalankan fitur tersebut dengan perintah ini:
$ uiautomatorviewer
Untuk melihat properti UI untuk aplikasi Anda:
- Dalam antarmuka
uiautomatorviewer
, klik tombol Screenshot Perangkat. - Arahkan kursor ke snapshot di panel sebelah kiri untuk melihat komponen UI yang diidentifikasi oleh fitur
uiautomatorviewer
. Properti dicantumkan di panel kanan bawah dan hierarki tata letak di panel kanan atas. - (Opsional) Klik tombol Toggle NAF Nodes untuk melihat komponen UI yang tidak dapat diakses oleh UI Automator. Hanya informasi terbatas yang tersedia untuk komponen ini.
Untuk mempelajari jenis umum komponen UI yang disediakan oleh Android, lihat Antarmuka Pengguna.
Memastikan aktivitas Anda dapat diakses
Framework pengujian UI Automator berperforma lebih baik pada aplikasi yang telah mengimplementasikan fitur aksesibilitas Android. Jika Anda menggunakan elemen UI dari jenis View
, atau subclass View
dari SDK, Anda tidak perlu mengimplementasikan dukungan aksesibilitas, karena class tersebut telah melakukannya untuk Anda.
Namun, beberapa aplikasi menggunakan elemen UI kustom untuk memberikan pengalaman pengguna yang lebih kaya. Elemen tersebut tidak akan memberikan dukungan aksesibilitas secara otomatis. Jika aplikasi Anda berisi instance subclass dari View
yang bukan dari SDK, pastikan Anda menambahkan fitur aksesibilitas ke elemen ini dengan menyelesaikan langkah-langkah berikut:
- Buat class konkret yang memperluas
ExploreByTouchHelper
. - Kaitkan instance class baru Anda dengan elemen UI kustom tertentu dengan memanggil
setAccessibilityDelegate()
.
Untuk mendapatkan panduan tambahan terkait menambahkan fitur aksesibilitas ke elemen tampilan kustom, lihat Membuat Tampilan Kustom yang Dapat Diakses. Untuk mempelajari lebih lanjut praktik terbaik yang umum untuk aksesibilitas di Android, lihat Membuat Aplikasi Lebih Mudah Diakses.
Membuat class pengujian UI Automator
Class pengujian UI Automator Anda harus ditulis dengan cara yang sama seperti class pengujian JUnit 4. Untuk mempelajari lebih lanjut cara membuat class pengujian JUnit 4 serta menggunakan pernyataan dan anotasi JUnit 4, lihat Membuat Class Pengujian Unit Berinstrumen.
Tambahkan anotasi @RunWith(AndroidJUnit4.class)
di awal definisi class pengujian Anda. Anda juga harus menentukan class
AndroidJUnitRunner
, yang disediakan di AndroidX Test, sebagai runner pengujian default Anda. Langkah ini dijelaskan secara lebih mendetail dalam Menjalankan pengujian UI Automator pada perangkat atau emulator.
Implementasikan model pemrograman berikut ke class pengujian UI Automator Anda:
- Dapatkan objek
UiDevice
untuk mengakses perangkat yang ingin Anda uji, dengan memanggil metodegetInstance()
dan meneruskan objekInstrumentation
sebagai argumen. - Dapatkan objek
UiObject
untuk mengakses komponen UI yang ditampilkan pada perangkat (misalnya, tampilan aktif di latar depan), dengan memanggil metodefindObject()
. - Simulasikan interaksi pengguna tertentu untuk dijalankan pada komponen UI tersebut, dengan memanggil metode
UiObject
. Misalnya, panggilperformMultiPointerGesture()
untuk menyimulasikan gestur multi-sentuh, dansetText()
untuk mengedit kolom teks. Bila perlu, ulangi langkah 2 dan 3 untuk memanggil API guna menguji interaksi pengguna yang lebih kompleks yang melibatkan beberapa komponen UI atau serangkaian tindakan pengguna. - Periksa apakah UI mencerminkan status atau perilaku yang diharapkan, setelah interaksi pengguna ini dilakukan.
Langkah ini dibahas lebih detail di bagian di bawah ini.
Mengakses komponen UI
Objek UiDevice
adalah cara utama Anda mengakses dan memanipulasi status perangkat. Dalam pengujian, Anda dapat memanggil metode UiDevice
untuk memeriksa status berbagai properti, seperti orientasi saat ini atau ukuran tampilan.
Pengujian dapat menggunakan objek UiDevice
untuk melakukan tindakan tingkat perangkat, seperti memaksa perangkat berpindah ke rotasi tertentu, menekan tombol fisik D-pad, dan menekan tombol Layar Utama dan Menu.
Sebaiknya mulai pengujian Anda dari Layar utama perangkat. Dari Layar utama (atau beberapa lokasi awal lain yang Anda pilih pada perangkat), Anda dapat memanggil metode yang disediakan oleh UI Automator API untuk memilih dan berinteraksi dengan elemen UI tertentu.
Cuplikan kode berikut menunjukkan cara pengujian Anda bisa mendapatkan instance UiDevice
dan menyimulasikan penekanan tombol Layar Utama:
Kotlin
import org.junit.Before import androidx.test.runner.AndroidJUnit4 import androidx.test.uiautomator.UiDevice import androidx.test.uiautomator.By import androidx.test.uiautomator.Until ... private const val BASIC_SAMPLE_PACKAGE = "com.example.android.testing.uiautomator.BasicSample" private const val LAUNCH_TIMEOUT = 5000L private const val STRING_TO_BE_TYPED = "UiAutomator" @RunWith(AndroidJUnit4::class) @SdkSuppress(minSdkVersion = 18) class ChangeTextBehaviorTest2 { private lateinit var device: UiDevice @Before fun startMainActivityFromHomeScreen() { // Initialize UiDevice instance device = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation()) // Start from the home screen device.pressHome() // Wait for launcher val launcherPackage: String = device.launcherPackageName assertThat(launcherPackage, notNullValue()) device.wait( Until.hasObject(By.pkg(launcherPackage).depth(0)), LAUNCH_TIMEOUT ) // Launch the app val context = ApplicationProvider.getApplicationContext<Context>() val intent = context.packageManager.getLaunchIntentForPackage( BASIC_SAMPLE_PACKAGE).apply { // Clear out any previous instances addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK) } context.startActivity(intent) // Wait for the app to appear device.wait( Until.hasObject(By.pkg(BASIC_SAMPLE_PACKAGE).depth(0)), LAUNCH_TIMEOUT ) } }
Java
import org.junit.Before; import androidx.test.runner.AndroidJUnit4; import androidx.test.uiautomator.UiDevice; import androidx.test.uiautomator.By; import androidx.test.uiautomator.Until; ... @RunWith(AndroidJUnit4.class) @SdkSuppress(minSdkVersion = 18) public class ChangeTextBehaviorTest { private static final String BASIC_SAMPLE_PACKAGE = "com.example.android.testing.uiautomator.BasicSample"; private static final int LAUNCH_TIMEOUT = 5000; private static final String STRING_TO_BE_TYPED = "UiAutomator"; private UiDevice device; @Before public void startMainActivityFromHomeScreen() { // Initialize UiDevice instance device = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation()); // Start from the home screen device.pressHome(); // Wait for launcher final String launcherPackage = device.getLauncherPackageName(); assertThat(launcherPackage, notNullValue()); device.wait(Until.hasObject(By.pkg(launcherPackage).depth(0)), LAUNCH_TIMEOUT); // Launch the app Context context = ApplicationProvider.getApplicationContext(); final Intent intent = context.getPackageManager() .getLaunchIntentForPackage(BASIC_SAMPLE_PACKAGE); // Clear out any previous instances intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK); context.startActivity(intent); // Wait for the app to appear device.wait(Until.hasObject(By.pkg(BASIC_SAMPLE_PACKAGE).depth(0)), LAUNCH_TIMEOUT); } }
Dalam contoh, pernyataan @SdkSuppress(minSdkVersion = 18)
membantu memastikan bahwa pengujian hanya berjalan di perangkat yang menggunakan Android 4.3 (API level 18) atau yang lebih tinggi, seperti yang diwajibkan oleh framework UI Automator.
Gunakan metode findObject()
untuk mengambil UiObject
yang merepresentasikan tampilan yang cocok dengan kriteria pemilih yang diberikan. Anda dapat menggunakan kembali instance UiObject
yang telah Anda buat di bagian lain pengujian aplikasi, sesuai kebutuhan. Perhatikan bahwa framework pengujian UI Automator menelusuri tampilan saat ini untuk pencocokan setiap kali pengujian Anda menggunakan instance UiObject
untuk mengklik elemen UI atau membuat kueri properti.
Cuplikan berikut menunjukkan cara pengujian dapat membuat instance UiObject
yang merepresentasikan tombol Batal dan tombol OK di aplikasi.
Kotlin
val cancelButton: UiObject = device.findObject( UiSelector().text("Cancel").className("android.widget.Button") ) val okButton: UiObject = device.findObject( UiSelector().text("OK").className("android.widget.Button") ) // Simulate a user-click on the OK button, if found. if (okButton.exists() && okButton.isEnabled) { okButton.click() }
Java
UiObject cancelButton = device.findObject(new UiSelector() .text("Cancel") .className("android.widget.Button")); UiObject okButton = device.findObject(new UiSelector() .text("OK") .className("android.widget.Button")); // Simulate a user-click on the OK button, if found. if(okButton.exists() && okButton.isEnabled()) { okButton.click(); }
Menentukan pemilih
Jika Anda ingin mengakses komponen UI tertentu dalam aplikasi, gunakan class UiSelector
. Class ini merepresentasikan kueri untuk elemen tertentu di UI yang saat ini ditampilkan.
Jika elemen pencocokan yang ditemukan lebih dari satu, elemen pencocokan pertama dalam hierarki tata letak ditampilkan sebagai target UiObject
.
Saat membuat UiSelector
, Anda dapat mengaitkan beberapa properti untuk mempersempit penelusuran. Jika tidak ditemukan elemen UI yang cocok,
UiAutomatorObjectNotFoundException
akan dimunculkan.
Anda dapat menggunakan metode
childSelector()
untuk menyarangkan beberapa instance UiSelector
. Misalnya, contoh kode berikut menunjukkan cara pengujian Anda dapat menentukan penelusuran untuk menemukan ListView
pertama dalam UI yang saat ini ditampilkan, lalu menelusuri di dalam ListView
untuk menemukan elemen UI dengan Aplikasi properti teks.
Kotlin
val appItem: UiObject = device.findObject( UiSelector().className("android.widget.ListView") .instance(0) .childSelector( UiSelector().text("Apps") ) )
Java
UiObject appItem = device.findObject(new UiSelector() .className("android.widget.ListView") .instance(0) .childSelector(new UiSelector() .text("Apps")));
Sebagai praktik terbaik, saat menentukan pemilih, sebaiknya gunakan ID Resource (jika ada yang ditetapkan untuk elemen UI), bukan elemen teks atau deskriptor konten. Tidak semua elemen memiliki atribut teks (misalnya, ikon di toolbar). Pemilih teks bersifat rapuh dan dapat menyebabkan kegagalan pengujian jika terdapat perubahan kecil pada UI. Pemilih teks juga mungkin tidak mendukung bahasa-bahasa lain. Pemilih teks Anda mungkin tidak mencocokkan string yang diterjemahkan.
Hal tersebut mungkin berguna untuk menentukan status objek dalam kriteria pemilih Anda. Misalnya, jika Anda ingin memilih daftar semua elemen yang dicentang sehingga Anda dapat menghapus centangnya, panggil metode
checked()
dengan argumen yang ditetapkan ke true
.
Melakukan tindakan
Setelah pengujian Anda mendapatkan objek UiObject
, Anda dapat memanggil metode dalam class UiObject
untuk menjalankan interaksi pengguna pada komponen UI yang direpresentasikan oleh objek tersebut. Anda dapat menentukan tindakan seperti:
-
click()
: Mengklik di tengah bagian yang terlihat dari elemen UI. -
dragTo()
: Menarik objek ini ke koordinat arbitrer. -
setText()
: Menyetel teks dalam kolom yang dapat diedit, setelah menghapus konten kolom. Sebaliknya, metodeclearTextField()
menghapus teks yang ada di kolom yang dapat diedit. -
swipeUp()
: Melakukan tindakan geser ke atas padaUiObject
. Begitu juga, metodeswipeDown()
,swipeLeft()
, danswipeRight()
akan melakukan tindakan yang sesuai.
Framework pengujian UI Automator mengizinkan Anda mengirimkan Intent
atau meluncurkan Activity
tanpa menggunakan perintah shell, dengan mendapatkan objek Context
melalui getContext()
.
Cuplikan berikut menunjukkan menggunakan Intent
dalam pengujian Anda untuk meluncurkan aplikasi yang sedang diuji. Pendekatan ini berguna saat Anda hanya tertarik untuk menguji aplikasi kalkulator, dan tidak memerlukan peluncur.
Kotlin
fun setUp() { ... // Launch a simple calculator app val context = getInstrumentation().context val intent = context.packageManager.getLaunchIntentForPackage(CALC_PACKAGE).apply { addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK) } // Clear out any previous instances context.startActivity(intent) device.wait(Until.hasObject(By.pkg(CALC_PACKAGE).depth(0)), TIMEOUT) }
Java
public void setUp() { ... // Launch a simple calculator app Context context = getInstrumentation().getContext(); Intent intent = context.getPackageManager() .getLaunchIntentForPackage(CALC_PACKAGE); intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK); // Clear out any previous instances context.startActivity(intent); device.wait(Until.hasObject(By.pkg(CALC_PACKAGE).depth(0)), TIMEOUT); }
Menjalankan tindakan pada koleksi
Gunakan class
UiCollection
jika Anda ingin menyimulasikan interaksi pengguna pada koleksi item (misalnya, lagu dalam album musik atau daftar email di Kotak Masuk). Untuk membuat objek
UiCollection
, tentukan UiSelector
yang menelusuri penampung UI atau wrapper elemen UI turunan lainnya, seperti tampilan tata letak yang berisi elemen UI turunan.
Cuplikan kode berikut menunjukkan bagaimana pengujian Anda dapat membuat
UiCollection
untuk merepresentasikan album video yang ditampilkan dalam FrameLayout
:
Kotlin
val videos = UiCollection(UiSelector().className("android.widget.FrameLayout")) // Retrieve the number of videos in this collection: val count = videos.getChildCount( UiSelector().className("android.widget.LinearLayout") ) // Find a specific video and simulate a user-click on it val video: UiObject = videos.getChildByText( UiSelector().className("android.widget.LinearLayout"), "Cute Baby Laughing" ) video.click() // Simulate selecting a checkbox that is associated with the video val checkBox: UiObject = video.getChild( UiSelector().className("android.widget.Checkbox") ) if (!checkBox.isSelected) checkBox.click()
Java
UiCollection videos = new UiCollection(new UiSelector() .className("android.widget.FrameLayout")); // Retrieve the number of videos in this collection: int count = videos.getChildCount(new UiSelector() .className("android.widget.LinearLayout")); // Find a specific video and simulate a user-click on it UiObject video = videos.getChildByText(new UiSelector() .className("android.widget.LinearLayout"), "Cute Baby Laughing"); video.click(); // Simulate selecting a checkbox that is associated with the video UiObject checkBox = video.getChild(new UiSelector() .className("android.widget.Checkbox")); if(!checkBox.isSelected()) checkbox.click();
Menjalankan tindakan pada tampilan yang dapat di-scroll
Gunakan class
UiScrollable
untuk menyimulasikan scroll vertikal atau horizontal di seluruh tampilan. Teknik ini berguna bila elemen UI ditempatkan di belakang layar dan Anda perlu men-scroll untuk menampilkannya.
Cuplikan kode berikut menunjukkan cara menyimulasikan scroll ke bawah menu Setelan dan mengklik opsi Tentang tablet:
Kotlin
val settingsItem = UiScrollable(UiSelector().className("android.widget.ListView")) val about: UiObject = settingsItem.getChildByText( UiSelector().className("android.widget.LinearLayout"), "About tablet" ) about.click()
Java
UiScrollable settingsItem = new UiScrollable(new UiSelector() .className("android.widget.ListView")); UiObject about = settingsItem.getChildByText(new UiSelector() .className("android.widget.LinearLayout"), "About tablet"); about.click();
Memverifikasi hasil
InstrumentationTestCase
memperluas TestCase
, sehingga Anda dapat menggunakan metode Assert
JUnit standar untuk menguji komponen UI dalam aplikasi yang menampilkan hasil yang diharapkan.
Cuplikan berikut menunjukkan cara pengujian Anda dapat menemukan beberapa tombol di aplikasi kalkulator, mengklik tombol tersebut secara berurutan, lalu memverifikasi bahwa hasil yang benar ditampilkan.
Kotlin
private const val CALC_PACKAGE = "com.myexample.calc" fun testTwoPlusThreeEqualsFive() { // Enter an equation: 2 + 3 = ? device.findObject(UiSelector().packageName(CALC_PACKAGE).resourceId("two")).click() device.findObject(UiSelector().packageName(CALC_PACKAGE).resourceId("plus")).click() device.findObject(UiSelector().packageName(CALC_PACKAGE).resourceId("three")).click() device.findObject(UiSelector().packageName(CALC_PACKAGE).resourceId("equals")).click() // Verify the result = 5 val result: UiObject2 = device.findObject(By.res(CALC_PACKAGE, "result")) assertEquals("5", result.text) }
Java
private static final String CALC_PACKAGE = "com.myexample.calc"; public void testTwoPlusThreeEqualsFive() { // Enter an equation: 2 + 3 = ? device.findObject(new UiSelector() .packageName(CALC_PACKAGE).resourceId("two")).click(); device.findObject(new UiSelector() .packageName(CALC_PACKAGE).resourceId("plus")).click(); device.findObject(new UiSelector() .packageName(CALC_PACKAGE).resourceId("three")).click(); device.findObject(new UiSelector() .packageName(CALC_PACKAGE).resourceId("equals")).click(); // Verify the result = 5 UiObject result = device.findObject(By.res(CALC_PACKAGE, "result")); assertEquals("5", result.getText()); }
Menjalankan pengujian UI Automator pada perangkat atau emulator
Anda dapat menjalankan pengujian UI Automator dari Android Studio atau dari command line. Pastikan untuk menentukan
AndroidJUnitRunner
sebagai runner instrumentasi default dalam project Anda.
Referensi lainnya
Untuk mengetahui informasi selengkapnya tentang penggunaan UI Automator dalam pengujian Android, lihat referensi berikut.
Contoh
- BasicSample: Contoh dasar UI Automator.