并行测试:更早获得反馈,更快发布

作为负责测试Azimo iOS应用程序的唯一人员,我遇到了各种问题。 当我四年前开始在Azimo工作时,测试是100%手动的。 一个完整的测试周期最多可能需要两天的时间。 某些功能根本没有经过测试,更不用说在不同的设备和操作系统上了。

如今,只有15%的测试是手动的。 自动化使我们更快,更高效。 在2018年,我们99.9%的用户没有崩溃。 但是,由于我们应用程序的复杂性,整个测试周期大约需要八个小时。 这段时间的一半以上是由自动化测试占用的。 鉴于我们每周至少发布一次,因此我们需要找到一种方法来进一步缩短测试周期。

幸运的是,6月5日,一场革命来到了。 在WWDC 2018大会上,Apple宣布支持Xcode 10中的并行测试。这将我们250项自动测试的周期减少到大约55分钟,使我的生活压力减轻了很多。

在本文中,我将指导您了解并行测试的好处,因为我们在Azimo上已经体验过它们。 我将概述测试内容,机器配置方式以及遇到的问题。 我还将提供一些技巧,以帮助您充分利用并行测试。

在Xcode 9中为iOS设备引入了并行测试。从那时起,我们就能够在不同设备上并行测试不同的类。 但是,Xcode 9版本要求我们使用带有适当参数的命令行。

Xcode 10的革命性功能是自动化测试器-能够直接从Xcode级别在多个模拟器上同时运行不同的测试类,而无需人工测试。 就像启用该功能一样简单:

在这种模式下,Xcode将创建同一模拟器的多个克隆(例如,如果我们使用iPhone X模拟器,则Xcode将创建模拟的iPhone X克隆)。 这仅适用于模拟设备。 我们将在本文后面讨论物理设备上的并行测试。

好处:

  • 简单直观的配置
  • 更快的测试执行
  • 更快的反馈
  • 允许更多版本
  • 同时检查多台设备上的应用程序服务器(请求,超时等)
  • 无需创建其他测试目标,即可在它们之间分配测试类
  • 与CI完美集成

缺点:

  • 如果后端服务器/应用程序服务器不稳定,则可能发生超时(同一时间的多个请求可能会导致更长的响应)
  • 保持模拟器稳定所需的大量处理能力
  • 脱皮-如果发生上述任何问题
  • 克隆相同的设备/系统配置,无法同时在几种不同的配置上进行测试(我们必须使用命令行)

假设:

使用并行测试必须满足的基本条件是测试用例的独立性。 例如:

  • 我们不能仅在测试A完成后才开始依赖测试B
  • 更快的执行速度或测试B的结果不会影响测试A的结果,反之亦然

有用的参数:

  maximum-concurrent-test-simulator-desstinations NUMBER要在同时启用并行测试 的情况下测试的模拟器目标的最大数量YES | NO覆盖方案parallel-testing-worker-count方案中的每个目标设置NUMBER确切的测试数量并行测试期间将产生的测试运行程序maximum-parallel-testing-workers编号并行测试期间将产生的最大测试运行程序数 

有效的测试划分

为了最大化并行测试的优势,我们必须将测试用例划分为多个类。 让我们以我们的国际汇款应用程序Azimo为例,并假设我们的整个测试周期包含五个测试用例。

我们绝对不建议使用的第一个选项是创建一个包含所有五个测试用例的大型类:

假设Azimo目标与Azimo1目标具有不同的测试类,反之亦然,我们使用以下命令在不同设备上的两个目标上运行并行测试:

  xcodebuild \ 
-方案Azimo \
-destination id = {deviceID1} \
无需构建测试&\
xcodebuild \
-方案Azimo1 \
-目标ID = {deviceID2} \
无需构建测试

使用-only-testing参数以及确定测试类,测试执行时间将等于执行时间。

如您所见,上述方法有效,但需要一些人工(创建新目标,在目标之间分离测试,在添加新用例/测试类时维护目标)。 Xcode 10带来了很多好处,可以帮助您解决这一问题。

