测试 PreferenceFragment 不适用于 Espresso 和 JUnit-Rules 或 ActivityInstrumentationTestCase2
Testing a PreferenceFragment does not work with Espresso and JUnit-Rules or ActivityInstrumentationTestCase2
我正在开发一个带有设置屏幕的应用程序,我想用浓缩咖啡对其进行测试。在此设置屏幕中,我添加了一个 PreferenceFragment,如下所示:
setContentView(R.layout.settings_activity);
...
getFragmentManager().beginTransaction().replace(R.id.content_frame, new V4SettingsFragment()).commit();
settings_activity
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<include layout="@layout/toolbar" />
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:id="@id/content_frame"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ListView
android:id="@android:id/list"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
<View
android:layout_width="match_parent"
android:layout_height="4dp"
android:id="@+id/shadow_prelollipop"
android:background="@drawable/shadow_toolbar" />
</FrameLayout>
当我以正常方式使用此设置屏幕时,它工作得很好,但是当我尝试检查和更改浓缩咖啡测试中的首选项时,会出现一些奇怪的情况。
AndroidJUnit4 测试
@Rule
public ActivityTestRule<V4SettingsActivity> settingsActivity = new ActivityTestRule<>(V4SettingsActivity.class);
@Test
public void checkFragement(){
Resources resources = settingsActivity.getActivity().getResources();
Matcher<View> adapterMatcher = allOf(isDescendantOfA(withId(R.id.content_frame)), withId(android.R.id.list));
onData(allOf(
is(instanceOf(Preference.class)),
withKey(resources.getString(R.string.prefs_category_display_preferredviewer))))
.inAdapterView(adapterMatcher);
}
这是我从 Espresso 得到的错误:
....CustomFailureHandler$NoHierarchyException: android.support.test.espresso.AmbiguousViewMatcherException: Multiple Ambiguous Views found for matcher (is descendant of a: with id: ....:id/content_frame and with id: android:id/list)
所以我进一步调查,发现我的设置页面的布局在我正常使用该应用程序时和在 Espresso 测试中使用它时看起来不同。通常在 ID 为 content_frame 的 LinearLayout 中只有一个 child(其 ID 为 android:id/list。但是当我 运行 时,Espresso 测试我看到相同的 LinearLayout 视图包含 2 childs。
当我在 Espresso 测试中 运行 以下代码时:
ViewGroup viewById = (ViewGroup) settingsActivity.getActivity().findViewById(R.id.content_frame);
for(int i=0; i<viewById.getChildCount(); i++){
ViewGroup vgChild = (ViewGroup) viewById.getChildAt(i);
Log.d(TAG, "switchDirectToHtmlReader() " + vgChild.toString()); // called two times during espresso test
}
我得到以下输出:
D: switchDirectToHtmlReader() android.widget.ListView{2854b6d9 V.ED.VC. ......ID 0,0-1080,0 #102000a android:id/list}
D: switchDirectToHtmlReader() android.widget.LinearLayout{37eb976a V.E..... ........ 0,0-1080,1677}
但是当我 运行 类似的代码不在浓缩咖啡测试中而是在 activity 中时,我得到以下输出:
D: onCreate() android.widget.ListView{149b8a90 V.ED.VC. ......I. 0,0-0,0 #102000a android:id/list}
因此,当我正常使用该应用程序时,我得到两个 child,而不是只有一个 ID 为 android:id/list 的 child 运行 浓缩咖啡测试。
我做错了什么,为什么层次结构看起来与正常使用时的层次结构如此不同?
我不太明白,但这解决了我的问题:
如果我添加以下行
ViewGroup vgParent = (ViewGroup)findViewById(R.id.content_frame);
vgParent.removeView(findViewById(android.R.id.list));
之前
getFragmentManager().beginTransaction().replace(R.id.content_frame, new V4SettingsFragment()).commit();
然后我在浓缩咖啡测试期间 R.id.content_frame 里面只有一个 child(就像我正常使用该应用程序时一样),我的浓缩咖啡测试工作正常。
我正在开发一个带有设置屏幕的应用程序,我想用浓缩咖啡对其进行测试。在此设置屏幕中,我添加了一个 PreferenceFragment,如下所示:
setContentView(R.layout.settings_activity);
...
getFragmentManager().beginTransaction().replace(R.id.content_frame, new V4SettingsFragment()).commit();
settings_activity
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<include layout="@layout/toolbar" />
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:id="@id/content_frame"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ListView
android:id="@android:id/list"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
<View
android:layout_width="match_parent"
android:layout_height="4dp"
android:id="@+id/shadow_prelollipop"
android:background="@drawable/shadow_toolbar" />
</FrameLayout>
当我以正常方式使用此设置屏幕时,它工作得很好,但是当我尝试检查和更改浓缩咖啡测试中的首选项时,会出现一些奇怪的情况。
AndroidJUnit4 测试
@Rule
public ActivityTestRule<V4SettingsActivity> settingsActivity = new ActivityTestRule<>(V4SettingsActivity.class);
@Test
public void checkFragement(){
Resources resources = settingsActivity.getActivity().getResources();
Matcher<View> adapterMatcher = allOf(isDescendantOfA(withId(R.id.content_frame)), withId(android.R.id.list));
onData(allOf(
is(instanceOf(Preference.class)),
withKey(resources.getString(R.string.prefs_category_display_preferredviewer))))
.inAdapterView(adapterMatcher);
}
这是我从 Espresso 得到的错误:
....CustomFailureHandler$NoHierarchyException: android.support.test.espresso.AmbiguousViewMatcherException: Multiple Ambiguous Views found for matcher (is descendant of a: with id: ....:id/content_frame and with id: android:id/list)
所以我进一步调查,发现我的设置页面的布局在我正常使用该应用程序时和在 Espresso 测试中使用它时看起来不同。通常在 ID 为 content_frame 的 LinearLayout 中只有一个 child(其 ID 为 android:id/list。但是当我 运行 时,Espresso 测试我看到相同的 LinearLayout 视图包含 2 childs。
当我在 Espresso 测试中 运行 以下代码时:
ViewGroup viewById = (ViewGroup) settingsActivity.getActivity().findViewById(R.id.content_frame);
for(int i=0; i<viewById.getChildCount(); i++){
ViewGroup vgChild = (ViewGroup) viewById.getChildAt(i);
Log.d(TAG, "switchDirectToHtmlReader() " + vgChild.toString()); // called two times during espresso test
}
我得到以下输出:
D: switchDirectToHtmlReader() android.widget.ListView{2854b6d9 V.ED.VC. ......ID 0,0-1080,0 #102000a android:id/list}
D: switchDirectToHtmlReader() android.widget.LinearLayout{37eb976a V.E..... ........ 0,0-1080,1677}
但是当我 运行 类似的代码不在浓缩咖啡测试中而是在 activity 中时,我得到以下输出:
D: onCreate() android.widget.ListView{149b8a90 V.ED.VC. ......I. 0,0-0,0 #102000a android:id/list}
因此,当我正常使用该应用程序时,我得到两个 child,而不是只有一个 ID 为 android:id/list 的 child 运行 浓缩咖啡测试。
我做错了什么,为什么层次结构看起来与正常使用时的层次结构如此不同?
我不太明白,但这解决了我的问题: 如果我添加以下行
ViewGroup vgParent = (ViewGroup)findViewById(R.id.content_frame);
vgParent.removeView(findViewById(android.R.id.list));
之前
getFragmentManager().beginTransaction().replace(R.id.content_frame, new V4SettingsFragment()).commit();
然后我在浓缩咖啡测试期间 R.id.content_frame 里面只有一个 child(就像我正常使用该应用程序时一样),我的浓缩咖啡测试工作正常。