2012-08-10 15:47 by 知平软件, 15839 阅读, 5 评论, 收藏, 编辑html
写在前面ios
研究iOS的自动化测试也有些日子了,刚开始的时候,一直苦于找不到什么好的资料,只能从Apple的官网查阅相关的API文档,只惋惜,Apple对开发者来讲实在是不怎么友好,文档写得至关的粗略,对于初学者来讲有必定的难度。web
原本是打算本身动手写一篇关于iOS的UI自动化测试的入门级别的介绍性文档的,但想起来后面在具体解决一些问题的时候,收藏一篇很好的Blog,很全面地介绍了如何使用UIAutomation的JavaScript Libraries作iOS程序的自动化测试。若是做者早点看到这篇文章,应该要少走一些弯路,这里没有创意性的它他翻译成中文,但愿对大家有一些帮助。xcode
原文地址:http://blog.manbolo.com/2012/04/08/ios-automated-tests-with-uiautomation网络
翻译正文:app
快速入门框架
自动化测试代码能够“在你的睡着的时候”很好地帮你测试你的应用程序。它可让你可以快速地跟踪你程序中的回归和性能方面的问题,这样你就不用担忧你新增的功能会影响到你以前已经完成开发的程序了。编辑器
随着iOS4.0的发布,苹果公司同时发布了一个名为UIAutomation的测试框架,它能够用来在真实设备和iPhone模拟器上执行自动化测试。但官方关于UIAutomation的文档至关的有限,在网络上也没有太多的资源能够查找的。本文将向你展现你如何将UIAutomation整合到你的工做流程当中去。ide
做为基础知识的准备,你能够先看一下苹果公司关于UIAutomation的文档,另外还有一篇快速入门的介绍苹果Instruments的文档也值得看看,固然,若是你有一个免费的Apple开发者帐号的话,你能够看一下WWDC 2010 - Session 306 – 使用Instruments进行用户界面自动化测试的幻灯片或者视频。post
除此以外,包括在Xcode中的OCUnit测试框架也能够用来为你的应用程序编写单元测试。
1. 第一个UIAutomation测试脚本
使用iOS 模拟器
使用iOS设备
2. 处理UIAElement和元素可访问性(Accessibility)
UIAElement层次结构
模拟用户操做
3. 经验分享(让你的生活变得更简单)
类库Tune-up介绍
导入外部脚本
使用强大的命令行
使用录制交互功能
当遇到问题时,加上“UIATarget.delay(1);”
4. 高级交互
处理非预期和预期的提示框(alerts)
多任务
屏幕方向
5. 总结
有用的连接
一个视频
1. 你的第一个UIAutomation测试脚本
UIAutomation的功能测试代码是用Javascript编写的。UIAutomation和Accessibility有着直接的关系,你将用到经过标签和值的访问性来得到UI元素,同时完成相应的交互操做。
下面让咱们来编写咱们的第一段测试代码。
使用iOS模拟器
1. 下载示例应用程序TestAutomation.xcodeproj,并打开它。这个项目是一个很简单的包含2个tab的tabbar应用程序。
2. 确保选中以下图所示的“TestAutomation > iPhone 5.0 Simulator”模式(或许你已经切换成5.1了,所以它多是iPhone5.1模拟器)。
3. 启动Instruments(Product > Profile),或者经过⌘I。
4. 选择左边的iOS Simulator,而后再选择Automation模板,而后点击“Profile”。
5. Instruments就已经启动好后,而后直接开始录制了。这里先中止录制,(红包按钮或者⌘R)。
6. 在左边的Scripts窗口,点击“Add > Create”建立新的脚本。
7. 在脚本编辑器里,输入下面的代码
1
2
3
4
|
var
target = UIATarget.localTarget();
var
app = target.frontMostApp();
var
window = app.mainWindow();
target.logElementTree();
|
8. 从新运行这段脚本⌘R(不须要保存)。脚本跑起来后,你能够在日志打完后中止它。
赞一个!咱们就这样完成了咱们的第一个UIAutomation测试用例。
使用iOS设备
你除了将你的测试用例运行模拟器上,也能够将它运行在一个真实的设备上。不过,自动化测试用例只能运行在支持多任务的:iPhone 3GS,iPad,iOS > 4.0等设备上。遗憾的是无论iPhone 3G的系统版本是什么,都不支持。
下面是如何操做:
1. 经过USB接口链接上你的iPhone。
2. 选择 “TestAutomation > iOS Device”模式。
3. 确保Developper profile设置成Release模式(而不是Ad-Hoc Distribution profile)。默认状况下,profiling是设置成Release模式的(由于没有必要将profile设置成Debug模式)。
4. 启动测试 (⌘I)
5. 后面的步骤请参考前面模拟器部分。
2. 处理UIAElement和元素可访问性(Accessibility)
UIAElement层次结构
Accessibility和UIAutomation有密切的联系:若是一个控件的Accessibility是能够被访问的,你就能够设置和读取它的值,做相关的操做,而当一个控件的Accessibility不可见时,你就没有办法经过automation访问它。
你能够经过Interface Builder,或者经过在程序里设置isAccessibilityElement属性的方式来设置一个控件的Accessibility或者可被自动化。当你设置container view(即:一个视图包含其它的UIKit元素)的accessibility时,你必须注意。你设置了整个View的accessibility将会“隐藏”它的子视图的accessibility,例如:在示例项目中,你不能将outlet视图设置成可访问的,不然它全部的子控件将都不能够访问了。在任什么时候候,logElementTree都是你忠实的朋友:它将当前界面的全部可被访问的元素都打印在日志里。
每个能够被访问的UIKit控件均可以用一个Javascript对象来描述,它就是一个UIAElement。UIAElement有几个属性:name, value, elements, parent。你的主窗口包含不少的控件,它们是以UIKit层次的方式定义的,这些UIKit层次结构对应的是UIAElement的层次树。例如:前面的测试代码中,经过调用logElementTree,咱们能够获得以下面所示的树结构:
+- UIATarget: name:iPhone Simulator rect:{{0,0},{320,480}}
| +- UIAApplication: name:TestAutomation rect:{{0,20},{320,460}}
| | +- UIAWindow: rect:{{0,0},{320,480}}
| | | +- UIAStaticText: name:First View value:First View rect:{{54,52},{212,43}}
| | | +- UIATextField: name:User Text value:Tap Some Text Here ! rect:{{20,179},{280,31}}
| | | +- UIAStaticText: name:The text is: value:The text is: rect:{{20,231},{112,21}}
| | | +- UIAStaticText: value: rect:{{145,231},{155,21}}
| | | +- UIATabBar: rect:{{0,431},{320,49}}
| | | | +- UIAImage: rect:{{0,431},{320,49}}
| | | | +- UIAButton: name:First value:1 rect:{{2,432},{156,48}}
| | | | +- UIAButton: name:Second rect:{{162,432},{156,48}}
你能够经过下面的代码来访问文本框:
1
2
|
var
textField =
UIATarget.localTarget().frontMostApp().mainWindow().textFields()[0];
|
你能够选择经过从0开始的索引或者这个元素的名称来访问这个元素,例如:你也能够经过下面的代码来访问文本控件。
1
2
|
var
textField =
UIATarget.localTarget().frontMostApp().mainWindow().textFields()[
"User Text"
];
|
后一种方式更加清晰明了,应该多使用。你能够经过Interface Builder设置UIAElement的name属性,
或者经过编写代码的方式:
1
2
|
myTextField.accessibilityEnabled = YES;
myTextField.accessibilityLabel = @
"User Text"
;
|
你如今能够看到,经过accessibility属性能够被UIAutomation用来找到不一样的控件。这很是的清晰,由于,第一,你只要学习一个测试框架;第二,经过编写自动化测试代码,你同时还能够保证你的程序是能够被访问的。所以,每个UIAElement对象的子控件能够经过下面的方法进行访问:
buttons(), images(), scrollViews(),textFields(), webViews(), segmentedControls(), sliders(), staticTexts(), switches(), tabBar(),tableViews(), textViews(), toolbar(), toolbars() 等等……
你能够经过以下代码在tabbar上访问第一个tab:
1
2
|
var
tabBar = UIATarget.localTarget().frontMostApp().tabBar();
var
tabButton = tabBar.buttons()[
"First"
];
|
UIAElement结构层次很是的重要,你之后会经常用到它。并且你还要记住,你能够在随时经过调用UIAAplication的logElementTree来得到它的结构。
1
|
UIATarget.localTarget().frontMostApp().logElementTree();
|
在模拟器上,你还能够激活Accessibility 的检测器。启动模拟器,找到“Settings > General > Accessibility > Accessibility Inspector”,而后将它设为“打开”状态。
这个彩色的小框框就是Accessibility 检测器了。当它收起来的时候,Accessibility就被关闭了,当它展开的时候,Accessibility就是打开的。你只要点击上面的箭头按钮就能够激活或者屏蔽Accessibility。如今,打开咱们的示例程序,激活检测器。
而后,点击文本框,检查UIAElement的name和value属性(其实就是accessibilityLabel和accessibilityValue对应的NSObject类型的值)。这个检测器能够帮助你调试和编写你的测试代码。
模拟用户操做
让咱们更进一步,模拟一些用户的交互操做。你能够简单地调用按钮的tap()来做一个点击操做:
1
2
3
4
5
|
var
tabBar = UIATarget.localTarget().frontMostApp().tabBar();
var
tabButton = tabBar.buttons()[
"First"
];
// Tap the tab bar !
tabButton.tap();
|
你还能够调用UIAButtons的doubleTap(), twoFingerTap()。若是你不想操做具体的某个元素,你也能够直接根据屏幕上指定的坐标点进行操做,你能够这么用:
点击:
1
2
3
|
UIATarget.localTarget().tap({x:100, y:200});
UIATarget.localTarget().doubleTap({x:100, y:200});
UIATarget.localTarget().twoFingerTap({x:100, y:200});
|
缩放:
1
2
|
UIATarget.localTarget().pinchOpenFromToForDuration({x:20, y:200},{x:300, y:200},2);
UIATarget.localTarget().pinchCloseFromToForDuration({x:20, y:200}, {x:300, y:200},2);
|
拖拽与划动:
1
2
|
UIATarget.localTarget().dragFromToForDuration({x:160, y:200},{x:160,y:400},1);
UIATarget.localTarget().flickFromTo({x:160, y:200},{x:160, y:400});
|
注意,当你指定操做的时间间隔的时候,它是有特定的范围的,即:拖拽操做的时间间隔必须大于或者等于0.5秒,小于60秒。
如今,让咱们来练习一下:
中止Instruments (⌘R)
在Scripts窗口里, 移除当前的脚本
点击“Add > Import”而后选择TestAutomation/TestUI/Test-1.js(将下面的代码保存到这个路径)
点击录制按钮 (⌘R) 而后看看将会发生什么…
下面是Test-1.js代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
|
var
testName =
"Test 1"
;
var
target = UIATarget.localTarget();
var
app = target.frontMostApp();
var
window = app.mainWindow();
UIALogger.logStart( testName );
app.logElementTree();
//-- select the elements
UIALogger.logMessage(
"Select the first tab"
);
var
tabBar = app.tabBar();
var
selectedTabName = tabBar.selectedButton().name();
if
(selectedTabName !=
"First"
) {
tabBar.buttons()[
"First"
].tap();
}
//-- tap on the text fiels
UIALogger.logMessage(
"Tap on the text field now"
);
var
recipeName =
"Unusually Long Name for a Recipe"
;
window.textFields()[0].setValue(recipeName);
target.delay( 2 );
//-- tap on the text fiels
UIALogger.logMessage(
"Dismiss the keyboard"
);
app.logElementTree();
app.keyboard().buttons()[
"return"
].tap();
var
textValue = window.staticTexts()[
"RecipeName"
].value();
if
(textValue === recipeName){
UIALogger.logPass( testName );
}
else
{
UIALogger.logFail( testName );
}
|
这段脚本先启动待测程序,而后,若是第一个tab没有被选的话就切换到第一个tab,并将上面的文本框的值设成“Unusually Long Name for a Recipe”,接着收起虚拟键盘。这里有一些新的方法值得注意的:UIATarget的delay(Number timeInterval) 方法容许你在两个操做之间作一些等待,UIALogger的logMessage( String message) 方法用来将你想打印的信息输出到日志上去,UIALogger的logPass(String message)方法指明你的测试脚本已经成功的完成测试了。
你还知道了如何访问键盘上的按钮,而后做点击操做:
1
|
app.keyboard().buttons()[
"return"
].tap();
|
因为时间有限且原文太长,先只能翻译到这里,我会尽快的将剩下的部分翻译补上。另外,时间仓促,若有翻译得不许确的地方,也敬请担待。谢谢。
本文由知平软件的Dawson Liu翻译,转载请注明出处。
知平软件致力于移动平台自动化测试技术的研究,咱们但愿经过向社区贡献知识和开源项目,来促进行业和自身的发展。