Android使用Espresso进行UI自动化测试

发表于:2017-12-18 10:57

字体: | 上一篇 | 下一篇 | 我要投稿

 作者:安卓干货营    来源:掘金

  谷歌2013年的时候开源了espress,谷歌的思路是,等到它足够成熟和稳定以后,将其迁移到Android SDK中,以此可见对他的重视。Google使用Espresso测试了他们自己的超过30个应用程序,包括G+、Maps和Drive。
  Espresso测试是非常容易实现的,由三步构成:
  · ViewMachers:寻找用来测试的View。
  · ViewActions:发送交互事件。
  · ViewAssertions:检验测试结果
  先看下官方给的示例,就能理解以上的三个步骤:
  onView(withId(R.id.my_view))  // withId(R.id.my_view) is a ViewMatcher
  .perform(click())    // click() is a ViewAction
  .check(matches(isDisplayed())); // matches(isDisplayed()) is a ViewAssertion
  Espresso框架是google官方大力推荐的一套测试框架,所以无论如何都要学习一下的.另外,自Android Studio2.2版本开始,google就为Espresso框架内置了一个图形化界面,用来自动生成单元测试代码。
  接下来一起写一demo测试,深入了解Espresso。
  准备
  支持Espresso:
dependencies {
...
testCompile 'junit:junit:4.12'
androidTestCompile 'com.android.support.test.espresso:espresso-core:2.2.2', {
exclude group: 'com.android.support', module: 'support-annotations'
}
}
  在dependencies中添加,一般默认会有testCompile 'junit:junit:4.12',所以我们只需添加另一句即可。
  defaultConfig{
  ...
  testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
  }
  在defaultConfig中添加如上语句,支持测试运行。
  创建Test类
  特别注意,该类应在androidTest文件夹下
  · androidTest:进行与Android相关(如调用Android设备等)测试;
  · test:进行简单的只涉及java SE相关的测试。
  举个简单例子:
@RunWith(AndroidJUnit4.class)
@LargeTest
public class MainActivityInstrumentationTest {
@Rule
public ActivityTestRule mActivityRule = new ActivityTestRule<>(
MainActivity.class);
@Test
public void sayHello(){
onView(withText("Say hello!")).perform(click());
onView(withId(R.id.textView)).check(matches(withText("Hello, World!")));
}
}
  首先需要在测试用例类的类体前添加@RunWith的注解,并设置测试运行平台为AndroidJUnit4
  如果允许测试需要较大消耗,可以使用@LargeTest注解
  设置ActivityTestRule用来指明被测试的Activity,使用@Rule注解
  测试方法必须以 test 开头,并且使用@Test注解(否则会报找不到方法异常)
  @Rule
  @Rule
  public ActivityTestRule mTestRule = new ActivityTestRule<>(MainActivity.class);
  这句话就定义了一个测试规则,可以看到构造方法的参数里指定了一个 MainActivity.class, 具体的体现就是当你运行这段测试代码时,app将会直接打开 MainActivity界面然后进行你所定义的测试用例。 所以当你想直接测试某个界面时,你可以把那个界面填到这个参数里,这样就直接打开你指定的界面进行测试了。
  @Test
  @Test
  public void testLogin() {
  ...
  }
  定义一个测试方法,当你的测试类运行时,所执行的代码就是Test注解下的方法(Espresso还提供了其他的一些注解: 比如@After,@Before等,具体的用法可以去我上面写的android官网上查看),当然上面那段代码对应的就是testLogin测试方法,testLogin方法里所定义的就是要测试的内容。
  ViewMachers 查找View
  使用onView方法找到view:其中参数可以是withId(通过资源id查找),withText(通过显示内容查找)有多个约束条件时,可以使用allOf  如allOf(withText("Hello") ,withId(R.id.hello))
  注意:
  无论是通过withId()找控件还是通过withText()找控件,或者其他方式比如 withClassName(),withResourceName(),withTagKey()等方法,都要一定保证你所找的控件在当前页面确实存在且可见。
  如果要测试AdapterView ,比如 ListView 或GridView等,使用上面的onView()方法是无效的,因为AdapterView的布局item是动态呈现的,没法直接指定,所以当要测试AdapterView时,请把onView()方法换成onData() 方法,与onView()方法返回ViewInteraction类似,onData()方法返回DataInteraction,二者用法基本都是一样的。
  ViewActions 执行事件
  对View的操作:perform()方法  方式是onView(...).perform()。也可以执行多个操作在一个perform中如:perform(click(),clearText())。
  所有的操作都有一个前提 ———— 就是要执行的view必须在当前界面上显示出来(有且可见)。
  使用check()方法来检查View是否符合我们的期望: onView(...).check() 检查view中是否含有文本“hello”              check(matches(withText("hello")))
  看下我写的示例
  我们基本所有的app都有登录功能,都需要呼入用户名和密码,那么在点击登录之前需要对用户名和密码进行非空、格式等验证。
  以下示例我们点击登录按钮时,首先对输入的用户名和密码进行验证,验证不通过在TextView上显示对应原因,验证没有问题显示“登录成功”。
  Activity界面及逻辑
