如何在 Android 或 Android Espresso 中获取视图层次结构
How do you get view hierarchy in Android or Android Espresso
我正在使用 Android Espresso,当它找不到匹配项时,它会在打印视图层次结构时抛出异常。当您在 运行 Android 测试或 Espresso
时,有没有办法动态地获取这种视图层次结构
View Hierarchy:
+>DecorView{id=-1, visibility=VISIBLE, width=480, height=800, has-focus=true, has-focusable=true, has-window-focus=true, is-clickable=false, is-enabled=true, is-focused=false, is-focusable=false, is-layout-requested=false, is-selected=false, root-is-layout-requested=false, has-input-connection=false, x=0.0, y=0.0, child-count=2}
|
+->LinearLayout{id=-1, visibility=VISIBLE, width=480, height=800, has-focus=true, has-focusable=true, has-window-focus=true, is-clickable=false, is-enabled=true, is-focused=false, is-focusable=false, is-layout-requested=false, is-selected=false, root-is-layout-requested=false, has-input-connection=false, x=0.0, y=0.0, child-count=2}
|
+-->ViewStub{id=16909225, res-name=action_mode_bar_stub, visibility=GONE, width=0, height=0, 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=true, is-selected=false, root-is-layout-requested=false, has-input-connection=false, x=0.0, y=0.0}
|
+-->FrameLayout{id=-1, visibility=VISIBLE, width=480, height=764, has-focus=true, has-focusable=true, has-window-focus=true, is-clickable=false, is-enabled=true, is-focused=false, is-focusable=false, is-layout-requested=false, is-selected=false, root-is-layout-requested=false, has-input-connection=false, x=0.0, y=36.0, child-count=1}
|
+--->ActionBarOverlayLayout{id=2131427395, res-name=decor_content_parent, visibility=VISIBLE, width=480, height=764, has-focus=true, has-focusable=true, has-window-focus=true, is-clickable=false, is-enabled=true, is-focused=false, is-focusable=false, is-layout-requested=false, is-selected=false, root-is-layout-requested=false, has-input-connection=false, x=0.0, y=0.0, child-count=2}
|
鉴于 Android View hierarchy
是树结构,使用某种算法更容易遍历每个树节点,您可以在 https://developer.android.com/reference/android/support/test/espresso/util/TreeIterables.html[=15 查看这些方法=]
它打印出异常跟踪的方式使用了一种名为 breadthFirstViewTraversal
的方法,并在 class ViewFinderImpl
中打印出视图树
https://developer.android.com/reference/android/support/test/espresso/base/ViewFinderImpl.html
您可以引发异常并显示视图层次结构。例如把这个放在你的测试文件中:
onView(withText("XYZ")).perform(click())
并且由于文本 XYZ 不存在,结果将是:
...espresso.NoMatchingViewException: No views in hierarchy found matching: with text: is "XYZ"
View Hierarchy:
+>DecorView{id=-1, visibility=VISIBLE, width=1024, height=600, has-focus=true, has-focusable=true, has-window-focus=true, is-clickable=false, is-enabled=true, is-focused=false, is-focusable=false, is-layout-requested=false, is-selected=false, root-is-layout-requested=false, has-input-connection=false, x=0.0, y=0.0, child-count=1}
|
+->LinearLayout{id=-1, visibility=VISIBLE, width=1024, height=600, has-focus=true, has-focusable=true, has-window-focus=true, is-clickable=false, is-enabled=true, is-focused=false, is-focusable=false, is-layout-requested=false, is-selected=false, root-is-layout-requested=false, has-input-connection=false, x=0.0, y=0.0, child-count=2}
|
...
HumanReadables.getViewHierarchyErrorMessage
是 Espresso 在视图匹配器失败时用来打印图形的方式,因此与其抛出一个虚假匹配并捕获它,不如:
\ import androidx.test.espresso.util.HumanReadables
val theRootView = fragment.view
val viewHierarchy: String = HumanReadables.getViewHierarchyErrorMessage(theRootView, null, "", null)
您需要一个来传递一个视图。例如,如果您正在使用一个片段,fragment.view
将是图表的根。
我正在使用 Android Espresso,当它找不到匹配项时,它会在打印视图层次结构时抛出异常。当您在 运行 Android 测试或 Espresso
时,有没有办法动态地获取这种视图层次结构View Hierarchy:
+>DecorView{id=-1, visibility=VISIBLE, width=480, height=800, has-focus=true, has-focusable=true, has-window-focus=true, is-clickable=false, is-enabled=true, is-focused=false, is-focusable=false, is-layout-requested=false, is-selected=false, root-is-layout-requested=false, has-input-connection=false, x=0.0, y=0.0, child-count=2}
|
+->LinearLayout{id=-1, visibility=VISIBLE, width=480, height=800, has-focus=true, has-focusable=true, has-window-focus=true, is-clickable=false, is-enabled=true, is-focused=false, is-focusable=false, is-layout-requested=false, is-selected=false, root-is-layout-requested=false, has-input-connection=false, x=0.0, y=0.0, child-count=2}
|
+-->ViewStub{id=16909225, res-name=action_mode_bar_stub, visibility=GONE, width=0, height=0, 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=true, is-selected=false, root-is-layout-requested=false, has-input-connection=false, x=0.0, y=0.0}
|
+-->FrameLayout{id=-1, visibility=VISIBLE, width=480, height=764, has-focus=true, has-focusable=true, has-window-focus=true, is-clickable=false, is-enabled=true, is-focused=false, is-focusable=false, is-layout-requested=false, is-selected=false, root-is-layout-requested=false, has-input-connection=false, x=0.0, y=36.0, child-count=1}
|
+--->ActionBarOverlayLayout{id=2131427395, res-name=decor_content_parent, visibility=VISIBLE, width=480, height=764, has-focus=true, has-focusable=true, has-window-focus=true, is-clickable=false, is-enabled=true, is-focused=false, is-focusable=false, is-layout-requested=false, is-selected=false, root-is-layout-requested=false, has-input-connection=false, x=0.0, y=0.0, child-count=2}
|
鉴于 Android View hierarchy
是树结构,使用某种算法更容易遍历每个树节点,您可以在 https://developer.android.com/reference/android/support/test/espresso/util/TreeIterables.html[=15 查看这些方法=]
它打印出异常跟踪的方式使用了一种名为 breadthFirstViewTraversal
的方法,并在 class ViewFinderImpl
中打印出视图树
https://developer.android.com/reference/android/support/test/espresso/base/ViewFinderImpl.html
您可以引发异常并显示视图层次结构。例如把这个放在你的测试文件中:
onView(withText("XYZ")).perform(click())
并且由于文本 XYZ 不存在,结果将是:
...espresso.NoMatchingViewException: No views in hierarchy found matching: with text: is "XYZ"
View Hierarchy:
+>DecorView{id=-1, visibility=VISIBLE, width=1024, height=600, has-focus=true, has-focusable=true, has-window-focus=true, is-clickable=false, is-enabled=true, is-focused=false, is-focusable=false, is-layout-requested=false, is-selected=false, root-is-layout-requested=false, has-input-connection=false, x=0.0, y=0.0, child-count=1}
|
+->LinearLayout{id=-1, visibility=VISIBLE, width=1024, height=600, has-focus=true, has-focusable=true, has-window-focus=true, is-clickable=false, is-enabled=true, is-focused=false, is-focusable=false, is-layout-requested=false, is-selected=false, root-is-layout-requested=false, has-input-connection=false, x=0.0, y=0.0, child-count=2}
|
...
HumanReadables.getViewHierarchyErrorMessage
是 Espresso 在视图匹配器失败时用来打印图形的方式,因此与其抛出一个虚假匹配并捕获它,不如:
\ import androidx.test.espresso.util.HumanReadables
val theRootView = fragment.view
val viewHierarchy: String = HumanReadables.getViewHierarchyErrorMessage(theRootView, null, "", null)
您需要一个来传递一个视图。例如,如果您正在使用一个片段,fragment.view
将是图表的根。