App or screen¶
Examples are in Python
Kotlin has the same calls (app.wait → app.await). Kotlin + JUnit 5
shows this page's examples in Kotlin.
Attaching a device names no app: one test can drive several apps (device.app("a"),
device.app("b")) and the system UI on the same device. Every lookup searches all the windows
on screen, and what you call element / wait on decides which of their nodes count:
device.app(pkg).element(sel)/.wait(sel): only nodes that belong topkg. The package is one more predicate in the selector the device receives, so a dialog, a keyboard or a notification of another package can never be what a test of your app matches, whether or not it is focused.device.screen.element(sel)/.wait(sel): nodes of any package: system dialogs, the status bar's panels, the launcher. Use it when you do not know, or do not care, which package owns what you are after.
shop = device.app("com.shop")
shop.element(res("search")).set_text("socks") # com.shop's search field only
device.screen.wait(text("Allow")).visible() # whoever owns it
In Python and Kotlin, binding a selector that already has an exact top-level package
predicate for the same app (such as a snapshot selector) keeps it unchanged, including its
first() or at() choice. A package predicate for another app, a nonexact match, or ownership
only inside an OR branch or a relation does not replace the app's package restriction.
A permission dialog belongs to the permission controller, for instance:
device.app("com.google.android.permissioncontroller").element(
res_id("com.android.permissioncontroller", "permission_allow_button")
).tap()
For tests that just need the permission, prefer app.grant_permission(...), which needs no
dialog at all, or the permission dialog helpers when the dialog is under test.
Covered elements¶
Another window, such as a keyboard, a popup or another app's overlay, can hide a node you match:
- Covered completely, the node is not found: Android reports it as not visible, so an action
fails with
NOT_FOUNDandvisible()keeps waiting. - Covered partly, it is found, but a gesture whose touch point (a tap's centre, a swipe's
start) is under the other window fails with
NOT_INTERACTABLE/OBSCUREDbefore any input, instead of landing on whatever is on top.
Close the covering window (often device.press_back() or device.hide_keyboard()) or scroll
the node clear first.