ไม่ขอเกริ่นอะไรมาก เริ่มเลยละกัน
พอดีตอนนี้ผมหัดทำ เน้นอีกครั้งว่า หัดทำ 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 ได้แล้วครับ…น้ำตาจะไหล