空闲资源表示其结果会影响其结果的异步操作 界面测试中的后续操作。通过将空闲资源注册到 Espresso 进行编程时,您可以更可靠地验证这些异步操作, 测试您的应用
确定何时需要空闲资源
Espresso 提供了一套先进的
同步功能。这个
而这一框架的特色仅应用于
MessageQueue
上的消息,例如
在屏幕上绘制其内容的 View
。
因为 Espresso 不知道任何其他异步操作,包括 那些在后台线程上运行的应用,Espresso 无法提供其同步 提供保证。为了让 Espresso 知道应用的 长时间运行的操作,您必须将每个操作注册为空闲资源。
如果您在测试应用的结果时不使用空闲资源, 异步工作,您可能会发现自己必须使用 来改进测试可靠性:
- 添加对
Thread.sleep()
的调用。当您 人为增加测试延迟,那么测试套件所需的时间 有时,测试在执行时仍可能会失败 运行速度较慢的设备此外,这些延迟并不能很好地进行调整,因为您的应用可能 必须在未来的版本中执行更耗时的异步工作。 - 实现重试封装容器,使用循环来反复检查 您的应用仍在执行异步工作,直到发生超时。即使 您在测试中指定重试次数上限,每次重新执行都会消耗 尤其是 CPU
- 使用
CountDownLatch
的实例, 允许一个或多个线程等待特定数量的操作 在另一个线程中执行的所有操作都已完成这些对象要求您指定 超时时长;否则,您的应用可能会被无限期屏蔽。开关 还会给代码增加不必要的复杂性,使维护更加困难。
Espresso 可让您从测试中移除这些不可靠的解决方法, 而是将应用的异步工作注册为空闲资源。
常见用例
在测试中执行与以下示例类似的操作时, 可以考虑使用空闲资源:
- 从互联网或本地数据源加载数据。
- 与数据库和回调建立连接。
- 管理服务(使用系统服务或
IntentService
。 - 执行复杂的业务逻辑,如位图转换。
在执行这些操作时注册空闲资源 更新测试随后会验证的界面。
空闲资源实现示例
以下列表介绍了空闲资源的几个实现示例 您可以集成到应用中:
CountingIdlingResource
- 维护活动任务的计数器。当计数器为零时,相关联的
视为空闲资源该功能与
Semaphore
。在大多数情况下,这种实现方式 以便在测试期间管理应用的异步工作。 UriIdlingResource
- 类似于
CountingIdlingResource
, 但计数器必须在特定时间段内为零,才能 视为空闲资源这一额外的等待期将连续 而线程中的应用可能会发出新的 。 IdlingThreadPoolExecutor
ThreadPoolExecutor
的自定义实现 用于跟踪所创建的线程中正在运行的任务总数 资源池。此类使用CountingIdlingResource
至 维护活跃任务的计数器。IdlingScheduledThreadPoolExecutor
- 自定义实现
ScheduledThreadPoolExecutor
。它提供 Google Cloud 的IdlingThreadPoolExecutor
类,但它也可以跟踪为将来安排的任务, 定期执行 。
创建您自己的空闲资源
当您在应用的测试中使用空闲资源时,您可能需要提供 自定义资源管理或日志记录在这些情况下, 可能不够。如果是这种情况,您可以 扩展其中一个空闲资源实现或创建自己的空闲资源实现。
如果您实现自己的空闲资源功能,请始终遵循以下最佳做法, 特别是第一种:
- 在空闲检查之外调用转换到空闲状态。
- 在应用进入空闲状态后,
onTransitionToIdle()
任何isIdleNow()
。这样, Espresso 不会进行第二个不必要的检查来确定给定的 空闲资源处于空闲状态。
以下代码段说明了此建议:
Kotlin
fun isIdle() { // DON'T call callback.onTransitionToIdle() here! } fun backgroundWorkDone() { // Background work finished. callback.onTransitionToIdle() // Good. Tells Espresso that the app is idle. // Don't do any post-processing work beyond this point. Espresso now // considers your app to be idle and moves on to the next test action. }
Java
public void isIdle() { // DON'T call callback.onTransitionToIdle() here! } public void backgroundWorkDone() { // Background work finished. callback.onTransitionToIdle() // Good. Tells Espresso that the app is idle. // Don't do any post-processing work beyond this point. Espresso now // considers your app to be idle and moves on to the next test action. }
- 在需要之前注册空闲资源。
与空闲资源关联的同步优势仅生效 在 Espresso 首次调用该资源的
isIdleNow()
方法。以下列表显示了此属性的几个示例:
- 如果您在带有
@Before
注解的方法中注册了空闲资源, 空闲资源会在每个测试的第一行生效。 - 如果您在测试中注册了空闲资源,该空闲资源 在下一项基于 Espresso 的操作期间生效。这种行为仍然 即使下一项操作与执行测试的语句在同一测试中, 注册空闲资源。
- 如果您在带有
- 使用完空闲资源后将其取消注册。
为节约系统资源,您应该尽快取消注册空闲资源 因为您不再需要它们例如,如果您注册了空闲资源 则最好在带有
@Before
注解的方法中取消注册此资源, 相应的方法(带有@After
注解)。- 使用空闲资源注册表来注册和取消注册空闲资源。
通过使用此容器存储应用的空闲资源,您可以注册和 根据需要反复取消注册空闲资源,并且仍会观察到一致 行为
- 在空闲资源内仅维护简单的应用状态。
例如,您实现和注册的空闲资源不应 包含对
View
对象的引用。
注册空闲资源
Espresso 提供了一个容器类,您可以将应用的空闲状态置于其中
资源。此类称为
IdlingRegistry
是
给应用带来的开销极低的独立工件。类
还可以让您采取以下措施来改进
可维护性:
- 创建对
IdlingRegistry
(而不是空闲资源)的引用 。 - 保持用于以下用途的空闲资源集合中的差异 每个 build 变体。
- 在应用的服务中定义空闲资源,而不是在界面中定义 引用这些服务的组件
将空闲资源集成到应用中
尽管您可以通过多种不同的方式向应用添加空闲资源, 具体做法是,该方法会为您的应用维护封装,同时仍允许 您可以指定给定空闲资源表示的特定操作。
建议的方法
向应用添加空闲资源时,我们强烈建议您将空闲资源 应用本身中存在空闲资源逻辑,并且仅执行注册和 取消注册操作。
虽然您在 Google Cloud 中 将空闲资源封装在 代码,从而保持应用的 APK 大小和方法计数。
替代方法
如果您不希望应用的正式版中有空闲资源逻辑 代码,还有其他几种可行的集成策略:
- 创建 build 变体,如 Gradle 的 build 变体 产品 变种,并且仅在应用的调试 build 中使用空闲资源。
- 使用依赖项注入框架(如 Dagger)注入应用的空闲状态 资源依赖关系图添加到您的测试中。如果您使用的是 Dagger 2,则 注入本身应源自子组件。
在应用的测试中实现空闲资源,并公开该部分 需要同步的 测试。
注意 :尽管此设计决策似乎 创建对空闲资源的独立引用,也会破坏 封装在除最简单的应用之外的所有应用中。
其他资源
如需详细了解如何在 Android 测试中使用 Espresso,请查阅 以下资源。
示例
- IdlingResourceSample: 与后台作业同步。