@Override
public void onClick(View view) {
if (view.getId() == R.id.bt_login) {
login();
}
}
/**
* 去登录
*/
private void login() {
String name = et_name.getText().toString().trim();
String pwd = et_pwd.getText().toString().trim();
if (TextUtils.isEmpty(name)) {
tv_login_result.setText("用户名为空");
return;
}
if (name.length() < 6 ) {
tv_login_result.setText("用户名格式错误");
return;
}
if (TextUtils.isEmpty(pwd)) {
tv_login_result.setText("密码为空");
return;
}
if (pwd.length() < 6 ) {
tv_login_result.setText("密码格式错误");
return;
}
tv_login_result.setText("登录成功");
}
  其他代码忽略。
@RunWith(AndroidJUnit4.class)
@LargeTest
public class MainActivityTest {
private String[] names = {"", "a", "123123"};
private String[] pwds = {"", "a", "123123"};
@Rule
public ActivityTestRule mTestRule = new ActivityTestRule<>(MainActivity.class);
@Before
public void init() {
Log.e("TAG", "init: ");
}
@Test
public void testLogin() {
// 不做任何输入,直接点击登录
onView(allOf(withId(R.id.bt_login), isDisplayed())).perform(click());
onView(allOf(withId(R.id.tv_login_result), isDisplayed())).check(matches(withText("用户名为空")));
// 用户名是空,点击登录
onView(allOf(withId(R.id.et_name), isDisplayed())).perform(replaceText(names[0]), closeSoftKeyboard());
onView(allOf(withId(R.id.bt_login), isDisplayed())).perform(click());
onView(allOf(withId(R.id.tv_login_result), isDisplayed())).check(matches(withText("用户名为空")));
// 用户名格式错误,点击登录
onView(allOf(withId(R.id.et_name), isDisplayed())).perform(replaceText(names[1]), closeSoftKeyboard());
onView(allOf(withId(R.id.bt_login), isDisplayed())).perform(click());
onView(allOf(withId(R.id.tv_login_result), isDisplayed())).check(matches(withText("用户名格式错误")));
// 用户名和密码都正确,点击登录
onView(allOf(withId(R.id.et_name), isDisplayed())).perform(replaceText(names[2]), closeSoftKeyboard());
onView(allOf(withId(R.id.et_pwd), isDisplayed())).perform(replaceText(pwds[2]), closeSoftKeyboard());
onView(allOf(withId(R.id.bt_login), isDisplayed())).perform(click());
onView(allOf(withId(R.id.tv_login_result), isDisplayed())).check(matches(withText("登录成功")));
}
}
  这里我们事先定义了一些测试数据,使用Espresso进行模拟各种情况输入和点击,测试是否符合我们的预期:
  对Espresso的介绍大概就是这些了,希望大家多提建议,一起进步。

上文内容不用于商业目的,如涉及知识产权问题,请权利人联系博为峰小编(021-64471599-8017),我们将立即处理。
《2023软件测试行业现状调查报告》独家发布~

精彩评论

  • winson1234
    2018-1-09 15:46:35

    android UI自动化

关注51Testing

联系我们

快捷面板 站点地图 联系我们 广告服务 关于我们 站长统计 发展历程

法律顾问:上海兰迪律师事务所 项棋律师
版权所有 上海博为峰软件技术股份有限公司 Copyright©51testing.com 2003-2024
投诉及意见反馈:webmaster@51testing.com; 业务联系:service@51testing.com 021-64471599-8017

沪ICP备05003035号

沪公网安备 31010102002173号