非常好的一篇关于 Instruments UI Automation 的文章,我之前在 testerhome qq 群里分享了。忍不住还是在这里转载。当然有部分内容不是最新的。但是大部分都是非常棒的。

发信人: LuDerek (DerekLu), 信区: MobileDev
标 题: iPhone/iPad UI 自动化测试指南
发信站: 饮水思源 (2012年12月08日21:48:43 星期六)

简述

本指南使用 XCode 附件 Instruments 实现 iPhone/iPad 上的 UI 自动化测试.
本指南较少涉及代码,在很大程度上只是思路的分享.

本指南完全基于 iOS6,XCode 版本 4.5.1,Instruments 版本 4.5(4523)。
作者碰到过一次从 iOS 到 API 的彻底的版本更新,导致原本写的测试代码
大量的细节修改。所以本指南的过期是可以预见的。如果有任何版本更
新导致的本指南与实际状况不一致,请不要来问我因为作者预期今后很
长时间不会接触 UI 自动化开发了。

参考文件

UIA Objects Reference API:
http://developer.apple.com/library/ios/#documentation/DeveloperTools/Reference/UIAutomationRef/_index.html

UIAutomation 介绍:
http://developer.apple.com/library/ios/#documentation/DeveloperTools/Reference/UIAutomationRef/Introduction/Introduction.html

Hello World

入门:如何使用 Instruments 打印指定场景的拓扑结构

  1. 打开 XCode 项目,选择调试目标(一般为 iPhone 或 iPad 模拟器模拟器),并且把调试模
    式指向 Profile。

  2. 选择 Automation。

  3. 等待,直到 Instruments 和模拟器都启动。

  4. 在模拟器中进行操作,直到达到你需要的场景(作为一个 HelloWorld 而言,你也可以不
    进行操作)

  5. 增加一个脚本

  6. 在脚本中添加打印环境语句:
    target.frontMostApp().logElementTree();

  7. 等待环境拓扑被打印出来

可以看到,环境拓扑被以树的形式打印出来。树的节点与 UI 元素一一对应。

UI Automation
Automation 工具提供的元操作

Automation 提供 3 种操作:
读取 UI 拓扑
模拟用户行为
记录日志

可以认为,Automation 主要提供了 “模拟用户行为并且记录一些环境信息” 的工具。(相
比之下,我认为自动化测试这个概念是基于自动化对指定数据做出判断的行为,是个更为
狭窄的概念。)

读取 UI 拓扑

UI 拓扑读取是类似于上章 logElmentTree 的行为。它是基于 View 的 accessibility 的。开发
人员可以重新定义 accessibility,方便测试人员测试。默认的 View 有默认的 accessibili
ty 获取方式。大多数 View 的 accessibility 都是默认的。少量的按钮和表格的 name 属性做了
显式的重定义。

模拟用户行为

用户行为模拟实际上是全局行为和 UI 拓扑的某些参数的结合。例如,API 中提供了对按钮的
点击动作(tap)。事实上这个行为可以被分解成两个部分:程序通过 API 获得这个按钮的
位置和大小,计算这个按钮的中心位置相对于整个屏幕的位置,再把这个位置坐标传向设
备,模拟了一个指定坐标的点击事件。值得注意的是,如果一个元素被遮挡,API 也可以调
用点击动作,然而结果却是上层遮挡的元素被点击。

日志记录

日志记录有两个方面,一方面 Instruments 会自动打印一些日志,一方面用户也可以自行打
印一些日志。日志的类型,时间和内容会被记录。为了支持 UI 自动化测试,Instruments 提
供了 8 种用户日志类型。此外。像 logElementTree 之类的方法也可以认为是用户日志的一部
分。值得注意的是,Automation 暂时不支持原生的 “将元素及其子元素转化为 JSON 格式返
回” 这样的操作,需要自行进行树的遍历与 JSON 格式转化。

UIA 对象

Automation 的 API

UIA 对象即是向运行于设备的 app 获取数据的 API。UIA 对象在 JavaScript 下是一些顶级对象
与返回类型(在 JavaScript 中,“对象” 和 “类” 的概念有一些微妙的通用关系)。它们
具有一定的继承关系。
例如,UIAElement 类是大多数类的基类。UIASecureTextField 和 UIASearchBar 是 UIATextF
ield 的派生类。UIATextField 是 UIAElement 的派生类。但 UIATarget,UIAHost 不是 UIAEle
ment 的派生类。

继承