从Xcode 9开始,Apple支持内置的Xcode服务器。 以前,我们不得不使用其他OS X服务器应用程序。 创建和配置Xcode服务器非常简单:转到Xcode-> Preferences-> Server&Bots ,然后创建新的 Xcode服务器 具有正确的凭据。

在启用和配置Xcode服务器之后,接下来我们必须创建一个机器人以与给定的配置运行集成。 在我们的案例中,它是一个名为UITestsDaily的机器人。 该漫游器每天午夜在我们本地的CI上运行完整的应用程序测试周期。

就个人而言,通过使用值为5的参数parallel-testing-worker-count配置机器人,可以在五个模拟器上同时执行运行测试。

在Azimo,我们使用安装了Xcode 10的iMac(以下规格)。 这是我们本地的持续集成。

为什么使用上面的解决方案?

  • 每个漫游器都有一个集成历史记录(屏幕截图,日志等)
  • 在CI上测试集成时,我们可以在个人计算机上实施/调试其他测试方案
  • 更多资源(内存,处理器)—同时允许我们在并行测试中运行更多模拟器

上面的规范允许您在五个稳定的模拟器上运行并行测试。 我的MacBook Pro 15英寸(16GB RAM,Intel i7 2.2GHZ)最多可支持3个模拟器。 这样可以节省很多时间。

缺点:

  • 需要专用的高规格计算机
  • 大型集成会占用大量内存
  • 没有简单的方法可以清除旧的和不必要的数据
  • 僵尸程序配置没有灵活性(例如,我们无法将集成设置为每30分钟启动一次)

在我们的CI上开始每次集成之后,我们想知道成功测试的百分比。 一种选择是连接到CI并输入特定的集成,然后手动检查。 更好的选择是使用Slack + Fastlane连接,该连接在完成集成后立即向Slack发送通知:

如您所见,以上集成为我们提供了许多有趣的信息,包括:

  • 进行整合的分支
  • 进行集成的机器人的名称
  • 集成中的测试数量
  • 测试失败次数
  • 成功完成测试的百分比

扳机

每个创建的漫游器都具有“ 触发器 ”选项卡。 在这里,我们可以确定每次集成之前和之后应该调用的内容。 正确编写的脚本可以加快调试速度-搜索集成错误的原因(例如,尝试测试不存在的设备,从错误的目录运行脚本等)。 在UITests Daily的集成示例中,它将显示我们用于改进工作的内容。

集成前脚本 —集成前调用的命令

日志信息

  • 打印环境变量
  • 打印所有可用模拟器的列表
  • 打印当前文件夹中的所有文件
  • 打印路径到当前文件夹

清洁

  • 在运行测试之前清洁模拟器
  • 用项目打开一个文件夹

集成后脚本 —集成后要调用的命令

日志信息

  • 打印环境变量
  • 打印路径到当前文件夹

发送状态

  • 打开主目录,以便我们可以从集成到Slack的状态发送中受益
  • 打印路径到当前文件夹

LANG = zh_CN.UTF-8 —在终端会话中设置区域设置export PATH = / usr / local / bin:$ PATH —将usr / local / bin的路径添加到path变量(在我们的情况下,是为了方便使用Fastlane的访问)

  echo:“….. :::所有环境变量::: ..”, 
“….. ::发送状态:: ...”,
“….. :::模拟器列表:: ...”,
“….. :::列出当前文件夹::: ..”

上面的打印输出可以更轻松地搜索我们感兴趣的值的日志。

我希望本文提供一些有关并行测试的好处的有用信息。 尽管并行测试为我们节省了大量时间和精力,但它仍然存在硬件限制(您始终需要更多的设备/处理能力)。 我们的下一步是在几乎无限资源的云中开始测试。 我将在下一篇文章中对此进行介绍。

如有任何疑问,请随时在评论部分🤓发表。