Espresso自动生成的测试失败

时间:2017-04-21 09:01:17

标签: android android-espresso android-espresso-recorder

我创建了一个使用espresso记录的简单测试,当按钮点击“Hello World”到“Button Clicked!”时,textview的值会发生变化。生成的代码如下

public class MainActivityTest {

    @Rule
    public ActivityTestRule<MainActivity> mActivityTestRule = new ActivityTestRule<>(MainActivity.class);

    @Test
    public void mainActivityTest() {
        ViewInteraction textView = onView(
                allOf(withId(R.id.tv), withText("Hello World!"),
                        childAtPosition(
                                childAtPosition(
                                        withId(android.R.id.content),
                                        0),
                                1),
                        isDisplayed()));
        textView.check(matches(withText("Hello World!")));

        ViewInteraction button = onView(
                allOf(withId(R.id.button), withText("Button"), isDisplayed()));
        button.perform(click());

        ViewInteraction textView2 = onView(
                allOf(withId(R.id.tv), withText("Button Clicked!!"),
                        childAtPosition(
                                childAtPosition(
                                        withId(android.R.id.content),
                                        0),
                                1),
                        isDisplayed()));
        textView2.check(matches(withText("Button Clicked!!")));

    }

    private static Matcher<View> childAtPosition(
            final Matcher<View> parentMatcher, final int position) {

        return new TypeSafeMatcher<View>() {
            @Override
            public void describeTo(Description description) {
                description.appendText("Child at position " + position + " in parent ");
                parentMatcher.describeTo(description);
            }

            @Override
            public boolean matchesSafely(View view) {
                ViewParent parent = view.getParent();
                return parent instanceof ViewGroup && parentMatcher.matches(parent)
                        && view.equals(((ViewGroup) parent).getChildAt(position));
            }
        };
    }
}

此测试将在执行时失败,并给出以下错误

  

android.support.test.espresso.NoMatchingViewException:没有视图   层次结构找到匹配:(与id:com.mysampleapps.mytestproject:id / tv   和文字:是“Hello World!”和孩子在父母的第1位   父级的位置0的孩子,id:android:id / content,是   在屏幕上显示给用户)

如果我从测试用例中删除'childAtPosition'匹配器

public void mainActivityTest() {
        ViewInteraction textView = onView(
                allOf(withId(R.id.tv), withText("Hello World!"),
                        isDisplayed()));
        textView.check(matches(withText("Hello World!")));

        ViewInteraction button = onView(
                allOf(withId(R.id.button), withText("Button"), isDisplayed()));
        button.perform(click());

        ViewInteraction textView2 = onView(
                allOf(withId(R.id.tv), withText("Button Clicked!!"),
                        isDisplayed()));
        textView2.check(matches(withText("Button Clicked!!")));

    }

现在它将完美运作。

这是浓缩咖啡的错误吗?

2 个答案:

答案 0 :(得分:0)

我认为这是Android Studio中Espresso代码生成器中的一个错误。我看到完全相同的事情。虽然我还没有能够检测出一个模式,但我认为它可能只是计算布局中的特定项目(并非所有项目)。例如,我在布局中包含了三个指南(这些指南位于布局的顶部),第一个视图生成的计数减少了3个。

当我知道我不需要它时,我正在做的不是使用这个匹配器,但是在它有用的情况下,我将基于0的计数与特定布局中的第N项匹配。这似乎有用(虽然它很脆弱 - 我所要做的就是更改布局文件中的顺序,而匹配器现在会中断)。

答案 1 :(得分:0)

此问题归因于断言依赖于UI Automator层次结构来建立元素的子位置,而动作依赖于Espresso层次结构。在重播期间,动作和断言都是使用Espresso层次结构执行的,因此,由于UI Automator和Espresso层次结构之间的子位置不匹配,断言更容易失败。

有几种解决此限制的方法:

1)在Android Studio中,在文件|设置,打开构建,执行,部署| Espresso Test Recorder并将“ Assertion depth”设置为1。这样,添加的断言将不依赖于子位置来标识断言的元素(生成的代码与上面的示例非常相似,其中删除了“ childAtPosition”匹配器)。缺点是断言可能变得太笼统,可能会匹配多个元素。

2)依靠动作来断言屏幕上某些元素的存在,例如,不要断言屏幕上存在带有特定文本的按钮,而是单击它。

3)仅记录动作并将声明手动添加到生成的Espresso测试中。

4)手动调整记录的断言以使用正确的子位置。