您的位置:首页 > 其它

使用Espresso过程中遇到的问题

2016-10-19 17:45 316 查看
一、android.support.test.espresso.NoMatchingViewException: No views in hierarchy found matching

android.support.test.espresso.NoMatchingViewException: No views in hierarchy found matching: (with text: is "gh" and Child at position 0 in parent (with id: studiotwotwotest.myapplication:id/lay_root and Child at position 0 in parent with id: android:id/content)
and is displayed on the screen to the user)



原因:在AdapterView控件中,在子view运行时才会动态填充view。所以如果布局中有AdapterView(例如ListView,GridView,or Spinner),并且屏幕初始化时并未加载到屏幕里,方法onView()将无效。你需要调用onData()方法来进行控件的查找。

过程:

(一)布局中没有ListView

目的:测试AdapterView之外的控件(测试以editText为id,并且文本为gh的EditText是否存在)

1.activity_main.xml中的代码,EditText中text为空

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/lay_root"
android:layout_width="match_parent"
android:layout_height="match_parent">
<EditText
android:layout_width="100dp"
android:layout_height="100dp"
android:text=""
android:id="@+id/editText"
tools:layout_constraintTop_creator="1"
tools:layout_constraintRight_creator="1"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />

<TextView
android:text="TextView"
android:layout_width="100dp"
android:layout_height="100dp"
android:id="@+id/textView"
tools:layout_constraintTop_creator="1"
android:layout_marginStart="16dp"
android:layout_marginTop="7dp"
tools:layout_constraintLeft_creator="1"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent"
android:layout_marginLeft="16dp" />

</android.support.constraint.ConstraintLayout>


布局预览图(左边一个TextView,右边一个EditText)



现在执行Record Espresso Test,界面中输入的内容



选择exist



现在修改布局文件,给EditText赋值gh,运行生成的测试文件

修改后的main_activity.xml

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/lay_root"
android:layout_width="match_parent"
android:layout_height="match_parent">
<EditText
android:layout_width="100dp"
android:layout_height="100dp"
android:text="gh"
android:id="@+id/editText"
tools:layout_constraintTop_creator="1"
tools:layout_constraintRight_creator="1"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />

<TextView
android:text="TextView"
android:layout_width="100dp"
android:layout_height="100dp"
android:id="@+id/textView"
tools:layout_constraintTop_creator="1"
android:layout_marginStart="16dp"
android:layout_marginTop="7dp"
tools:layout_constraintLeft_creator="1"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent"
android:layout_marginLeft="16dp" />

</android.support.constraint.ConstraintLayout>


生成的测试文件MainActivityTest3中的内容

package studiotwotwotest.myapplication;

import android.support.test.espresso.ViewInteraction;
import android.support.test.rule.ActivityTestRule;
import android.support.test.runner.AndroidJUnit4;
import android.test.suitebuilder.annotation.LargeTest;

import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;

import static android.support.test.espresso.Espresso.onView;
import static android.support.test.espresso.action.ViewActions.click;
import static android.support.test.espresso.action.ViewActions.closeSoftKeyboard;
import static android.support.test.espresso.action.ViewActions.replaceText;
import static android.support.test.espresso.matcher.ViewMatchers.isDisplayed;
import static android.support.test.espresso.matcher.ViewMatchers.withId;
import static android.support.test.espresso.matcher.ViewMatchers.withParent;
import static org.hamcrest.Matchers.allOf;

@LargeTest
@RunWith(AndroidJUnit4.class)
public class MainActivityTest3 {

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

@Test
public void mainActivityTest3() {
ViewInteraction editText = onView(
allOf(withId(R.id.editText),
withParent(allOf(withId(R.id.lay_root),
withParent(withId(android.R.id.content)))),
isDisplayed()));
editText.perform(click());

ViewInteraction editText2 = onView(
allOf(withId(R.id.editText),
withParent(allOf(withId(R.id.lay_root),
withParent(withId(android.R.id.content)))),
isDisplayed()));
editText2.perform(replaceText("gh"), closeSoftKeyboard());

}

}


运行结果可以看到一切正常:



(二)布局中有ListView

