中文翻译版:

为了使大家确信“应做单元测试,就一定能做单元测试”,谷歌测试工程师Mona El Mahdy专门写了一篇博客,提出了几种执行安卓应用用户界面单元测试的方法。Mahdy推荐使用 Robolectric和Android Studio Gradle插件做常规的单元测试,用 Espresso 或 UI Automator 创建和运行单元测试。

端到端的测试。Mahdy提出的第一种UI测试方法是E2E。这样的测试应该可以启动安卓应用及其所有与之相关的后端系统,使之可以在真实的场景中完成UI测试。重复执行这些的测试是很困难的,因为“存在很多的影响因素,比如网络带宽、实际服务器的认证、系统规模等”,所以就很难做到“E2E测试的调试排查和稳定化处理”。为简化这些点,Mahdy也提出了一些其他的测试策略。

用隔离的服务器测试。隔离的服务器是指与外界隔离的服务器,是在本地运行的一台单独的服务器,不连接网络。在运行的时间通过依赖注入(可能需要绑定到这台服务器的静态文件)的方式提供与其他服务器的连接,如果需要的话,还可以在本地文件或内存存储中伪造一些响应数据。另一个选择是,为隔离的服务器提供一系列记录好的响应,以模拟真实终端服务器的返回值。

针对测试目的,隔离的服务器作为被测系统在同一台机器上本地运行,其上运行安卓模拟器。虽然这种方式提高了测试的执行速度,有时也会消除一些网络连接的碎片,但是它需要单独的集成测试以确保客户端应用与后端是同步的。出于这个目的,Google+团队用了一组“黄金的”需求/响应文件,大家都知道它们包含了客户端应用到终端服务器的正确的传输序列。用黄金的需求文件根据这台服务器的所有响应生成一个文件,然后再用这个文件与黄金的响应文件进行比较。

Mahdy提出,使用隔离的服务器比E2E测试可以更好地完成测试,但是调试却仍旧是个难题,而且这台隔离的服务器可能会导致一些通讯碎片。所以,她提出了另一个改进方案。

使用依赖注入(DI)。移动应用可以设计成支持依赖注入的,在测试期间有些模块可以用仿造模块代替。应用将和仿造的网络模块进行通讯,这个网络模块为所有请求提供应答,以取代刚才所讲的使用网络模块的隔离的服务器。这会使UI测试更快更可靠。在DI这一方面,Mahdy建议使用Dagger。

多重类库。如果安卓应用比较大,Mahdy建议把它分割成更多小的组件,每个和它自己的模块和视图把包到一个单独的类库中。然后,你们就可以使用单独的DI、模拟模块和测试进行每个组件的开发和测试了。为确保整个应用的运转,需要集成的测试。这一方式更是进一步提升了测试的速度。

最后,Mahdy总结道:“组件化的UI测试要比E2E测试快得多,并具备99%的稳定性。快速而稳定的测试从根本上提升了开发人员的生产效率。”

英文原文版:

Convinced that “whatever can be unit tested should be unit tested”, Mona El Mahdy, a Software Engineer in Test at Google, has written a blog post proposing several approaches to perform unit tests on the user interface of Android applications. Mahdy recommends Robolectric and the Android Studio Gradle plug-in for general unit testing, and Espresso or UI Automator for creating and running UI tests.

End-to-End (E2E) Tests. The first approach to UI testing mentioned by Mahdy is E2E. Such a test should be able to fire up the Android application and all its related back-end systems, enabling the UI testing in real life scenarios. Repeatedly performing such tests is difficult because “debugging and stabilizing E2E tests” is hard due to “many variables like network flakiness, authentication against real servers, size of your system, etc.” To simplify things a bit, Mahdy proposes another strategy for testing.

Testing using Hermetic Servers. Hermetic servers are servers that are isolated from the outside world, running locally on a single machine without network connections. Connections to other servers are provided at runtime through dependency injection, any static files that might be requested are bundled with the server, and, if necessary, responses to data store requests are faked with data from local files or an in-memory store. Another option is for a hermetic server to provide a sequence of responses recorded when returned by a real back-end server.

For testing purposes, hermetic servers run locally on the same machine as the System Under Test (SUT) where the Android emulator runs. While this approach speeds up test runs and eliminates flakiness sometimes associated with network connections, it requires separate integration testing to make sure the client app is in sync with the back-end. For this purpose, the Google+ team uses a pair of “golden” request/response files that are known to contain a correct sequence of transmissions between a client app and a back-end server. The golden request file is played and a file is created with all the responses coming from the server, being later compared with the golden response file.

Mahdy argues that using hermetic servers is better for testing than E2E tests, but debugging is still not easy and the hermetic server may cause some flakiness in communication. So, she proposes another improvement.

Using Dependency Injection (DI). The mobile application can be designed for using DI having some modules replaced with faked ones during testing. Instead of talking to a hermetic server through a network module, the app will communicate with a fake network module which provides answers to all requests. This makes UI tests even faster and reliable. For DI, Mahdy suggests using Dagger.