作为派生类,理所应当会继承基类的一些方法。比较常用的方法都来自于 UIAElement 类。
例如 name,value,elements,rect 等。UIATextField 有 setValue 方法,故而派生类 UIASe
cureTextField 和 UIASearchBar 也会继承这些方法。

类名的获取

如何获取一个已知对象的类名?在 JavaScript 中这是一个比较繁琐的行为。JavaScript 的
typeof 关键字只能判断基本的数据类型,而 instanceof 会判断类是否在对象的派生链上。
所以通常会将所有的 UIA 对象按照派生顺序排成一列,再用 instanceof 关键字进行顺序判断
。这是一种有点浪费但是效率上还好的做法。?
行为模拟
全局行为模拟 + 参数

在之前已经叙述过了,一个特定 UIA 对象上的行为模拟方法实际上是一个全局行为加上一些
参数所模拟出来的。
再举个例子。例如调用 UIAKeyboard 输入一个字符串,程序会把所输入的字符串截成字符逐
个输入。这个过程稍微带点智能,比如在小写状态输入字母 B,那么程序会去按一下 shift
再去按 B,标点符号同理。但是比如如果输入的是中文字符,程序就会因为找不到对应的键
盘输入方法而报错。
因此,可以看到,所谓的 UIA 对象封装的 API 在实现上存在了大量的冗余。很多 API 本身可以
使用其他 API 的组合来实现,当然可能在效率和兼容性上原生 API 可能做得更好(也存在大
量不可靠的例子)。

行为模拟的作用范围

由于授权模式,行为模拟和真实行为的一大区别在于无法在权限以外进行操作。比如,B1
Mobile 运行过程中访问谷歌地图时可能会跳出一个需要 location 授权的 alert,作为一个系
统级 alert 框这个东西不能被模拟出来的行为杀掉,必须跑脚本之前手动杀掉。

日志记录

日志有两种输出格式:plist 格式和 trace 格式。前者是一个 xml,便于后续的程序性分析。
后者是一个 Instrments 自带格式,存储了脚本,运行记录和日志多种信息,并提供原生的
界面。

日志分类

日志大致上分为 3 种:

  1. 系统自动日志。例如使用脚本模拟行为时,系统会自动打印行为,并以 Debug 类型计入
    日志。再例如在 JavaScript 丢出一个没有被抓住的错误的时候,系统会以 Error 类型打印这
    个错误并停止脚本(话说 Instrments 最近一次版本更新以后增加了错误打印的代码栈,这
    个不错)。

  2. 环境打印日志。在这里环境打印日志指的是 logElement,logElementTree 这样的方法所
    打印的日志。这类日志的特点在于日志是直接通过 API 打印的,中间没有 JavaScript 读取过
    程。比如 logElementTree 直接打印,日志中可以获得该对象的很多信息,但中间没有 Java
    Script 过程。诚然 JavaScript 可以通过遍历的方式来获得相应的信息,但效率上无法匹敌
    。比较特殊的环境打印日志还包括 savaSnapShot,可以存储目标设备截图。

  3. 用户日志。用户有 8 种日志类型。都位于 UIALogger 之下。事实上可以推测出这种类型设
    计是专为自动化测试定制的。值得注意的是大部分系统自动日志都是 Debug 类型的,所以尽
    量避开这种类型可以防止和系统自动日志搞混。

限制

Automation 无法获取所有的元素。

在实践中,有一些元素是 Automation 无法获取的,主要是一些看起来像是浮于
文字上方的元素。这些元素无法被 Automation 获取。

当然,前文已经说过,Automation 无法获取这些元素的原因是因为在写代码的时候这些对
象的 accessibility 没有正确的默认显示方式。如果愿意对 Automation 更大支持的话,也可
以重写它们的 accessibility。Accessibility 不单影响 Automation,对 VoiceOver 等特性也
有支持。

部分元素被以 “兼容模式” 显示

同样是 accessibility 的问题。一些元素没有很好的打印支持,所以被以兼容模式显示。例
如一个日期显示控件,或者一个 WebView 的 Canvas 元素,由于 accessibility 没有过多的支
持,它们仅仅作为一张图片被打印,失去了内部特性。

另一方面,旧版本的 GoogleMap 同样以一张图片显示,新版本变成了一个 UIAMapView。所以
这类兼容模式显示的元素也有被新版本支持的 “机会” 与 “风险”。

渲染细节的失去

