私はSettingsActivity
クラスをテストしようとしていますが、私はAmbiguousViewMatcherException
を得ています。ここでエスプレッソ:複数のリストビュー
は私のテストケースです:
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
の何らかの理由で、私はちょうどこれを防ぐ方法を見つけ出すことはできません、:
@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()));
}
ここではログ出力があります最初の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()));
}
しかし、それはまだ動作しません。ログ出力は次のようになります。私はPreferenceCategory
が内部ListView
を作成したとし
...
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が隠されています。レイアウトインスペクタでは、線形レイアウトにIDというヘッダがあり、デバッグ出力に整数値があることがわかるので、これは本当に奇妙です。 – Bohsen
'item.getId()の代わりに' resources.getIdentifier( "headers"、 "id"、 "android")を実行します。 – azizbekian
getIdentifier()はソリューションの一部でした。助けてくれてありがとう。 – Bohsen