注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

和申的个人主页

专注于java开发,1985wanggang

 
 
 

日志

 
 

Espresso实战:快速的Android UI自动化测试  

2015-08-27 11:11:19|  分类: 安卓 |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |
本文出自:Michael Evans译文出自:开发技术前线,译者:desmond1121,校对者:Mr.Simple

在我和很多Android开发者聊天的时候,我注意到他们在开发的过程中并不注重测试这一环节,原因是他们认为Android测试太难实现,或者难以集成到现有的工程中等等。但是实际上写一个 Espresso并不是一件很难的事情,而且它能够非常方便地集成到你的工程之中。

容易实现

Espresso测试是非常容易实现的,它由三部分组成:

  • ViewMachers:寻找用来测试的View。
  • ViewActions:发送交互事件。
  • ViewAssertions:检验测试结果。

举个例子,接下来这部分代码向id为name_field的EditText输入”Steve”,并点击id为greet_button的按钮,最后检查屏幕上是否有”Hello Steve!”字样。

  1. @Test  
  2. public void testSayHello() {  
  3.   onView(withId(R.id.name_field)).perform(typeText("Steve"));  
  4.   onView(withId(R.id.greet_button)).perform(click());  
  5.   onView(withText("Hello Steve!")).check(matches(isDisplayed()));  
  6. }  

是不是很简单?我们再来看看在多线程情况下如何进行测试。

集成测试

Espresso官方文档有这样一段话:

Espresso测试有个很强大的地方是它在多个测试操作中是线程安全的。Espresso会等待当前进程的消息队列中的UI事件,并且在任何一个测试操作中会等待其中的AsyncTask结束才会执行下一个测试。这能够解决程序中大部分的线程同步问题。

我一般使用 Retrofit来处理我的Http请求,而不是AsyncTask(虽然大多数人还是使用AsyncTask),在这种情况下也有别的办法来实现线程安全的测试。Espresso中有个API叫做registerIdlingResource,它可以让你使用自定义的线程安全逻辑。

通过IdlingResource,我们可以通过以下这段代码来实现线程同步的Retrofit接口:

  1. public class MockApiService implements ApiService, IdlingResource {  
  2.    
  3.   private final ApiService api;  
  4.   private final AtomicInteger counter;  
  5.   private final List<ResourceCallback> callbacks;  
  6.    
  7.   public MockApiService(ApiService api) {  
  8.       this.api = api;  
  9.       this.callbacks = new ArrayList<>();  
  10.       this.counter = new AtomicInteger(0);  
  11.   }  
  12.    
  13.   @Override  
  14.   public Response doWork() {  
  15.       counter.incrementAndGet();  
  16.       return decrementAndNotify(api.doWork());  
  17.   }  
  18.    
  19.   @Override  
  20.   public String getName() {  
  21.       return this.getClass().getName();  
  22.   }  
  23.    
  24.   @Override  
  25.   public boolean isIdleNow() {  
  26.       return counter.get() == 0;  
  27.   }  
  28.    
  29.   @Override  
  30.   public void registerIdleTransitionCallback(ResourceCallback resourceCallback) {  
  31.       callbacks.add(resourceCallback);  
  32.   }  
  33.    
  34.   private <T> T decrementAndNotify(T data) {  
  35.       counter.decrementAndGet();  
  36.       notifyIdle();  
  37.       return data;  
  38.   }  
  39.    
  40.   private void notifyIdle() {  
  41.       if (counter.get() == 0) {  
  42.           for (ResourceCallback cb : callbacks) {  
  43.               cb.onTransitionToIdle();  
  44.           }  
  45.       }  
  46.   }  
  47. }  

这个类告诉了Espresso你的应用将会在(doWork())方法调用后才能够进入下一个步骤。但是你看完这段代码应该马上意识到一件事情:这样的写法太过啰嗦了,你需要实现很多方法才能做到这线程同步一个小功能。一定有其他更好的办法来实现(接下来就是了!)。

实际上技巧就隐藏在之前的官方文档中,“Expresso会等待UI事件……并等待AsyncTask的结束才会执行下一个测试”。 实际上我们只要在AsyncTask的ThreadPoolExecutor中执行Retrofit请求就可以了!

幸运的是Retrofit的BaseAdapter.Builder类提供了这样一种方法:

  1. new RestAdapter.Builder()  
  2.    .setExecutors(AsyncTask.THREAD_POOL_EXECUTOR, new MainThreadExecutor())  
  3.    .build();  

如此简单,你还有理由不写Espresso测试吗?


预告:  2015中国移动开发者大会(MDCC 2015)将于10月15-16日在北京新云南皇冠假日酒店召开。大会特设五大技术专场:平台与技术iOS、平台与技术Android、产品与设计、游戏开发、企业移动化。此外,大会更是首次举办国内极具权威影响力的IoT技术峰会,特设硬件开发技术与虚拟现实两大专场。大会将聚集国内最具实力的产品技术团队,与开发者一道进行最前沿的探讨与交流。


http://www.csdn.net/article/2015-08-19/2825493-using-espresso-for-easy-ui-testing

  评论这张
 
阅读(216)| 评论(0)
推荐 转载

历史上的今天

在LOFTER的更多文章

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2016