在大部分情况下,关于元素的信息获取是有限的,一个 UIAStaticText 一般有 name,value
,label,rect 等属性,而实际上它们还应该有关于字体渲染的细节,如字体大小,粗细,
行距,字体类型等等。
图片有同样的问题。程序只能分辨两张图片的位置和大小的不同,导致的问题是,两张相
同大小的图片,程序无法分辨他们是不是同一张。

没有全局的唯一 ID 选择器。

没有类似于浏览器 Dom 的 getElementById 的方法。也就是说,需要选取一个已知 id 的元素,
也必须通过其父节点。诚然可以通过遍历的方法找到一个匹配的元素。但是在 B1Mobile 这
样的元素不多的应用环境场景下,一个深度遍历的算法选取某 id 元素也需要 2 分钟的时间。
这是大多数测试下不能容忍的。

App 以外无权限读写操作。

之前提到过,一个系统级 alert 是无法被环境所反馈的。事实上,所有 app 以外的设置都无
法被环境所读取与操作。例如,B1Mobile 需要到 settings 里去预先配置,这部分由于在 ap
p 以外,必须手动完成,自动化操作无能为力。
用户视图与 Automation 视图的差异

用户从物理设备上看到的应用与 Automation 获取的信息存在差异。除了上文提及的拓扑过
程的信息缺失以外,还存在类似于这样的问题:

文本过长,渲染时以省略号作为摘要,而 Automation 丢失此渲染信息,直接获取原字符串

文本过长,渲染时浮出自动截断,而 Automation 丢失此渲染信息,直接获取原字符串。
页过长,阅览时需要滚动条拖动显示,而 Automation 不需要滚动条,直接获取了所有页内
所有信息。
页被部分或完全遮挡,Automation 仍能获取被遮挡页所有信息。

事实上对于这类例子,可以说是 Automation 获取了比正常用户更多的细节。但问题是,作
为自动化测试,Automation 本身应该以用户为准。即,存在这样一个事实,在 app 信息对于
用户不可见的情况下,对 Automation 可见也是完全没有意义的。作为工具的限制,应该将
Automation 视图作为一个与用户视图 “相似却不完全一样的黑盒”。

精确的时间

Automation 无法做到精确的计时。这主要是因为整个 API 不是事件驱动的。例如,对于登陆
时间的测算,从按下登陆按钮的那一刻起计时,当登陆后最后一个 UI 元素渲染完毕,设备
不会传递一个事件给 Automation 告知渲染结束。一个解决方案是,程序每隔一段很小的时
间去检查 UI 元素有没有渲染完毕,有则返回。这种做法的精确度取决于检查时间间隔,并
且是低效而无奈的做法

另一方面,API 的调用也需要返回时间。这段时间在模拟器中不够明显,在真实设备上,这
个过程对程序相当地长。并且很遗憾的是,这段时间甚至不是能够预知的。这对于自动化
测试的影响是,无法对某个在时间上过程性的行为做测试。例如。在某个页上点击后,一
个新的页会滑入。理论上可以通过这个页掉落过程的坐标变换来判断它的滑入方向,但实
际上由于 API 调用时间的不精确,不一定能够在这滑入时间间隔内使点击事件返回并重新调
用选择器和位置方法。所以可以说,对于这种暂态的自动化测试是不可靠的。

错误

Instrments 本身的频繁崩溃

我也不知道为什么。通过软件重启能够解决的问题都不是问题。

在同一个设备实例上同时运行两个 Automation

听起来很美妙。在 Instruments 启动时我拖入了两个 Automation 组件,其一运行我预先写好
的脚本,另一个每隔一段时间为设备截一张图。
结果失败了。不管试几次 Automation 都会 crash。
我对于 crash 的猜测是,Instrments 的确允许同时运行两个 Automation,但两个 Automatio
n 不能同时调用 API。同一时间对于 API 的调用会出错,而且之前我说过了,API 方法的返回
有相当长的间隔时间。

elements 方法的错误:返回全局对象

在我尝试写出全局遍历方法时,我遇到了我没有预期的栈溢出错误。分析问题时发现,el
ements 方法(即获取节点子节点)对于所有没有子节点的 UIAStaticText 都返回全局的 UIA
Application 对象。后来 Instruments 升级到 4.5 后,返回对象改为了 UIAWindow。这个问题
应该也是 accessibility 问题。

频繁的 UIALogger 的方法