目的:测试AdapterView(本文中测试的是ListView)

activity_main.xml中的内容,布局中含有一个ListView,高度是固定值200dp

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/lay_root"
android:layout_width="match_parent"
android:layout_height="match_parent">
<EditText
android:layout_width="100dp"
android:layout_height="200dp"
android:text=""
android:id="@+id/editText"
tools:layout_constraintTop_creator="1"
tools:layout_constraintRight_creator="1"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />

<TextView
android:text="TextView"
android:layout_width="100dp"
android:layout_height="100dp"
android:id="@+id/textView"
tools:layout_constraintTop_creator="1"
android:layout_marginStart="16dp"
android:layout_marginTop="7dp"
tools:layout_constraintLeft_creator="1"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent"
android:layout_marginLeft="16dp" />

<ListView
android:id="@+id/lv_listview"
android:layout_width="150dp"
android:layout_height="200dp"
tools:layout_constraintTop_creator="1"
android:layout_marginTop="251dp"
tools:layout_constraintLeft_creator="1"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</android.support.constraint.ConstraintLayout>


手机界面



1.点击listview条目中的界面可见的button,并且也选择Exists



生成的测试文件

package studiotwotwotest.myapplication;

import android.support.test.espresso.ViewInteraction;
import android.support.test.rule.ActivityTestRule;
import android.support.test.runner.AndroidJUnit4;
import android.test.suitebuilder.annotation.LargeTest;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewParent;

import org.hamcrest.Description;
import org.hamcrest.Matcher;
import org.hamcrest.TypeSafeMatcher;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;

import static android.support.test.espresso.Espresso.onView;
import static android.support.test.espresso.Espresso.pressBack;
import static android.support.test.espresso.action.ViewActions.click;
import static android.support.test.espresso.assertion.ViewAssertions.matches;
import static android.support.test.espresso.matcher.ViewMatchers.isDisplayed;
import static android.support.test.espresso.matcher.ViewMatchers.withId;
import static android.support.test.espresso.matcher.ViewMatchers.withParent;
import static android.support.test.espresso.matcher.ViewMatchers.withText;
import static org.hamcrest.Matchers.allOf;

@LargeTest
@RunWith(AndroidJUnit4.class)
public class MainActivityTest3 {

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

@Test
public void mainActivityTest3() {
//隐藏了虚拟键盘
pressBack();
<span style="white-space:pre"> </span>//查找listview中第一个button,显示内容为0,并点击
ViewInteraction button = onView(
allOf(withId(R.id.bt_button), withText("0"),
withParent(childAtPosition(
withId(R.id.lv_listview),
0)),
isDisplayed()));
button.perform(click());
<span style="white-space:pre"> </span>//查找listview中第四个按钮,显示的内容为3,并点击了一下
ViewInteraction button2 = onView(
allOf(withId(R.id.bt_button), withText("3"),
withParent(childAtPosition(
withId(R.id.lv_listview),
3)),
isDisplayed()));
button2.perform(click());
<span style="white-space:pre"> </span>//检测id为bt_btton,显示内容为0的按钮是否存在
ViewInteraction button3 = onView(
allOf(withId(R.id.bt_button),
childAtPosition(
childAtPosition(
withId(R.id.lv_listview),
0),
0),
isDisplayed()));
button3.check(matches(isDisplayed()));

}

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));
}
};
}
}


此时可以看到运行结果正常:



2.点击界面listview中不可见的条目,如6,或者7、8、9

package studiotwotwotest.myapplication;

import android.support.test.espresso.ViewInteraction;
import android.support.test.rule.ActivityTestRule;
import android.support.test.runner.AndroidJUnit4;
import android.test.suitebuilder.annotation.LargeTest;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewParent;

import org.hamcrest.Description;
import org.hamcrest.Matcher;
import org.hamcrest.TypeSafeMatcher;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;

