When you first start learning UI testing with Espresso, it begins fairly quickly and easily by coding using its fluent APIs that manipulate your app’s UI elements. For example, here’s a pretty straightforward test that launches an activity “MainActivity”, types in an email and password, presses a button to sign in, and checks to see if there is a welcome message on screen.

当您首次开始使用Espresso学习UI测试时,它会通过使用可操纵应用程序UI元素的流利API进行编码,从而相当轻松快捷地开始。 例如,这是一个非常简单的测试,它启动一个活动“ MainActivity”,输入电子邮件和密码,按一个按钮登录,然后检查屏幕上是否显示欢迎消息。

This sort of thing works well if the sign-in process is fast. However, if the sign-in happens slower than expected, perhaps due to network or disk access, the test can fail to find the welcome message. This is what you might call a “flaky test”: a test that doesn’t work reliably, depending on the current situation. The app being tested might be coded perfectly, but the test itself isn’t resilient to variance in performance. Your app and tests need to be coded to expect delays.

如果登录过程很快,这种事情就很好用。 但是,如果登录发生得比预期的慢,可能是由于网络或磁盘访问所致,则测试可能无法找到欢迎消息。 这就是所谓的“不稳定测试”:根据当前情况,该测试无法可靠地运行。 被测试的应用程序可能被完美地编码,但是测试本身不能适应性能的变化。 您的应用和测试需要进行编码,以防延迟。

Nearly all Android applications today work with some data requested over the network. If not that, certainly data is stored in a local database, using libraries such as Jetpack Room. When an app works with data that requires some I/O, the user doesn’t get a guarantee for how long it’s going to take. We just can’t be certain about the speed of all the networks, CPUs, and filesystems involved. As such, your UI test code also shouldn’t make any assumptions, and instead, should anticipate delays in the execution of the app.

如今,几乎所有的Android应用程序都可以处理通过网络请求的某些数据。 如果不是那样,则可以肯定地使用Jetpack Room之类的库将数据存储在本地数据库中。 当应用处理需要一些I / O的数据时,用户将无法保证需要花费多长时间。 我们只是不确定所涉及的所有网络,CPU和文件系统的速度。 因此,您的UI测试代码也不应做任何假设,而应预期应用程序执行的延迟。

One immediate solution to this might be to make the test wait at the point of the delay to allow time for it to complete:

对此的一种直接解决方案可能是使测试在延迟点等待,以便有时间完成它:

// Give the welcome message a moment to appear
// (BUT DON'T DO THIS!)
Thread.sleep(2000)// Check to make sure a welcome message is visible
onView(ViewMatchers.withId(R.id.welcome)).check(matches(isDisplayed()))

While this might work most of the time, it’s still not guaranteed to work all of the time. What if your network or login system are experiencing slowness? You could always bump up the sleep time, but that just makes your test that much longer to complete in normal conditions. Forcing a wait time like this can have a huge impact on the total time it takes to run your test suite — don’t do this!

尽管这可能在大多数时间都有效,但仍不能保证它一直都有效 。 如果您的网络或登录系统运行缓慢,该怎么办? 您总是可以增加睡眠时间,但这只会使您的测试花费更长的时间才能在正常条件下完成。 强制这样的等待时间会对运行测试套件所需的总时间产生巨大影响,请不要这样做!

Instead, it might be tempting to check periodically if the welcome message becomes visible. This could be done by putting a loop around the check, and ignoring the exceptions thrown when the view isn’t visible yet:

相反,可能很想定期检查欢迎消息是否可见。 这可以通过在检查周围放置一个循环,并忽略在视图不可见时引发的异常来完成:

var found = false
while (!found) {try {onView(ViewMatchers.withId(R.id.welcome)).check(matches(isDisplayed()))found = true// When does this loop time out?// Does it affect the overall test performance?}catch (_: Exception) {// Execution goes here if the view isn't found}
}

Yes, that code is just as ugly as it looks. Don’t do this either. While it might find the view as soon as it becomes visible, it’s also chewing up CPU time on the device where it’s running, which could make the app run slower while it’s under test. This code also doesn’t have a sense of timeout, so if there’s an error, it won’t know when to terminate. You’d have to add more lines to make sure this looping only goes on for so long. Yuck. Fortunately, there’s a way out.

是的,该代码看起来很难看。 也不要这样做。 尽管它可能会在视图一出现就立即找到视图,但它也会减少正在运行的设备上的CPU时间,这可能会使应用在测试过程中的运行速度变慢。 该代码也没有超时感,因此,如果有错误,它将不知道何时终止。 您必须添加更多行,以确保此循环仅持续这么长时间。 uck 幸运的是,有一条出路。

请改用Espresso IdlingResource (Use an Espresso IdlingResource instead)

A better way to handle this is using an Espresso IdlingResource. An IdlingResource is an object that lets your app code tell your test code when the app is busy with some background work, so that the test code waits until that work completes. It’s pretty easy to understand, but has some challenges to implement. In general, it works like this (I’ll use “IR” as shorthand for IdlingResource in this post):

解决此问题的更好方法是使用Espresso IdlingResource 。 IdlingResource是一个对象,可让您的应用程序代码在应用程序忙于某些后台工作时告诉您的测试代码,以便测试代码等待该工作完成。 这是很容易理解的,但是要实现它会遇到一些挑战。 通常,它的工作方式如下(在这篇文章中,我将使用“ IR”作为IdlingResource的简写):

  1. The app exposes an IR to the test code via the activity under test.该应用通过被测活动向测试代码公开IR。
  2. The test registers the IR and pays attention to its state changes.该测试会注册IR,并注意其状态变化。
  3. The app indicates to the IR when it’s occupied with work (e.g. making a network request, or loading data)该应用程序会在IR忙碌时向IR指示(例如,发出网络请求或加载数据)
  4. The test pauses when the IR is “busy” and resumes when the IR is “complete”.当IR“忙”时,测试暂停;当IR“完成”时,测试恢复。
  5. The test unregisters the IR just after the test is complete测试完成后,测试将注销IR

Basically, the IdlingResource is a way for the app to tell the test that it’s busy with some asynchronous work, then again when that work is complete. This lets the test wait for the app to finish any background work, avoiding the need to code a sleep or a loop that can waste time and make your test difficult to understand.

基本上,IdlingResource是应用程序告知测试正在忙于某些异步工作的一种方法,然后在工作完成时再次进行测试。 这样一来,测试就可以等待应用程序完成所有后台工作,而无需编写睡眠或循环代码,而这可能会浪费时间并使测试难以理解。

The tricky part is getting that IR from your app code into the test. The Espresso documentation on IR gives you some options. The recommended approach is to have your Activity expose the object directly to your tests.

棘手的部分是将IR从您的应用程序代码导入到测试中。 IR上的Espresso 文档为您提供了一些选择。 推荐的方法是让您的Activity将对象直接暴露给测试。

If your test is working with an Activity object directly, and it exposes an IR directly from a property, test code starts to look something like this:

如果您的测试直接使用Activity对象,并且直接从属性公开IR,则测试代码开始看起来像这样:

@RunWith(AndroidJUnit4::class)
class MainActivityTest {@get:Ruleval activityRule = ActivityTestRule(MainActivity::class.java)private lateinit var signInIdlingResource: IdlingResource@Beforefun setUp() {val activity = activityRule.activity as MainActivity// Get the IdlingResource directly from the activitysignInIdlingResource = activity.signInIdlingResourceIdlingRegistry.getInstance().register(signInIdlingResource)}@Afterfun tearDown() {IdlingRegistry.getInstance().unregister(signInIdlingResource)}@Testfun testSignIn() {// The test code is unchanged - it will pause automatically// if the IdlingResource says there is ongoing workonView(ViewMatchers.withId(R.id.email)).perform(typeText("foo@bar.com"), closeSoftKeyboard())onView(ViewMatchers.withId(R.id.password)).perform(typeText("dontsharethis"), closeSoftKeyboard())onView(ViewMatchers.withId(R.id.btnSignIn)).perform(click())onView(ViewMatchers.withId(R.id.welcome)).check(matches(isDisplayed()))}}

You can see above that the @Test method is unchanged. However, @Before the test executes, the code will get a hold of the Activity being tested, cast it to the expected type, and reach into it to get the IR. The IR is registered with Espresso. @After the test is over, it’s unregistered. There is nothing else to be done here — the test will automatically pause when the IR indicates that the Activity is busy, then immediately resume when it’s idle. All that remains is using the IR correctly in the app’s code to indicate status. Here’s how.

您可以在上面看到@Test方法未更改。 但是, @Before测试执行之前,代码将保留正在测试的Activity,将其@Before转换为预期的类型,然后进入其中以获取IR。 IR已在Espresso中注册。 @After测试结束后,它尚未注册。 此处无需执行其他操作-当IR指示Activity繁忙时,测试将自动暂停,然后在空闲时立即恢复。 剩下的一切都是在应用程序代码中正确使用IR来指示状态。 这是如何做。

您可以依靠CountingIdlingResource (You can count on CountingIdlingResource)

Espresso provides some implementations of IdlingResource. The most common is CountingIdlingResource, and others are derived from it. The way it works is pretty straightforward. It’s governed by these rules:

Espresso提供了IdlingResource的一些实现 。 最常见的是CountingIdlingResource ,其他派生自其。 它的工作方式非常简单。 它受以下规则支配:

  • It starts with an initial “count” of 0, the number of ongoing background tasks.它以初始“计数” 0(正在进行的后台任务的数量)开始。
  • App code can increment or decrement the count to indicate when a task starts or stops.应用程序代码可以增加或减少计数,以指示任务何时开始或停止。
  • A count of 0 means the app is “idle” — no work is ongoing.计数为0表示应用程序处于“空闲”状态-正在进行任何工作。
  • Anything greater than 0 means the app is “busy”.大于0的值表示应用程序“忙”。

What you can do is create an instance of CountingIdlingResource, expose it to the test through your Activity object, and work with it in your code. It sounds simple, but requires some architectural planning to make this work well. If you’re using MVVM, an easy place to work with an IR is in your ViewModel, which manages the calls to your repository objects that are doing the actual work.

您可以做的是创建一个CountingIdlingResource实例,通过Activity对象将其公开给测试,然后在代码中使用它。 听起来很简单,但是需要一些体系结构计划才能使其正常工作。 如果您使用的是MVVM,则在ViewModel中可以轻松使用IR,它可以管理对正在执行实际工作的存储库对象的调用。

This can get complicated, and there are a lot of ways to do this. As a super brief example using Kotlin coroutines and LiveData, say you have a ViewModel that signs in the user using a suspending function on a repository, and returns a LiveData to the UI layer:

这可能会变得很复杂,并且有很多方法可以做到这一点。 作为使用Kotlin协程和LiveData的简短示例,假设您有一个ViewModel,该ViewModel使用存储库上的挂起函数登录用户,并将LiveData返回到UI层:

class MyViewModel : ViewModel() {@VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)val signInIdlingResource = CountingIdlingResource("signIn")fun onClickSignIn(): LiveData<SignInResult> {signInIdlingResource.increment()return liveData(viewModelScope.coroutineContext) {try {val result = repository.suspendingSignIn(email, password)emit(SignInSuccess(result))}catch (e: Exception) {emit(SignInError("Sign-in failed"))}finally {signInIdlingResource.decrement()}}}}

Some details are omitted for brevity, but you can see here that:

为了简洁起见,省略了一些细节,但是您可以在此处看到:

  • A CountingIdlingResource is created, named, and made available to the UI layer by a public property通过公共属性创建,命名CountingIdlingResource并将其提供给UI层
  • The IR is used to indicate when the sign-in process is initially busy by incrementing itIR用于通过递增登录时间来指示登录过程最初何时处于繁忙状态
  • The IR is then marked complete by decrementing it, even if an error occurs然后,即使发生错误,也可以通过递减将IR标记为完成。

The UI layer (Activity) can then reach into the ViewModel to get the IR, then pass it along to the test using another public property.

然后,UI层(Activity)可以进入ViewModel以获取IR,然后使用另一个公共属性将其传递给测试。

(For very clean architecture, you might want to inject the responsibility of working with IdlingResources instead, from the test code itself.)

(对于非常干净的体系结构,您可能希望从测试代码本身注入使用IdlingResources的责任。)

By default, Espresso will wait 1 minute for an IdlingResource to transition to an idle state before timing out the test, which might not be what you want. If that’s too long, you could waste time on a test that’s expected to fail faster. Or, if it’s too short, your test could become flaky. To change the default, you should set the timeout @Before your test starts using IdlingPolicies:

默认情况下,Espresso将等待1分钟,以使IdlingResource过渡到空闲状态,然后再暂停测试,这可能不是您想要的。 如果时间太长,您可能会浪费时间进行预期会更快失败的测试。 或者,如果时间太短,则测试可能会变得不稳定。 要更改默认的,你应该设置超时@Before测试开始使用IdlingPolicies :

IdlingPolicies.setMasterPolicyTimeout(10, TimeUnit.SECONDS)IdlingPolicies.setIdlingResourceTimeout(10, TimeUnit.SECONDS)

如果您喜欢IdlingResource,也可以尝试BusyBee (If you like IdlingResource, also try BusyBee)

One last thing. If you make heavy use of IdlingResource, you’ll find that becomes more difficult to use as your app has more complicated tasks to perform. Consider replacing them with BusyBee, developed by Michael Bailey at American Express. This utility makes it easier for you to group and debug your tasks. It can also be used outside of Android modules. Maybe best of all, it uses a singleton to share IdlingResources with Espresso, eliminating the need for your test to reach into an activity to find their instances.

最后一件事。 如果您大量使用IdlingResource,您会发现使用它变得更加困难,因为您的应用程序要执行更复杂的任务。 考虑用American Express的Michael Bailey开发的BusyBee代替它们。 该实用程序使您可以更轻松地对任务进行分组和调试。 它也可以在Android模块之外使用。 也许最好的办法是,它使用单例与Espresso共享IdlingResources,从而无需进行测试即可进入活动以查找其实例。

Whether you use IdlingResource or BusyBee, your tests should always expect delays, but minimize the amount of time spent waiting. It takes some engineering work to instrument the app, but it’s worth it.

不管您使用IdlingResource还是BusyBee,您的测试都应该始终期待延迟,但是要尽量减少等待时间。 进行应用程序检测需要一些工程工作,但值得。

有关在Android上进行更快的测试的更多文章 (More articles on faster testing on Android)

  • Reconsider the Android emulator for faster testing

    重新考虑Android模拟器以进行更快的测试

  • Accelerate your Android Espresso testing by grouping relevant tests

    通过对相关测试进行分组来加速您的Android Espresso测试

  • Shard your Android Espresso tests for faster execution in parallel

    分割您的Android Espresso测试,以加快并行执行速度

翻译自: https://medium.com/mesmerhq/use-espressos-idlingresource-for-max-android-test-speed-f2305b28b214


http://www.taodudu.cc/news/show-4197554.html

相关文章:

  • Espresso Idling Resource
  • android espresso跨程序,在Espresso Android中正确使用IdlingResource的方法
  • revit二次开发 IdlingExternalEvent 空闲事件与外部事件
  • 并行与分布式计算导论(六)MPI入门
  • 动态路由和tab页切换路由
  • layui自定义新增tab页方法
  • layui关闭当前tab页
  • vue关闭tab页
  • vue 前端进行tab页面切换时,要求不刷新
  • vue js监听浏览器tab页切换
  • Tab页的两种写法 - jeesite记录
  • Tab页面知识整理及其方法分析
  • vue tab页面缓存处理
  • js 跨浏览器tab页通信
  • HTML:tab页签
  • 多个tab页如何共享websocket
  • js监听浏览器tab页面变化
  • 按钮如何控制tab页面跳转
  • easyUI打开tab页面
  • Vue+Element实现tab页多页面切换
  • vue点tab不刷新页面_如何使tab页切换,页面不刷新
  • 【Vue实用功能】Vue实现tab页多页面切换
  • html的tab页面切换刷新,切换tab页,页面局部刷新,地址栏路径修改
  • spa项目开发之vue+elementUi实现tab页
  • 用纯css实现优雅的tab页,纯CSS实现Tab页切换效果的方法
  • 不同tab页sessionStorage共享情况
  • html 关闭当前tab页面,js关闭浏览器的tab页(兼容)
  • 左耳朵耗子:我做系统架构的一些原则
  • git项目拉下来之后无法找到主加载类
  • 计算机学习书籍

使用espressos idlingresource获得最高的Android测试速度相关推荐

  1. 5个最佳的Android测试框架

    2019独角兽企业重金招聘Python工程师标准>>> 谷歌的Android生态系统正在不断地迅速扩张.有证据表明,新的移动OEM正在攻陷世界的每一个角落,不同的屏幕尺寸.ROM / ...

  2. Android测试原理(三)——使用Eclipse的ADT进行测试

    原文链接:http://developer.android.com/tools/testing/testing_eclipse.html 1.使用Eclipse的ADT进行测试 这次的主题介绍了怎么使 ...

  3. Android测试原理(二)

    2.3.  The Testing API(测试API) Android的测试API是基于JUnitAPI和扩展的instrumentation 框架以及特定的Android测试类.          ...

  4. Android测试原理概述(一)

    翻译来源:http://developer.android.com/tools/testing/testing_android.html 1.   Testing http://developer.a ...

  5. 【Android测试】【第二节】Monkey工具

    最近开始研究Android测试的Monkey工具,因接触时间很短,还有很多不足之处,希望能和大家多多交流. ● 什么是Monkey Monkey是Android中的一个命令行工具,可以运行在模拟器里或 ...

  6. Android测试环境配置

    测试是软件开发中非常重要的一部分,Android中是使用junit测试框架,本文使用的是junit4和Android Studio.Android测试主要分两类本地测试和Instrumented测试, ...

  7. 1、Android测试入门

    编写和运行测试时Android APP开发周期中的重要的一环.好的测试可以让你非常容易的在开发过程中发现bug,提升你对自己代码的自信.使用Android Studio,你可以在物理设备或者虚拟机中运 ...

  8. Android 测试教程

    Android 测试教程:http://wiki.jikexueyuan.com/project/android-test-course/ 每个开发者都应该懂一点单元测试 一.什么是单元测试? 为了测 ...

  9. android 测试工程 关闭混淆,混淆Android Test项目以及项目(在发布和混淆版本上运行测试)...

    在阅读赏金的评论之后,我意识到OP实际上只是提出了一些简单的是/否回复,所以我将把我的评论扩展到答案.一般来说,正确设计的proguard.cfg和项目结构足以防止这种困境. 典型的proguard配 ...

最新文章

  1. 修改 mysql 支持远程连接
  2. 安装nginx0.7x+php5.2.8(Fastcgi)小结
  3. 网络爬虫-爬取微博热门话题前15个
  4. AR独角兽的死亡教训:融资3亿美元后,成投资人提线木偶,营销大于产品技术...
  5. 开发:随笔记录之 Json字符串和对象的相互转换
  6. 2.4 万余门在线课程免费开放!大量计算机相关课程.(赶紧收藏)
  7. 磁盘剩余空间策略_MySQL磁盘消耗迅猛掌握这点就够了,包你事半功倍
  8. linux内核优化策略,linux系统调优小结
  9. java 进度条_进度条Java
  10. qt 的mysql的库
  11. 数据科学 IPython 笔记本 8.9 自定义图例
  12. PHPWAMP集成环境配置ssl证书
  13. java 无锁并发_高并发情况下怎样尽量实现无锁编程
  14. 计算机查找的快捷键是,电脑快捷键快速查找
  15. 自己封装工具类Jar包
  16. 高中数学一轮复习逆袭必要学习方法
  17. startx 命令_通过startx从命令行启动KDE
  18. 中国男人配不上中国女人?
  19. Ruoyi的功能简单介绍
  20. 基于VNPY实现网格策略实盘(币圈)

热门文章

  1. 【iOS开发】从小白到低水平开发者进厂实习自救指南
  2. Wifi网络共享----Win8内置承载网络
  3. 第四章:jQuery动画
  4. ElasticSearch健康检查localhost:9200 not reachable
  5. 电商新趋势来临!?解析Dtop 环球嘉年华电商是否值得加入!
  6. 笔记本(win10、win7)开机在LOGO过后出现闪屏几下才进入系统成功解决问题步骤分享
  7. Vue制作图片翻面效果
  8. fatal: the remote end hung up unexpectedly问题解决办法
  9. OpenJDK源码赏析之三:Java命令参数的读取处理流程
  10. 在电脑上安装Linux系统步骤