频繁的 API 调用会导致类似于竞争的问题。这个问题在 UIALogger 上尤为显著。UIALogger 是
简单的将字符串打印为日志的 API,当我们频繁打印日志时(例如使用一个循环,迅速打印
1000 条日志),Instrments 生成这 1000 条日志的时间会明显长于生成一条日志的 1000 倍时
间。
另外需要注意的是,虽然理论上日志条目可以无限长,但我建议将日志条目控制在 5000 以
内,因为根据经验日志条目过长可能会导致意外崩溃。

不可靠的 onAlert 方法

作为这个号称事件驱动的方法,我的意见是直接放弃它。因为它从来没有正常运行过。
在 4.5 版本中这个方法尤为诡异,对 onAlert 事件的绑定甚至会影响下一次运行。

JavaScript 环境
JavaScript 版本

Automation 所使用的 JavaScript 环境是一个类似于 EcmaScript3 的环境。当然它不支持像 s
trict mode,bind 之类的方法。

与浏览器环境的差异

需要注意的是,Automation 不是一个 Browser 环境,没有 dom,所以也没有 document 方法,
没有 window 方法。这意味着一些你可能觉得很常用的方法如 setTimeout,在 Automation 的
JavaScript 环境中是不可用的。(事实上某些 API 有同名的 setTimeout 方法,但是用处是不
一样的)。
我倒不觉得这是一件坏事。对于 JavaScript 程序员来说,这是一个极佳的认识 JavaScript
本质的环境—环境更加简单纯净,而且脱离 Browser 的混淆,脱离像 node 这样的仍然是面向
Web 的 JavaScript 环境。而且通过一些环境 bug 来让你思考它的合理性。

Automation 不提供 console,也无法设置断点。在脚本错误时也无法实时在 JavaScript 环境
中调试。这样对你来说脚本是逐句解释执行还是编译为二进制执行也没什么大区别。

效率

在效率方面,我曾经在我的办公用笔记本电脑的 Chrome 和 Automation 上跑了下 Benchmark。
大概的执行效率,Automation 环境是 Chrome 的 1/12。听起来是个很可怕的数字,但其实效
率还好不是问题。可以容忍一些比较基本的算法。树的遍历啊什么的。

外部文件的加载

作为一个纯 JavaScript 环境,Automation 可以无差别地加载一些纯 JavaScript 库,如 back
bone.js(一个 MVC 库),underscore.js(集合与 Object 的拓展方法库)等。

Automation 为文件引用增加了 #import 语句。#import 语句可以援引另一个 JavaScript 文
件并插入原脚本头。值得注意的是,当被 #import 的文档再次 #import 其他文档时,这个其
它文档会被插入被 #import 文档的尾部。可以说 #import 是个功能相当简单的语句,不要当
C 语言中的 #include 来用。

JavaScript 环境的缺陷

设计理念

我相信苹果对于 Automation 的脚本设计理念是这样的:总要用一种脚本语言,又不可能用
对头家的 VB,定义自己的语言又有些多余,就选择一种相对合适的语言。于是就使用了 Ja
vaScript 语言。

本质:类 JavaScript 语言

我更倾向于将 Automation 使用的语言称为 “类似于 JavaScript 的脚本语言”,尽管在本指
南中经常直接称它为 JavaScript,官方文档最近也直接声明这种语言为 JavaScript。但我
不认为它是纯粹的 JavaScript。比较直观的原因如下

#import 语句不符合 JavaScript 语法标准(它本可以定义为注释类型)
waitForInvalid 方法可以类似于 break 语句直接跳出循环。没有任何 JavaScript 方法可以
混合实现这个效果。
从方法返回的对象并非是从顶级对象(类)名生成。修改 prototype 不会更改这些返回对
象。

事实上不单单是具体缺陷的问题,这种缺陷反映了这样一个事实:Automation 的 JavaScri
pt 环境不是纯粹的 JavaScript 环境。从设计理念来说,可以理解为苹果公司只是借用了 Ja
vaScript 大部分语法来实现自动化。Automation 的 JavaScript 环境是以 “够用” 作为标准
的,如果某些 API 在 JavaScript 标准语法中显得很奇怪,苹果会毫不犹豫打破 JavaScript 本
身。这样就有一个 risk,对于非常熟悉 JavaScript 的脚本撰写者而言,有一些 API 或者语法
会跳出 JavaScript 的思维定势。

或者可以这么理解:Automation 先把所谓的 JavaScript 代码放入一个预编译器,将 #impor
t,waitForInvalid 这样的特殊语法重新解释,然后再把生成的代码送入 JavaScript 执行环
境。
?

其他:网络,阻塞与事件缺失

