我创建了一个使用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!!")));
}
现在它将完美运作。
这是浓缩咖啡的错误吗?
答案 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)手动调整记录的断言以使用正确的子位置。