[译] 使用 Espresso 隔离测试视图

本文讲的是[译] 使用 Espresso 隔离测试视图,

使用 Espresso 隔离测试视图

在这篇文章里,我将会告诉你为何并且如何使用 Espresso 在 Android 设备上测试你的自定义视图。

你可以使用 Espresso 来一次性测试所有界面或流程。这些测试用例会启动某个页面,并像用户一般执行操作,包括等待数据的加载或跳转到其他页面。

这样做是非常有用的,因为你需要端到端的测试用例来验证常见的用户使用流程。这些自动化测试应该定期地执行,从而可以节约手工 QA 的时间来进行探索性测试。

即便如此,这些不是可以频繁运行的测试。运行一整套可能会花费数小时的时间(想象一下验证媒体内容的脱机同步),所以你可以选择在夜间运行它们。

这很困难,因为这些类型的测试包含了多个潜在的故障点。理想情况是,当某个测试失败时,你会希望它是由于单个逻辑断言而导致的。

大多数(或者说很多)可以引入的回归测试点都在 UI 上。这些问题很可能是十分细微的,以至于我们在添加新特性时并不会注意到,但是敏锐的 QA 团队却往往可以。

这样就浪费太多时间了。

你能做些什么?

让我们来看下如何使用 Espresso 来测试正确地绑定了数据的视图。

在 Novoda 里,我们编写的大多数视图都是继承自 Android 已有的 View 和 ViewGroup 类。这些视图一般只会暴露了一到两个方法用来绑定回调函数和数据对象/视图模型,如下所示:

public class MovieItemView extends RelativeLayout {
  private TextView titleTextView;
  private Callback callback;

  public void attach(Callback callback) {
    this.callback = callback;
  }

  public void bind(Movie movie) {
    titleTextView.setText(movie.name());
    setOnClickListener(new OnClickListener() {
      @Override
      public void onClick(View v) {
        callback.onClick(movie);
      }
    });
  }
}

他们将 UI 的逻辑部分组合在一起,并且通常还包含来自业务领域的命名规范。在
Novoda 的页面布局中你很少会看到“原始”的 Android 视图。

让我们使用 BDD 风格来编写这些视图测试,比如“当 MovieItemView 被绑定到 Edward Scissorhands 上,标题就被设置成 Edward Scissorhands”或者“MovieItemView 被绑定到 Edward Scissorhands 上,当点击视图时,onClick(Edward Scissorhands) 就会被调用”,等等。(译者注:BDD(Behaviour Driven Development),倾向于断言被测对象的行为特征而非输入输出。一个典型的 BDD 的测试用例包活完整的三段式上下文,测试大多可以翻译为Given-When-Then 的格式,即某种场景下,发生了事件,导致了什么结果。)

难道不能使用单元测试来捕获这些问题吗?

如果你正在使用像 MVP 或者 MVVM 这样可被单元测试的表现模式,为什么还需要 Espresso 来运行这些测试呢?

首先,让我们来看一下展示信息的流程并且描述一下目前所能做的测试,然后再看看使用 Espresso 测试能多做些什么。

  • Presenters 订阅发送事件的数据生成器
  • 事件可以处于加载中空闲错误状态,并且可能带有要展示的数据
  • Presenters 将使用 display(List<Movie>)displayCachedDataWhileLoading(List<Movie>)或 displayEmptyScreen() 等方法将这些事件转发给“displayers”(MVP 中的“View”)。
  • displayers 的具体实现类将显示/隐藏 Android 视图,并执行诸如moviesView.bind(List<Movie>) 之类的操作

你可以对 presenters 进行单元测试,验证是否调用了 displayers 正确的方法并且带有正确的参数。

你可以用相同的方式测试 displayers 吗?是的,你是可以模拟 Android 视图,并验证是否调用了正确的方法。但这样的粒度并不是我们想要的:

  • displayer 可能确实构建或更新了 RecyclerView 或 ViewPager 适配器,但这并不代表显示了正确的内容。
  • Android 视图是通过在代码中加载 XML(布局和样式)设置的;验证方法的调用不足以断言显示的内容是否正确

设置测试用例

就从使用 espresso-support 这个库开始吧。

在你的 build.gradle(JCenter 可用)里添加依赖

debugCompile 'com.novoda:espresso-support-extras:0.0.3'
androidTestCompile 'com.novoda:espresso-support:0.0.3'