import static android.support.test.espresso.Espresso.onView;
import static android.support.test.espresso.Espresso.pressBack;
import static android.support.test.espresso.action.ViewActions.click;
import static android.support.test.espresso.assertion.ViewAssertions.matches;
import static android.support.test.espresso.matcher.ViewMatchers.isDisplayed;
import static android.support.test.espresso.matcher.ViewMatchers.withId;
import static android.support.test.espresso.matcher.ViewMatchers.withParent;
import static android.support.test.espresso.matcher.ViewMatchers.withText;
import static org.hamcrest.Matchers.allOf;

@LargeTest
@RunWith(AndroidJUnit4.class)
public class MainActivityTest3 {

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

@Test
public void mainActivityTest3() {
//隐藏键盘
pressBack();
<span style="white-space:pre"> </span>//查找第一个button,显示的内容为0,并点击
ViewInteraction button = onView(
allOf(withId(R.id.bt_button), withText("0"),
withParent(childAtPosition(
withId(R.id.lv_listview),
0)),
isDisplayed()));
button.perform(click());
<span style="white-space:pre"> </span>//查找第8个button,显示的内容为7,并点击
ViewInteraction button2 = onView(
allOf(withId(R.id.bt_button), withText("7"),
withParent(childAtPosition(
withId(R.id.lv_listview),
7)),
isDisplayed()));
button2.perform(click());
<span style="white-space:pre"> </span>//断言第8个按钮,显示内容为7的存在
ViewInteraction button3 = onView(
allOf(withId(R.id.bt_button),
childAtPosition(
childAtPosition(
withId(R.id.lv_listview),
7),
7),
isDisplayed()));
button3.check(matches(isDisplayed()));

}

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));
}
};
}
}


可以看到运行失败:



解决办法:AdapterView中,如果view在屏幕初始化时不显示,onView()方法将会失效。onData()方法是安全的,出于安全性考虑,可以全部使用该方法。

现在将onView()替换为onData(),运行结果正常

替换后的测试文件

package studiotwotwotest.myapplication;

import android.support.test.espresso.ViewInteraction;
import android.support.test.rule.ActivityTestRule;
import android.support.test.runner.AndroidJUnit4;
import android.test.suitebuilder.annotation.LargeTest;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewParent;

import org.hamcrest.Description;
import org.hamcrest.Matcher;
import org.hamcrest.TypeSafeMatcher;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;

import static android.support.test.espresso.Espresso.onData;
import static android.support.test.espresso.Espresso.onView;
import static android.support.test.espresso.Espresso.pressBack;
import static android.support.test.espresso.action.ViewActions.click;
import static android.support.test.espresso.assertion.ViewAssertions.matches;
import static android.support.test.espresso.matcher.ViewMatchers.isDisplayed;
import static android.support.test.espresso.matcher.ViewMatchers.withId;
import static android.support.test.espresso.matcher.ViewMatchers.withParent;
import static android.support.test.espresso.matcher.ViewMatchers.withText;
import static org.hamcrest.Matchers.allOf;
import static org.hamcrest.Matchers.hasToString;

@LargeTest
@RunWith(AndroidJUnit4.class)
public class MainActivityTest5 {

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

@Test
public void mainActivityTest3() {
//隐藏键盘
pressBack();

//查找第一个button,显示的内容为0,并点击
ViewInteraction button = onData(hasToString("0")).perform(click());
<pre name="code" class="java"> //查找第8个button,显示的内容为7,并点击 ViewInteraction button1 = onData(hasToString("7")).perform(click());
<span style="white-space:pre">	</span>//断言第8个按钮,显示内容为7的存在
ViewInteraction button2 = onData(hasToString("7")).perform(click()); button2.check(matches(isDisplayed())); }}

运行结果:



二、No activities in stage RESUMED. Did you forget to launch the activity. (test.getActivity() or similar)



原因:屏幕锁屏了。

解决方法:测试时保持屏幕处于解锁常亮状态

三、运行测试文件时界面卡住了
布局文件如下,listview的高度设置的是wrap_content,并且距顶部251dp,所以listview位于屏幕底部,完全展开,但是没有在屏幕中完全显示

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/lay_root"
android:layout_width="match_parent"
android:layout_height="match_parent">
<EditText
android:layout_width="100dp"
android:layout_height="100dp"
android:text=""
android:id="@+id/editText"
tools:layout_constraintTop_creator="1"
tools:layout_constraintRight_creator="1"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />

<TextView
android:text="TextView"
android:layout_width="100dp"
android:layout_height="100dp"
android:id="@+id/textView"
tools:layout_constraintTop_creator="1"
android:layout_marginStart="16dp"
android:layout_marginTop="7dp"
tools:layout_constraintLeft_creator="1"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent"
android:layout_marginLeft="16dp" />

<ListView
android:id="@+id/lv_listview"
android:layout_width="362dp"
android:layout_height="wrap_content"
tools:layout_constraintTop_creator="1"
android:layout_marginTop="251dp"
tools:layout_constraintLeft_creator="1"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</android.support.constraint.ConstraintLayout>

手机界面为:



测试文件为:

package studiotwotwotest.myapplication;

import android.support.test.espresso.ViewInteraction;
import android.support.test.rule.ActivityTestRule;
import android.support.test.runner.AndroidJUnit4;
import android.test.suitebuilder.annotation.LargeTest;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewParent;

import org.hamcrest.Description;
import org.hamcrest.Matcher;
import org.hamcrest.TypeSafeMatcher;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;

import static android.support.test.espresso.Espresso.onData;
import static android.support.test.espresso.Espresso.onView;
import static android.support.test.espresso.Espresso.pressBack;
import static android.support.test.espresso.action.ViewActions.click;
import static android.support.test.espresso.assertion.ViewAssertions.matches;
import static android.support.test.espresso.matcher.ViewMatchers.isDisplayed;
import static android.support.test.espresso.matcher.ViewMatchers.withId;
import static android.support.test.espresso.matcher.ViewMatchers.withParent;
import static android.support.test.espresso.matcher.ViewMatchers.withText;
import static org.hamcrest.Matchers.allOf;
import static org.hamcrest.Matchers.hasToString;

@LargeTest
@RunWith(AndroidJUnit4.class)
public class MainActivityTest5 {

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

@Test
public void mainActivityTest3() {

ViewInteraction button = onData(hasToString("0")).perform(click());

ViewInteraction button1 = onData(hasToString("7")).perform(click());

ViewInteraction button2 = onData(hasToString("7")).perform(click());
button2.check(matches(isDisplayed()));

}
}


出现的状况如下,底部左侧的进度条不停地旋转,但是一直不结束:



原因:onData()加载AdapterView中的view时,需要先使view先获取焦点,即加载到屏幕中。如上的测试文件加载了条目7,但是条目7不在屏幕中,又由于listview设置为wrap_content,即listview已经完全展开,并不能移动条目,所以就出现了如上的问题

解决办法:使用onData()方法,在写布局时,需要将listview设置为一个固定的高度,即需要在listview内容长度过长显示不全时可以滑动界面。如设置高度200dp。

修改后的布局:

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/lay_root"
android:layout_width="match_parent"
android:layout_height="match_parent">
<EditText
android:layout_width="100dp"
android:layout_height="100dp"
android:text=""
android:id="@+id/editText"
tools:layout_constraintTop_creator="1"
tools:layout_constraintRight_creator="1"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />

<TextView
android:text="TextView"
android:layout_width="100dp"
android:layout_height="100dp"
android:id="@+id/textView"
tools:layout_constraintTop_creator="1"
android:layout_marginStart="16dp"
android:layout_marginTop="7dp"
tools:layout_constraintLeft_creator="1"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent"
android:layout_marginLeft="16dp" />

<ListView
android:id="@+id/lv_listview"
android:layout_width="150dp"
android:layout_height="200dp"
tools:layout_constraintTop_creator="1"
android:layout_marginTop="251dp"
tools:layout_constraintLeft_creator="1"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</android.support.constraint.ConstraintLayout>
修改后的手机界面:



注:参考资料:http://blog.csdn.net/yang786654260/article/details/52670837

    https://developer.android.com/training/testing/ui-testing/espresso-testing.html#run

    http://blog.csdn.net/qq744746842/article/details/50664136

    http://awonwon.blogspot.com/2015/10/hello-espresso.html

    https://google.github.io/android-testing-support-library/docs/espresso/index.html
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: