Android利用Espresso进行UI自动化测试的方法详解
我有一个观点,对于重复的工作,那么程序都是可以代替的,我想这是作为一个程序员的一个基本素养(能偷懒的绝不干活)。UI自动化测试就是为了应付一些重复的工作,比如说测试某个功能,那么从应用点击,再经过一系列的点击页面才能到达这个页面,然后进行测试,那么我们是不是可以写段代码让app自动跑起来,自动来到那个界面进行测试呢?答案是肯定的,这就是本文所要说的自动化测试。
引言
谷歌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必须在当前界面上显示出来(有且可见)。
方法名 | 含义 |
---|---|
click() | 点击view |
clearText() | 清除文本内容 |
swipeLeft() | 从右往左滑 |
swipeRight() | 从左往右滑 |
swipeDown() | 从上往下滑 |
swipeUp() | 从下往上滑 |
click() | 点击view |
closeSoftKeyboard() | 关闭软键盘 |
pressBack() | 按下物理返回键 |
doubleClick() | 双击 |
longClick() | 长按 |
scrollTo() | 滚动 |
replaceText() | 替换文本 |
openLinkWithText() | 打开指定超链 |
ViewAssertions 检验结果
使用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的介绍大概就是这些了,希望大家多提建议,一起进步。
总结
以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对脚本之家的支持。
您可能感兴趣的文章:
- Android高级UI特效仿直播点赞动画效果
- Android 仿抖音的评论列表的UI和效果的实现代码
- Android UI新组件学习和使用
- Android MIUI通知类短信权限的坑
- Android UI 中的 ListView列表控件的示例
- 浅谈Android RecyclerView UI的滚动控件示例
- android开发仿ios的UIScrollView实例代码
- Android Build Variants 为项目设置变种版本的方法
- Android编程设计模式之Builder模式实例详解
- Android UI控件之ImageSwitcher实现图片切换效果
- Android UI控件之Gallery实现拖动式图片浏览效果
- Android UI控件之ListView实现圆角效果
- Android UI控件之ProgressBar进度条
- Android UI控件之Spinner下拉列表效果
- Android编程处理窗口控件大小,形状,像素等UI元素工具类
- Android build文件的删除的方法
- android studio 一直卡在Gradle:Build Running的几种解决办法
- 25个实用酷炫的Android开源UI框架
- [置顶] 【Android】利用Fiddler进行抓包详解教程。抓取接口以及数据,可以抓真实安卓手机或者模拟器。
- .NET Core利用swagger进行API接口文档管理的方法详解
- Linux中利用Vim对文件进行密码保护的方法详解
- Android界面之----自定义的Dialog,然后利用回调方法,在调用处,进行Dialog中各按钮的事件处理。
- Android利用Dom对XML进行增删改查操作详解
- Linux中利用sudo进行赋权的方法详解
- android利用httpclient实现post、get请求restful接口进行json和form表单数据提交等公共方法类
- 关于/dev/null 和 /dev/zero文件详解以及误删/dev/null和/dev/zero的解决方法和利用/dev/zero进行磁盘IO测试方法
- python利用requests库进行接口测试的方法详解
- Android 利用httpclient进行网络通信,实现用户登录的方法
- .net core如何利用ConcurrentTest组件对方法进行压力测试详解
- Android中利用httpclient进行网络通信的方法(以用户登录为例说明)
- android 关于利用签名的SHA1进行安全校验的方法之一
- 详解Android应用中使用TabHost组件进行布局的基本方法
- Android利用SAX对XML进行增删改查操作详解
- 利用Jasmine对Angular进行单元测试的方法详解
- 解决Fedora14下eclipse进行android开发,ibus提示没有输入窗口的方法详解
- android 关于利用签名的SHA1进行安全校验的方法之一(推荐)
- Android中利用httpclient进行网络通信的方法(以用户登录为例说明)
- 使用Transact-SQL进行数据导入导出方法详解(转)