Why android espresso test fails when checking whether textView text ends with expected string (when ellipsized)

喜欢而已 提交于 2020-06-23 12:50:43

问题


I have an android test checking that external text message is truncated and ends with three dots when applying android:ellipsize="end". I do not know why test fails despite text presented in a activity is properly formatted.

@Test
fun when_errorMessage_is_very_long_then_text_of_errorMessageTextView_ends_with_dots() {

    //given
    val errorMessage = """
            Very long error, Very long error, Very long error, Very long error, Very long error,
            Very long error, Very long error, Very long error, Very long error, Very long error,
            Very long error, Very long error, Very long error, Very long error, Very long error,
            Very long error, Very long error, Very long error, Very long error, Very long 
    error,"""

    //when
    presentErrorActivityWith(errorMessage)

    //then
    onView(withId(R.id.errorMessageTextView)).check(matches(withText(endsWith("..."))));
}

I use functionality imported from

import androidx.test.espresso.Espresso.onView
import androidx.test.espresso.assertion.ViewAssertions.matches
import androidx.test.espresso.matcher.ViewMatchers.withId
import androidx.test.espresso.matcher.ViewMatchers.withText
import androidx.test.ext.junit.runners.AndroidJUnit4

errorMessageTextView declaration in ErrorActivity layout

<TextView
    android:id="@+id/errorMessageTextView"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"

    android:ellipsize="end"
    android:maxLines="2"

    android:paddingLeft="24dp"
    android:paddingRight="24dp"

    android:layout_marginTop="8dp"

    android:layout_marginStart="40dp"
    android:layout_marginLeft="40dp"
    android:layout_marginEnd="40dp"
    android:layout_marginRight="40dp"
    app:layout_constraintTop_toBottomOf="@+id/errorMessageTitleTextView"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintStart_toStartOf="parent"
    android:text=""/>


回答1:


To check if the text of a TextView has been ellipsized you can create your custom matcher like this one:

fun ellipsized() = object : TypeSafeMatcher<View>() {
    override fun describeTo(description: Description) {
        description.appendText("with ellipsized text")
    }

    override fun matchesSafely(v: View): Boolean {
        if (!(v is TextView)) {
            return false
        }
        val textView: TextView = v
        val layout: Layout = textView.getLayout()
        val lines = layout.lineCount
        if (lines > 0) {
            val ellipsisCount = layout.getEllipsisCount(lines - 1)
            if (ellipsisCount > 0) {
                return true
            }
        }

        return false
    }
}

And call it this way:

onView(withId(R.id.errorMessageTextView))
    .check(matches(ellipsized()))



回答2:


It might be because you're checking for the string "..." instead of the string "…" (the latter being one character instead of three dot characters).

Double check this by looking at the Espresso output. "Got: AppCompatTextView" ..." has a text= part that tells you exactly what text Espresso finds on the view.




回答3:


You can't test TextView with android:ellipsize by checking whether it ends with "..."

That is because even if you see it ends with "...", but it actually doesn't end with "...".

To verify this you can do this test

@Test
fun check_textview_text() {

    //given
    val errorMessage = """
            Very long error, Very long error, Very long error, Very long error, Very long error,
            Very long error, Very long error, Very long error, Very long error, Very long error,
            Very long error, Very long error, Very long error, Very long error, Very long error,
            Very long error, Very long error, Very long error, Very long error, Very long 
    error,"""

    //when
    presentErrorActivityWith(errorMessage)

    //then
    onView(withId(R.id.errorMessageTextView)).check(matches(withText(containsString(errorMessage ))));
}

This test must pass if your TextView contains the same string as in errorMessage variable. Although you actually see the elipsize three dots "..." on the screen instead.

Because actually under the hood android system doesn't set the "..." to end of the truncated string of the text field of the TextView.

In order to test android:ellipsize the right way:

@RunWith(AndroidJUnit4.class)
public class TextViewLongTextWithEllipsizeTest {
    private static final String TAG = "LOG_TAG";

    @Rule
    public ActivityTestRule mActivityRule = new ActivityTestRule<>(
            LongTextActivity.class);

    /**
     * Testing if a TextView uses "android:ellipsize"
     * at the end of its text as the text is long
     */
    @Test
    public void testTextIsEllipsized() {

        TextView textView = mActivityRule.getActivity().findViewById(R.id.errorMessageTextView);

        Layout layout = textView.getLayout();
        if (layout != null) {
            int ellipsisCount = layout.getEllipsisCount(layout.getLineCount() - 1);
            assertThat(ellipsisCount, is(greaterThan(0))); // if true then text is ellipsized
        }
    }

    /**
     * Testing if a TextView doesn't use "android:ellipsize"
     * at the end of its text as the text is not that long
     */
    @Test
    public void testTextNotEllipsized() {

        TextView textView = mActivityRule.getActivity().findViewById(R.id.no_ellipsize_text);

        Layout layout = textView.getLayout();
        if (layout != null) {
            int ellipsisCount = layout.getEllipsisCount(layout.getLineCount() - 1);
            assertThat(ellipsisCount, not(greaterThan(0))); // if true then text is not ellipsized
        }
    }


}

Hint: I just added the test method, please replicate the test given and when statements before testing.



来源:https://stackoverflow.com/questions/61437446/why-android-espresso-test-fails-when-checking-whether-textview-text-ends-with-ex

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!