我試圖測試我的SettingsActivity
類,但我不斷收到AmbiguousViewMatcherException
。濃咖啡:多個ListViews
這裏是我的測試用例:
@Test
public void whenHospitalSettingEmpty_shouldDisplaySummary() throws Exception {
Resources res = getInstrumentation().getTargetContext().getResources();
mPreferenceEditor.putString(
res.getString(R.string.activity_settings_hospital_key),
"");
mActivityTestRule.launchActivity(null);
String expected = res.getString(R.string.activity_settings_hospital_summary);
onData(allOf(
is(instanceOf(Preference.class)),
withKey(res.getString(R.string.activity_settings_hospital_key)),
withSummary(R.string.activity_settings_hospital_summary),
withTitle(R.string.activity_settings_hospital_title)))
.onChildView(withText(expected))
.check(matches(isDisplayed()));
}
這裏的日誌輸出:
android.support.test.espresso.AmbiguousViewMatcherException: 'is assignable from class: class android.widget.AdapterView' matches multiple views in the hierarchy.
Problem views are marked with '****MATCHES****' below.
View Hierarchy:
...
+------->LinearLayout{id=16909142, res-name=headers, visibility=VISIBLE, width=600, height=887, 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, root-is-layout-requested=false, has-input-connection=false, x=0.0, y=0.0, child-count=2}
|
+-------->ListView{id=16908298, res-name=list, visibility=VISIBLE, width=536, height=823, has-focus=false, has-focusable=false, has-window-focus=true, is-clickable=true, 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=32.0, y=32.0, child-count=0} ****MATCHES******
|
+-------->FrameLayout{id=16909143, res-name=list_footer, visibility=VISIBLE, width=536, 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=false, is-selected=false, root-is-layout-requested=false, has-input-connection=false, x=32.0, y=855.0, child-count=0}
|
+------>RelativeLayout{id=16909146, res-name=button_bar, 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, child-count=2}
|
+------->AppCompatButton{id=16909147, res-name=back_button, visibility=VISIBLE, width=0, height=0, 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=true, is-selected=false, root-is-layout-requested=false, has-input-connection=false, x=0.0, y=0.0, text=Tilbage, input-type=0, ime-target=false, has-links=false}
|
+------->LinearLayout{id=-1, visibility=VISIBLE, width=0, height=0, has-focus=false, has-focusable=true, 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, child-count=2}
|
+-------->AppCompatButton{id=16909148, res-name=skip_button, visibility=GONE, width=0, height=0, has-focus=false, has-focusable=false, has-window-focus=true, is-clickable=true, is-enabled=true, is-focused=false, is-focusable=true, is-layout-requested=true, is-selected=false, root-is-layout-requested=false, has-input-connection=false, x=0.0, y=0.0, text=Spring over, input-type=0, ime-target=false, has-links=false}
|
+-------->AppCompatButton{id=16909149, res-name=next_button, visibility=VISIBLE, width=0, height=0, 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=true, is-selected=false, root-is-layout-requested=false, has-input-connection=false, x=0.0, y=0.0, text=Næste, input-type=0, ime-target=false, has-links=false}
|
+----->LinearLayout{id=-1, visibility=VISIBLE, width=600, height=887, 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=3}
|
+------>ListView{id=16908298, res-name=list, visibility=VISIBLE, width=600, height=887, has-focus=true, has-focusable=true, has-window-focus=true, is-clickable=true, is-enabled=true, is-focused=true, is-focusable=true, is-layout-requested=false, is-selected=false, root-is-layout-requested=false, has-input-connection=false, x=0.0, y=0.0, child-count=12} ****MATCHES******
|
+------->AppCompatTextView{id=16908310, res-name=title, visibility=VISIBLE, width=584, height=35, 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, root-is-layout-requested=false, has-input-connection=false, x=8.0, y=0.0, text=Synkronisering, input-type=0, ime-target=false, has-links=false}
...
出於某種原因,onData()
2個ListView
s比,但我只是無法弄清楚如何防止這種情況,因爲我不明白第一個ListView
來自哪裏。
這裏是我的preference.xml
:
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
<PreferenceCategory
android:title="@string/activity_settings_sync_category_title"
android:key="@string/activity_settings_sync_category_key">
<SwitchPreference
android:key="@string/activity_settings_sync_key"
android:summary="@string/activity_settings_sync_summary"
android:title="@string/activity_settings_sync_title"
android:defaultValue="true"/>
</PreferenceCategory>
<PreferenceCategory
android:title="@string/activity_settings_site_category_title"
android:key="@string/activity_settings_site_category_key"
android:summary="@string/activity_settings_site_category_summary">
<EditTextPreference
android:key="@string/activity_settings_hospital_key"
android:title="@string/activity_settings_hospital_title"
android:summary="@string/activity_settings_hospital_summary"
android:dialogTitle="@string/activity_settings_hospital_dialog_title"
android:dialogMessage="@string/activity_settings_hospital_dialog_message"
android:inputType="textCapWords" />
<EditTextPreference
android:key="@string/activity_settings_department_key"
android:title="@string/activity_settings_department_title"
android:summary="@string/activity_settings_department_summary"
android:dialogTitle="@string/activity_settings_department_dialog_title"
android:dialogMessage="@string/activity_settings_department_dialog_message"
android:inputType="textCapWords" />
</PreferenceCategory>
<PreferenceCategory
android:title="@string/activity_settings_notification_ringtone_category_title"
android:key="@string/activity_settings_notification_ringtone_category_key">
<RingtonePreference
android:key="@string/activity_settings_notification_ringtone_key"
android:title="@string/activity_settings_notification_ringtone_title"
android:summary="@string/activity_settings_notification_ringtone_summary"
android:dialogTitle="@string/activity_settings_notification_ringtone_dialog_title"
android:dialogMessage="@string/activity_settings_notification_ringtone_dialog_message"/>
</PreferenceCategory>
<PreferenceCategory
android:title="@string/activity_settings_dicom_category_title"
android:key="@string/activity_settings_dicom_category_key">
<SwitchPreference
android:key="@string/activity_settings_dicom_worklist_key"
android:title="@string/activity_settings_dicom_worklist_title"
android:summary="@string/activity_settings_dicom_worklist_summary" />
<!--<EditTextPreference-->
<!--android:key="dcmwl_ae_title_preference"-->
<!--android:title="@string/pref_dicom_settings_worklist_ae_title"-->
<!--android:dialogMessage="@string/pref_dicom_settings_worklist_ip_dialog_text"-->
<!--android:dialogTitle="@string/pref_dicom_settings_worklist_ip_dialog_title"-->
<!--android:dependency="dcmwl_enable"/>-->
<!--<EditTextPreference-->
<!--android:defaultValue="10.0.0.2"-->
<!--android:key="dcmwl_ip_preference"-->
<!--android:title="@string/pref_dicom_settings_worklist_ip"-->
<!--android:dependency="dcmwl_enable" />-->
<!--<EditTextPreference-->
<!--android:key="dcmwl_port_preference"-->
<!--android:title="@string/pref_dicom_settings_worklist_port"-->
<!--android:dependency="dcmwl_enable"/>-->
<SwitchPreference
android:key="@string/activity_settings_dicom_pacs_key"
android:title="@string/activity_settings_dicom_pacs_title"
android:summary="@string/activity_settings_dicom_pacs_summary"/>
<!--<EditTextPreference-->
<!--android:key="pacs_ae_title_preference"-->
<!--android:title="@string/pref_dicom_settings_pacs_ae_title"-->
<!--android:dependency="pacs_enable"/>-->
<!--<EditTextPreference-->
<!--android:defaultValue="10.0.0.2"-->
<!--android:key="pacs_ip_preference"-->
<!--android:title="@string/pref_dicom_settings_pacs_ip"-->
<!--android:dependency="pacs_enable"/>-->
<!--<EditTextPreference-->
<!--android:key="pacs_port_preference"-->
<!--android:title="@string/pref_dicom_settings_pacs_port"-->
<!--android:dependency="pacs_enable"/>-->
</PreferenceCategory>
<PreferenceCategory
android:title="@string/activity_settings_debug_category_title"
android:key="@string/activity_settings_debug_category_key">
<SwitchPreference
android:key="@string/activity_settings_debug_key"
android:summary="@string/activity_settings_debug_summary"
android:title="@string/activity_settings_debug_title"
android:defaultValue="false"/>
</PreferenceCategory>
</PreferenceScreen>
更新: 試圖修改從第一個答案是這樣建議的解決方案:
private static Matcher<View> withResName(final String resName) {
return new TypeSafeMatcher<View>() {
@Override
public void describeTo(Description description) {
description.appendText("with res-name: " + resName);
Timber.d("Resourcename: ", resName);
}
@Override
public boolean matchesSafely(View view) {
Timber.d("View ID: ", view.getId());
String matchableResName = view.getResources().getResourceEntryName(view.getId());
return !TextUtils.isEmpty(matchableResName) && matchableResName.equals(resName);
}
};
}
測試現在看起來是這樣的:
@Test
public void whenHospitalSettingEmpty_shouldDisplaySummary() throws Exception {
Resources res = getInstrumentation().getTargetContext().getResources();
mPreferenceEditor.putString(
res.getString(R.string.activity_settings_hospital_key),
"").commit();
mActivityTestRule.launchActivity(null);
String expected = res.getString(R.string.activity_settings_hospital_summary);
// onView(withText(expected)).check(matches(isDisplayed()));
onData(allOf(
is(instanceOf(Preference.class)),
withKey(res.getString(R.string.activity_settings_hospital_key)),
withSummary(R.string.activity_settings_hospital_summary),
withTitle(R.string.activity_settings_hospital_title)))
.onChildView(withText(expected))
.inAdapterView(withParent(not(withResName("headers"))))
.check(matches(isDisplayed()));
}
但它仍然不起作用。日誌輸出看起來是這樣的:
...
I/TestRunner: android.content.res.Resources$NotFoundException:
Unable to find resource ID #0xffffffff
at android.content.res.Resources.getResourceEntryName(Resources.java:2127)
at com.conhea.smartgfr.preferences.SettingsActivityTest$2.matchesSafely(SettingsActivityTest.java:153)
at com.conhea.smartgfr.preferences.SettingsActivityTest$2.matchesSafely(SettingsActivityTest.java:143)
at org.hamcrest.TypeSafeMatcher.matches(TypeSafeMatcher.java:65)
at org.hamcrest.core.IsNot.matches(IsNot.java:25)
at android.support.test.espresso.matcher.ViewMatchers$26.matchesSafely(ViewMatchers.java:892)
at android.support.test.espresso.matcher.ViewMatchers$26.matchesSafely(ViewMatchers.java:883)
at org.hamcrest.TypeSafeMatcher.matches(TypeSafeMatcher.java:65)
...
這是行不通的。 item.getId()沒有返回一個ID。出於某種原因,android.R.id.headers id是隱藏的。這非常奇怪,因爲在佈局檢查器中,我可以看到,linearlayout有一個名爲headers的ID,在調試輸出中我可以看到整數值。 – Bohsen
getIdentifier()是解決方案的一部分,而不是'item.getId()'執行'resources.getIdentifier(「headers」,「id」,「android」)' – azizbekian
。謝謝您的幫助。 – Bohsen