J'essaie de tester ma classe SettingsActivity
, mais je continue d'obtenir un AmbiguousViewMatcherException
.Espresso: ListViews multiples
Voici mon testcase:
@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()));
}
est ici la sortie du journal:
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}
...
Pour une raison quelconque le onData()
correspond à deux ListView
s, mais je ne peux pas comprendre comment empêcher cela, parce que je ne comprends pas d'où vient le premier ListView
.
Voici mon 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>
Mise à jour: tenté de modifier la solution proposée de la première réponse à ceci:
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);
}
};
}
Le test ressemble à ceci maintenant:
@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()));
}
Mais ça ne marche toujours pas. La sortie du journal ressemble à ceci:
...
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)
...
Cela ne fonctionne pas. item.getId() ne retourne pas d'identifiant. Pour une raison quelconque, l'ID android.R.id.headers est masqué. C'est vraiment étrange parce que dans l'inspecteur de disposition, je peux voir que linearlayout a un ID nommé en-têtes et dans la sortie de débogage je peux voir la valeur entière. – Bohsen
Au lieu de 'item.getId()' effectuer 'resources.getIdentifier (" headers "," id "," android ")' – azizbekian
getIdentifier() faisait partie de la solution. Merci pour l'aide. – Bohsen