Periksa apakah dialog ditampilkan dengan Espresso

87

Saya mencoba menulis beberapa pengujian dengan android-test-kit (Espresso) baru . Tetapi saya tidak dapat menemukan informasi apa pun tentang cara memeriksa apakah sebuah dialog ditampilkan dan melakukan beberapa tindakan di dalamnya (seperti mengklik tombol positif dan negatif, dll). Perhatikan bahwa dialog juga dapat ditampilkan oleh a WebView, bukan oleh aplikasi itu sendiri.

Bantuan apa pun akan dihargai. Saya hanya butuh tautan, atau beberapa kode contoh untuk dasar-dasarnya:

  1. Periksa apakah dialog muncul
  2. Lakukan klik pada tombol dialog
  3. Berinteraksi dengan tampilan dalam dialog (jika itu tampilan kustom)
  4. Preform klik di luar dialog, dan periksa apakah itu ditampilkan atau tidak (misalnya jika setCancelable(false)dipanggil pada pembuat dialog dan kami ingin memeriksanya)

Terima kasih atas sarannya!

Serj Lotutovici
sumber
Ada tanggapan atas jawaban saya di bawah ini ??
menolak

Jawaban:

125
  1. Untuk memverifikasi apakah dialog muncul, Anda cukup memeriksa apakah Tampilan dengan teks yang ada di dalam dialog ditampilkan:

    onView(withText("dialogText")).check(matches(isDisplayed()));
    

    atau, berdasarkan teks dengan id

    onView(withId(R.id.myDialogTextId)).check(matches(allOf(withText(myDialogText), isDisplayed()));
    
  2. Untuk mengklik tombol dialog lakukan ini (tombol1 - OK, tombol2 - Batal):

    onView(withId(android.R.id.button1)).perform(click());
    

    MEMPERBARUI

  3. Saya rasa itu mungkin karena Espresso memiliki dukungan multi jendela .
  4. Tidak yakin tentang mengklik di luar tampilan dialog kustom tetapi untuk memeriksa apakah itu ditampilkan atau tidak Anda harus membuat pencocokan kustom Anda dan memeriksa di dalamnya.
Denys
sumber
3
Langkah 1 tidak berhasil untuk saya di ProgressDialog. Hanya mencoba memvalidasi Judul dan Pesan dialog
Tim Boland
1
Ada apa dengan espresso dan impor statis? Dari kelas mana metode tersebut berasal? Mengapa Anda menggunakan impor statis pada jawaban stack overflow?
2
@jvrodrigues setiap tutorial Espresso menggunakan impor statis. Saya sarankan Anda membiasakan diri (meskipun saya mengerti rasa frustrasinya). Ini membantu: google.github.io/android-testing-support-library/docs
AutonomousApps
Untuk langkah 4 alih-alih mengklik di luar dialog, Anda dapat memanggil "pressBack ();" yang menutup dialog. itu setara dengan menggunakan tombol kembali perangkat keras.
Ethan
Proyek @denys telah dipindahkan. sepertinya tautannya sudah mati.
Neon Warge
67

Saat ini saya menggunakan ini dan sepertinya berfungsi dengan baik.

onView(withText(R.string.my_title))
    .inRoot(isDialog()) // <---
    .check(matches(isDisplayed()));
Kiruwka
sumber
28

Jika Anda memiliki AlertDialog seperti itu:

masukkan deskripsi gambar di sini

Anda dapat memeriksa apakah komponen ditampilkan:

int titleId = mActivityTestRule.getActivity().getResources()
        .getIdentifier( "alertTitle", "id", "android" );

onView(withId(titleId))
        .inRoot(isDialog())
        .check(matches(withText(R.string.my_title)))
        .check(matches(isDisplayed()));

onView(withId(android.R.id.text1))
        .inRoot(isDialog())
        .check(matches(withText(R.string.my_message)))
        .check(matches(isDisplayed()));

onView(withId(android.R.id.button2))
        .inRoot(isDialog())
        .check(matches(withText(android.R.string.no)))
        .check(matches(isDisplayed()));

onView(withId(android.R.id.button3))
        .inRoot(isDialog())
        .check(matches(withText(android.R.string.yes)))
        .check(matches(isDisplayed()));

dan melakukan tindakan:

onView(withId(android.R.id.button3)).perform(click());
Luiz Augusto
sumber
2
Teks dalam kasus saya memiliki id android.R.id.messagedan judul memiliki id tersembunyi android.R.id.alertTitle.
Jason Robinson
2
Jika Anda menggunakan AlertDialog (atau DialogFragment) yang berasal dari pustaka dukungan AppCompat, gunakan ini:int alertDialogTitleId = android.support.v7.appcompat.R.id.alertTitle;
Mr-IDE
Jika ada yang perlu mengetahui nilai parameter, stackoverflow.com/a/15488321/1713366 . Jika Anda tidak tahu nama atau tipe def, coba check()tampilan yang tidak ada dan lihat hierarki tata letak di logcat. Anda akan melihat banyak dari ini defType = name. Misalnya, message=hello worldparameter Anda akan terlihat seperti"hello world", "message", "your package name"
Jcorretjer
3

Untuk menjawab pertanyaan 4, yang jawaban yang diterima tidak, saya memodifikasi kode berikut, yang saya temukan di sini di Stack Overflow ( tautan ) untuk menguji apakah Toast ditampilkan.

@NonNull
public static ViewInteraction getRootView(@NonNull Activity activity, @IdRes int id) {
    return onView(withId(id)).inRoot(withDecorView(not(is(activity.getWindow().getDecorView()))));
}

Yang idditeruskan adalah id dari yang Viewsedang ditampilkan dalam dialog Anda. Anda juga bisa menulis metode seperti ini:

@NonNull
public static ViewInteraction getRootView(@NonNull Activity activity, @NonNull String text) {
    return onView(withText(text)).inRoot(withDecorView(not(is(activity.getWindow().getDecorView()))));
}

Dan sekarang sedang mencari yang Viewmengandung string teks tertentu.

Gunakan seperti ini:

getRootView(getActivity(), R.id.text_id).perform(click());
AutonomousApps
sumber
3

Tombol Id R.id.button1 dan R.id.button2 tidak akan sama di semua perangkat. Id dapat berubah dengan versi OS.

Cara yang benar untuk mencapai ini adalah dengan menggunakan UIAutomator. Sertakan dependensi UIAutomator di build.gradle Anda

// Set this dependency to build and run UI Automator tests
  androidTestCompile 'com.android.support.test.uiautomator:uiautomator-v18:2.1.2'

dan gunakan

// Initialize UiDevice instance
UiDevice uiDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation());

// Search for correct button in the dialog.
UiObject button = uiDevice.findObject(new UiSelector().text("ButtonText"));
if (button.exists() && button.isEnabled()) {
    button.click();
}
JaydeepW
sumber
1
Sebenarnya, android.R.id.button1, android.R.id.button2dan android.R.id.button3untuk "positif", "netral" dan "negatif", adalah simbol global yang dapat digunakan. Jika Anda memilih untuk memilih tombol melalui teksnya - yang sama sekali tidak masalah - Anda tidak memerlukan UIAutomator, tetapi dapat melakukan hal yang sama dengan Espresso onView(withText("ButtonTest")).perform(click()).
Thomas Keller
Saya menggunakan solusi ini dengan kerangka kerja uji Robotium dan saya dapat memilih tombol kotak dialog OS Android dengan mudah. Menyelamatkan saya banyak waktu. Terima kasih jaydeepw!
Ray
@ThomasKeller Saya telah menggunakan tombol1, id tombol2 di masa lalu, pengujian saya rusak ketika saya menjalankannya di berbagai perangkat. Dialog yang ditampilkan adalah kontrol sistem. Bukan kontrol / UI Anda. Untuk apa pun di luar UI Anda, UIAutomator disarankan.
JaydeepW
Itu dia. Terima kasih banyak.
lb3r
3

Untuk berjaga-jaga jika ada yang tersandung pada pertanyaan ini seperti yang saya lakukan. Semua jawaban hanya akan berfungsi untuk dialog DENGAN tombol dialog. Jangan mencoba dan menggunakan ini untuk dialog kemajuan tanpa interaksi pengguna. Espresso terus menunggu aplikasi memasuki keadaan diam. Selama dialog kemajuan terlihat, aplikasi tidak menganggur.

Diana Farin
sumber