[Android] ทำ UI Testing ด้วย Espresso แล้วเจอ AlertDialog ที่ Title กับ PositiveButton มีข้อความเหมือนกันทำไงดี ?

ไม่ขอเกริ่นอะไรมาก เริ่มเลยละกัน

พอดีตอนนี้ผมหัดทำ เน้นอีกครั้งว่า หัดทำ Automate Testing บน Android อยู่ครับ

เรื่อง Unit Testing ขอข้ามไปก่อน มาทำ UI Testing เลย (ในที่นี้ใช้ Espresso ในการทดสอบนะครับ)

ทำไป ๆ ก็มาเจอปัญหาว่า Title ของ AlertDialog กับ ปุ่ม PositiveButton (หรือจะเป็นปุ่ม NegativeButton ก็ได้) มันดันเป็นข้อความเดียวกัน ตามรูปข้างบน (ตามหลัก UX แล้ว ปุ่มมันควรเป็นการกระทำ ไม่ใช่ “ตกลง” นะครับ)

จะอ้างอิงจาก ID เหมือน view อื่นก็ไม่ได้

จากการเสิร์ช ได้โค้ดมาประมาณนี้

onView(withText(R.string.logout))
                .inRoot(RootMatchers.isDialog())
                .check(matches(isDisplayed()))
                .perform(click());

ต่างจากการหา View ปกติตรงที่เพิ่ม

.inRoot(RootMatchers.isDialog()) 

กับ

.check(matches(isDisplayed())) 

เข้าไป แต่ก็ยังเจอ Error ว่า…

androidx.test.espresso.AmbiguousViewMatcherException: 'with string from resource id: <2131689606>[logout] value: ออกจากระบบ' matches multiple views in the hierarchy.
Problem views are marked with '****MATCHES****' below.

View Hierarchy:
+-------->DialogTitle{id=2131230775, res-name=alertTitle, visibility=VISIBLE, width=814, height=71, has-focus=false, has-focusable=false, has-window-focus=true, is-clickable=false, is-enabled=true, is-focused=false, is-focusable=false, is-layout-requested=false, is-selected=false, layout-params=android.widget.LinearLayout$LayoutParams@99bb5a5, tag=null, root-is-layout-requested=false, has-input-connection=false, x=63.0, y=47.0, text=ออกจากระบบ, input-type=0, ime-target=false, has-links=false} ****MATCHES****
|
+-------->AppCompatButton{id=16908313, res-name=button1, visibility=VISIBLE, width=276, height=126, has-focus=false, has-focusable=true, has-window-focus=true, is-clickable=true, is-enabled=true, is-focused=false, is-focusable=true, is-layout-requested=false, is-selected=false, layout-params=android.widget.LinearLayout$LayoutParams@47c9cb8, tag=null, root-is-layout-requested=false, has-input-connection=false, x=632.0, y=11.0, text=ออกจากระบบ, input-type=0, ime-target=false, has-links=false} ****MATCHES****

สังเกตเห็นอะไรมั้ยครับ ตรงที่เป็น Title

is-clickable=false

แต่ตรงที่เป็นปุ่ม

is-clickable=true

ดังนั้นเราต้องเพิ่มเงื่อนไขอะไรเข้าไปหน่อย ด้วยคำสั่ง allOf (คือต้องตรงตามเงื่อนไขในนี้ทุกอย่าง) ตามนี้ครับ

onView(allOf(withText(R.string.logout),isClickable()))
                .inRoot(RootMatchers.isDialog())
                .check(matches(isDisplayed()))
                .perform(click());

แค่นี้ก็ Test ได้แล้วครับ…น้ำตาจะไหล

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.