extras 依赖包中包含了 ViewActivity,在测试时需要将其添加到你的应用中。你可以在该 Activity 持有想要使用 Espresso 测试的单一视图。

核心部分(包含自定义测试规则)只需要作为 androidTest 依赖中的一部分。

ViewTestRule 使用方法与 ActivityTestRule 类似。只不过是将传递的参数从想要启动的 Activity 类替换成了包含你想要测试的视图的布局文件:

@RunWith(AndroidJUnit4.class)publicclassMovieItemViewTest{
  @Rule
  public ViewTestRule<MovieItemView> viewTestRule=newViewTestRule<>(R.layout.test_movie_item_view);
  ...

你可以使用 ViewTestRule<MovieItemView> 指定根布局的视图类型。

ViewTestRule 继承了 ActivityTestRule<ViewActivity>,所以它总会打开 ViewActivitygetActivityIntent() 被重写了,所以你可以将 R.layout.test_movie_item_view 作为 Intent 的附加数据传递给 ViewActivity

你可以在测试中使用 Mockito 代替回调函数。

@Rule
public MockitoRule mockitoRule = MockitoJUnit.rule();

@Mock
MovieItemView.Listener movieItemListener;

@Before
publicvoidsetUp(){
  MovieItemView view = viewTestRule.getView();
  view.attachListener(movieItemListener);
  ...
 }

ViewTestRule 有一个 bindViewUsing(Binder) 方法,该方法会返回视图的引用,以便你与之进行交互。当你使用 viewTestRule.getView() 直接访问视图时,你会希望与视图的所有交互都是在主线程上执行的,而非测试线程。

@Before
public void setUp() {
  MovieItemView view = viewTestRule.getView();
  view.attachListener(movieItemListener);
  viewTestRule.bindViewUsing(new ViewTestRule.Binder<MovieItemView>() {
    @Override
    public void bind(MovieItemView view) {
      view.bind(EDWARD_SCISSORHANDS);
    }
  });
}

准备测试

从用户的角度上来看,应用其实只做了两件事情:

  • 展示信息
  • 响应用户的操作

要为这两种情况编写测试,你可以先从使用标准的 Espresso ViewMatchers 和 ViewAssertions 语句断言是否显示正确的信息开始:

@Test
public void titleSetToMovieName() {
  onView(withId(R.id.movie_item_text_name))
      .check(matches(withText(EDWARD_SCISSORHANDS.name)));
}

接着,你应该确保用户的操作触发了正确的点击事件,并且具有正确的参数:

@Test
public void clickMovieItemView() {
  onView(withClassName(is(MovieItemView.class.getName())))
      .perform(click());

  verify(movieItemListener)
      .onClick(eq(EDWARD_SCISSORHANDS));
}

到这里就完成了,希望这些知识对你有用。

在接下来的文章里,我会介绍如何使用 Espresso 测试视图时支持 TalkBack 服务(译者注:Talkback 是一款由谷歌官方开发的系统工具软件,它的定位是帮助盲人或者有视力障碍的用户提供语言辅助)。






原文发布时间为:2017年5月02日


本文来自合作伙伴掘金,了解相关信息可以关注掘金网站。

时间: 2024-11-01 15:46:22

[译] 使用 Espresso 隔离测试视图的相关文章

[译] 使用 Espresso 和 Mockito 测试 MVP

本文讲的是[译] 使用 Espresso 和 Mockito 测试 MVP, 原文地址:TESTING MVP USING ESPRESSO AND MOCKITO 原文作者:Josias Sena 译文出自:掘金翻译计划 译者:skyar2009 校对者:lovexiaov, GangsterHyj 使用 Espresso 和 Mockito 测试 MVP 作为软件开发者,我们尽最大努力做正确的事情确保我们并非无能,并且让其他同事以及领导信任我们所写的代码.我们遵守最好的编程习惯.使用好的架构

[译] SQL 事务隔离实用指南

本文讲的是[译] SQL 事务隔离实用指南, 原文地址:Practical Guide to SQL Transaction Isolation 原文作者:Joe Nelson 译文出自:掘金翻译计划 本文永久链接:github.com/xitu/gold-m- 译者:sigoden 校对者:mnikn, tmpbook 你可能已经在你的数据库文档中看到过隔离级别这一个概念,虽然感到有点不安,但是并没有太放在心上.一些日常的例子中使用到的事务本质上是隔离.大多数人使用数据库的的默认隔离级别,并期

[译] Node.js 之战: 如何在生产环境中调试错误

本文讲的是[译] Node.js 之战: 如何在生产环境中调试错误, 原文地址:Node.js War Stories: Debugging Issues in Production 原文作者:Gergely Nemeth 译文出自:掘金翻译计划 译者:mnikn 校对者:lsvih.Aladdin-ADD Node.js 之战: 在生产环境中调试错误 在这篇文章,这篇文章讲述了 Netflix.RisingStack 和 nearForm 在生产环境中遇到 Node.js 错误的故事 - 因此

springMVC4(14)各类视图输出实例分析

1. 模板视图 FreeMarkerViewResolver . VolocityViewResolver 这两个视图解析器都是 UrlBasedViewResolver 的子类. FreeMarkerViewResolver 会把 Controller 处理方法返回的逻辑视图解析为 FreeMarkerView ,而 VolocityViewResolver 会把返回的逻辑视图解析为 VolocityView .这两个视图解析器是类似的. 对于 FreeMarkerViewResolver 而

LinkedIn Test Butler 旨在改进 Android UI 测试

LinkedIn工程师兼Test Butler创建者Drew Hannay写道,Test Butler是一款面向Android的开源测试工具,它允许开发人员对若干测试环境设置通过编程进行控制,从而使开发人员可以可靠地运行测试. 据Hannay介绍,Test Butler的灵感来自谷歌2014年的演讲"环保之路:清理有毒的移动环境".该演讲介绍了如何解决反复出现并影响移动测试的问题,比如缺少可靠性和可再现性.速度缓慢等.Hannay表示,当结果可能受到环境因素影响时,测试就不可靠了,尤其

《PowerShell V3——SQL Server 2012数据库自动化运维权威指南》——2.13 创建视图

2.13 创建视图 本方案展示了如何用PowerShell和SMO创建视图. 2.13.1 准备 我们将会使用AdventureWorks2008R2数据库的Person.Person表. 为了知道我们将会创建什么,我们给出了等价的T-SQL. CREATE VIEW dbo.vwVCPerson AS SELECT TOP 100 BusinessEntityID, LastName, FirstName FROM Person.Person WHERE PersonType = 'IN' O

使用 Selenium 和 TestNG 进行编程式测试

Testng与junit对比 1. 总体概念 TestNG,即Testing, Next Generation,下一代测试技术,是一套根据JUnit 和 NUnit思想而构建的利用注释来强化测试功能的一个测试框架,即可以用来做单元测试,也可以用来做集成测试. 2. 介绍 TestNG是一个设计用来简化广泛的测试需求的测试框架,从单元测试(隔离测试一个类)到集成测试(测试由有多个类多个包甚至多个外部框架组成的整个系统,例如运用服务器). 编写一个测试的过程有三个典型步骤: * 编写测试的 业务逻辑

《DBA修炼之道:数据库管理员的第一本书》——1.11节生产环境与测试环境

1.11 生产环境与测试环境合格的数据库部署至少要创建并支持两种独立的环境:生产环境和测试环境(或开发环境).在测试环境进行新的开发和维护工作,而在生产环境运行真正的业务运作应用程序.将测试环境与生产环境完全分开很有必要,这样可以确保业务操作的完整性和性能.如果这两者没有分开,将会导致开发工作对企业的日常业务产生影响.最终你可能要因为开发初期的错误程序代码而访问或修改生产数据.测试却访问了生产数据会导致生产性能问题.当然了,修改了生产数据的测试程序会创建无效数据.将测试与生产环境分开以确保业务操

《大灾变》“浩劫与重生”BETA测试即将开启

魔兽世界台服官方论坛版主于21日中午发表公告,催促参加<魔兽世界:浩劫与重生>(大陆暂译:大灾变)抢先测试的玩家于6月23日之前提交个人资料,并声称"浩劫与重生"的BETA测试"很快"开启. <魔兽世界>台服的抢先测试活动仍然是去北美服务器体验,使用的版本也是美版,共计抽取40名玩家. 以下是版主的声明内容: 感谢大家的热情支持与耐心等候! Beta测试将在近期内展开.(多近期?板主不能透露确切日期,只能说......真的很快就要到了!)当4