Automation 的 JavaScript 环境是封闭的,没有任何办法访问网络。

计时方面,JavaScript 失去了 setTimeout 队列使得它失去了很多特性。相对的提供了一个
阻塞函数 target.delay。很多 UIA 对象提供了封装性的函数。我不信任它们。事实上我很少
使用 waitForInvalid 这样的函数,所以连 pushTimeout 这样的函数也用的很少。其一是因为
B1 Mobile 测试对于效率的要求不是很高,其二是因为我觉得它们的表现很不稳定。

UIA 对象

UIA 对象在这里指的是 Automation JavaScript 环境中 UIA 打头的一些对象。

虽然 Automation 的环境中有一些 UIA 顶级对象,但是通常可以直接忽略它们。我认为它们的
唯一用途就是类型判断。很少有静态方法可供调用。

更多的是 API,而非 JavaScript 对象

对于 UIA 对象,我的意见是直接将它们看做 API(本文一直是这么表述的),而不要将它们
看做传统的 JavaScript 对象。有的时候我们会使用一些 JavaScript 特性,比如绑架方法,
更改调用者,访问 constructor,更改 prototype,这些特性在 UIA 对象中很难施行。

版本变化与 API 改变

UIA 对象作为 API 会随版本更替而调整。例如上文提到的 UIAMapView 的增加。在 4.5.1 中增加
了一个 visible 方法,判断一个对象是否可见(事实上就是判断一个元素中心点有没有被其
他元素遮盖)。
很多 API 事实上不是 “元 API” 而只是其他 API 的组合,在这一点上前文已经叙述过了。

访问方法

访问一个 UIA 元素有两种方法:通过它的 name 或者通过它的 index。这两种方法都需要取得
它的父元素。没有全局的通过 name 来唯一搜寻的方法。另外,也可以通过元素类型来搜寻
。UIAElement 提供了一系列通过类型来搜寻的方法,例如通过 cells 来搜寻所有 UIATableC
ell 对象。几乎所有的元素与属性都是通过函数而非变量来搜寻的(XXX.name()==” abc”
而不是 XXX.name==” abc”)。

另外 UIA 对象提供了 Predicate 选择器,通过 Predicate 语法来选取元素。可以理解为,通过
一个正则表达式去匹配元素,把它们选择出来。这是一个原生的方法。例如一个元素有 10
00 个子元素,如果直接使用 RegExp,需要把 1000 个子元素统统选取,然后使用 RegExp 逐一
比较。而 Predicate 理论上能够原生的提供更好的速度上的提升,忽略算法复杂度。
对于 B1 Mobile 而言,需要使用 Predicate 的地方比较少,所以我不大用这个东西。

设备一致性

对于目标设备来说,理论上 iOS 设备应该有极佳的一致性。也就是说,只要操作系统版本和
app 一致,同样的 Automation 脚本一旦能跑在 iPad 模拟器上,那它就应该能跑在相同设置的
任何物理 iPad 上(忽略 provisioning 问题)。事实上不是这样的。Accessibility 有的时候
会生成一些不需要的元素,例如把滚动条显示为窄而长的图片,影响脚本中元素顺序。

Utility 设计

无论你将它们称为 Utility 还是 Library,总之它们是一些在你写脚本之前会不假思索 #imp
ort 的一些 js 文件。它们应该完成以下功能:

环境修复

Instruments 有一些小问题,这些问题可以使用 JavaScript 本身修复。例如 onAlert 有一些
奇怪的表现,通常我会选择直接屏蔽这个方法。再比如我会针对命令行执行方式给出一个
比较好看的 CT100 格式渲染,所以会加载一个额外的库。

环境增强

比如我习惯于将当前环境存为 window 变量。再比如我希望 UIALogger 的方法除了接受 strin
g 类型,也接受 number 或者 Object 类型。再比如我可以给 function 的 prototype 增加 bind 方
法实现比较高级的调用,都可以在这部分完成。

自动化测试解决方案

Automation 顾名思义是自动化而不是自动化测试。需要一个 Utility 来定义一个自动化测试
脚本的撰写方法与日志规范。

选择器,集合运算与方法组合

Web 下的 JavaScript 库 JQuery 给人留下了很深的印象。一些通用的操作可以被归纳起来,例
如查找一个元素数组的子元素中一个特定 name 的元素,或者将一组元素转化为 JSON 类型,
再作为 String 打印出来。又或者前文提到的很慢的遍历方法。这些都可以写在这个库里。