Multiple Libraries. When an Android application is larger Mahdy suggest splitting it up into smaller components each with its own module and view packaged in a separate library. Then, each component can be developed and tested using separate DI, fake modules and tests. Integration tests are necessary to make sure the entire app works. This approach speeds up testing even further.

At the end, Mahdy concludes: “Componentized UI tests have proven to be much faster than E2E and 99%+ stable. Fast and stable tests have proven to drastically improve developer productivity.”

谷歌安卓UI自动化测试策略的更多相关文章

  1. uiautomator +python 安卓UI自动化尝试

    使用方法基本说明:https://www.cnblogs.com/mliangchen/p/5114149.html,https://blog.csdn.net/Eugene_3972/article ...

  2. Android_UiAutomator(安卓UI自动化)环境搭建

    一.配置JDK环境变量 1.新建系统变量JAVA_HOME,然后输入引号内的内容(JDK安装目录) "C:\Program Files\Java\jdk1.8.0_51"      ...

  3. UI自动化测试、接口测试等自动化测试策略

    今天跟大家介绍UI测试.接口测试.单元测试主要内容,以及每种测试花费时间讨论.UI测试[Selenium]UI测试是最接近软件真实用户使用行为的测试类型.通常是模拟真实用户使用软件的行为,即模拟用户在 ...

  4. 【Android测试】UI自动化代码优化之路(临时发布, 随时删除)

    ◆版权声明:本文出自胖喵~的博客,转载必须注明出处. 转载请注明出处:http://www.cnblogs.com/by-dream/p/5993622.html 关于UI自动化的抱怨 听过不少人这样 ...

  5. 手机APP自动化之uiautomator2 +python3 UI自动化

    题记: 之前一直用APPium直到用安卓9.0  发现uiautomatorviewer不支持安卓 9.0,点击截屏按钮 一直报错,百度很久解决方法都不可以,偶然间看见有人推荐:uiautomator ...

  6. Airtest 网易 UI 自动化工具 Airtest 浅用记录

    一 使用目的 该工具主要是面向游戏UI测试基于图像识别,如游戏框架unity,Cocos-js以及网易内部的游戏框架同时也支持原生Android App 的基于元素识别的UI自动化测试.本文主要使用目 ...

  7. UI自动化的痛点

    解决UI自动化难点痛点: 解决从安装过程中跳出的提示框以及操作过程中任意提示框的操作,来提高用例成功率: 公用用例及业务用例分离,便于维护和多人使用,提高脚本编写效率: 解决用android wind ...

  8. 【Android测试】UI自动化代码优化之路

    ◆版权声明:本文出自胖喵~的博客,转载必须注明出处. 转载请注明出处:http://www.cnblogs.com/by-dream/p/5993622.html 关于UI自动化的抱怨 听过不少人这样 ...

  9. 网易 UI 自动化工具 Airtest 浅用记录

    一 使用目的 该工具主要是面向游戏UI测试基于图像识别,如游戏框架unity,Cocos-js以及网易内部的游戏框架 同时也支持原生Android App 的基于元素识别的UI自动化测试. 本文主要使 ...

随机推荐

  1. 原生js获取屏幕的宽高

    function client(){ if(window.innerHeight !== undefined){ return { "width": window.innerWid ...

  2. 单位转换类UnitUtil2

    package com.jlb.scan.util; import java.math.BigDecimal; import java.text.DecimalFormat; import com.j ...

  3. roadhogrc.mock.js配置

    1.roadhogrc.mock.js const fs=require('fs'); const path=require('path'); const mockPath=path.join(__d ...

  4. flume 使用

    基本操作: 编写配置文件: # 指定Agent的组件名称 a1.sources = r1 a1.sinks = k1 a1.channels = c1 # 指定Flume source(要监听的路径) ...

  5. springBoot Ribbon Hystrix

    1.依赖包引入 <!-- 引入关于 hystrix的依赖 --> <dependency> <groupId>org.springframework.cloud&l ...

  6. [BZOJ1054][HAOI2008]移动玩具 bfs+hash

    1054: [HAOI2008]移动玩具 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 2432  Solved: 1355[Submit][Stat ...

  7. AC日记——Paint Pearls hdu 5009

    Paint Pearls 思路: 离散化+dp+剪枝: dp是个n方的做法: 重要就在剪枝: 如果一个长度为n的区间,有大于根号n种颜色,还不如一个一个涂: 来,上代码: #include <c ...

  8. AC日记——奶牛集会 洛谷 P2345

    奶牛集会 思路: 把奶牛按照v排序: 然后,每次都把奶牛放入一个集合s: 因为奶牛已经排序: 所以,每次第i次放入奶牛起作用的v就是vi: 每次ans+=(xi*sum-sumxl)*vi+(sumx ...

  9. (转)Ubuntu安装g++-4.8

    sudo add-apt-repository ppa:ubuntu-toolchain-r/test sudo apt-get update sudo apt-get install g++-4.8 ...

  10. (12)C#枚举,结构

    枚举 枚举类型是类似自定义的一个类,类里放着你自己定义的常量,关键字enum. enum Season{spring,summer,fall,winter} 想用这里的常量的话,首先把变量定义成 Se ...