针对具体 APP 特定方法

例如登陆功能将用户名密码输入指定框然后按登陆,或者判断一个页面是否加载完成,又
或者查找一个 page。

针对以上所有 Utility 的测试

思考

遍历

不常用的方法
遍历是非常差的方法。通常不需要通过遍历取某个元素,而是直接一层一层选择比较好。

Bug

一旦需要遍历,首先注意的是一个问题,就是一般 UIAStaticText 是没有子元素的,之前提
过一个 bug 就是 UIAStaticText 访问子元素会访问 UIAApplication。需要修复这一问题。
广度遍历 VS 深度遍历
另外对于 B1 Mobile,广度遍历比深度遍历达到元素的速度会更快。比如一个 UIATableCel
l 里有一个 UIAStaticText,然而这个 UIAStaticText 会直接把它的 value 传递给 UIATableCe
ll 作为 name,那么访问 UIAStaticText 就是没意义与浪费时间的。广度遍历可以让你首先找
到 UIATableCell 从而返回,阻止进一步的时间浪费。

适当的过滤

通常遍历不需要遍历不可见元素,所以在判断一个元素是否值得遍历子元素之前判断一下
这个元素本身是否可见是比较好的方法。isVisible 方法是一个比较粗糙的解决方案。

命名原则与名字空间

命名原则应该一致,且望文知义。名字空间上,按照功能与依赖丢入不同的名字空间(在
这里就是 $ 与 B1MA)有利于维护和查找。例如 login 如果没有名字空间,就会造成污染。它
很明显是个与 app 有关的方法,应该丢入 B1MA。

Test Case 设计

简短而正交
除了个别特殊测试,Test Case 应该保持简短而正交。
例如,如果有 2 个相关的 Test Case,第二个不必要地跟第一个有一些交叉。后来在交叉
部分出现了一个 Regression,就会让第一个 Test Case 报错。而事实上第二个 Test Case 是
没有报错必要的,很可能这种不必要交叉会阻塞住第二个 Test Case 的进行。
适当的长度
Test Case 过长一方面会增加 TA 撰写和调试时间,另一方面由于 Instruments 不是很稳定,
或者网络不稳定就要导致这个 Test Case 重新跑,这是比较耗费时间的。控制一个 Test Ca
se 在 15 分钟以内是比较好的设计。

代码压缩与闭包
代码压缩可以去除一些不必要地存储空间,以及提升运行效率。事实上我使用 google clo
sure compiler 对我写的 Utility 压缩过,结果挺好。
比较高级的代码压缩能分析整个测试代码工程,将库中没有使用的函数去除,并且把所有
的代码压缩成一个单独的文件。我个人比较喜欢压缩的单一文件。
值得注意的是,google closure compiler 高级功能需要一些配置和代码撰写规范。而且实
际上这个工具是为 web 定制的,需要规避一些像 window,document 之类的变量名。

半自动化与全自动化
现状:半自动化

事实上我一直认为我所做的事情一直是 “半自动化” 的:手动的打开 XCode,手动的选择 A
utomation,手动的配置 app,手动的载入脚本,手动的按开始键,然后自动运行完之后手
动载入下一个脚本,手动开始。当然我所做的事情是 “创造价值的那一半”,但我认为自
动化测试可以做的更多。

全自动化解决方案

命令行是这一切的基础。基于 Automation,网络上有 bwoken 和 CI 的解决方案。对于这个解
决方案的大致描述是,bwoken 提供了 instruments 命令行的参数环境兼容性解决方法,让用
户越过 instruments 又臭又长的参数输入列表,同时对 log 稍微优化一下。CI 和版本控制软
件相连,版本控制软件一旦 check in 新版本,CI 自动的取下新版本,并把相应的 Automati
on Test Case 分配给不同的测试机 worker(也许测试脚本可以进一下 Closure Compiler)
。Worker 取得 test case,跑完以后再把 log 上传到服务器。待所有 test case 跑完以后,s
erver 将这些结果生成综合报告。

危险:来自 Instruments

我认为这是一个恰当的全自动化测试方案。但是目前对于 Instruments 的依赖太强了。Ins
truments 作为一个比较新的工具,本身有很多不稳定因素,所以在此之上搭建更高级的平
台有很大的风险。但是这的确是一个合理的全自动测试方案。与之相比,GUI 的 Instrment
s 看起来更像是一个自动化测试脚本设计工具。


↙↙↙阅读原文可查看相关链接,并与作者交流