从零开始使用Xcode自动化测试

自动化测试代码可以“在你的睡着的时候”很好地帮你测试你的应用程序。它可以让你能够快速地跟踪你程序中的回归和性能方面的问题,这样你就不用担心你新增的功能会影响到你之前已经完成开发的程序了。

随着iOS4.0的发布,苹果公司同时发布了一个名为UIAutomation的测试框架,它可以用来在真实设备和iPhone模拟器上执行自动化测试。但官方关于UIAutomation的文档相当的有限,在网络上也没有太多的资源可以查找的。本文将向你展示你如何将UIAutomation整合到你的工作流程当中去。

作为基础知识的准备,你可以先看一下苹果公司关于UIAutomation的文档,另外还有一篇快速入门的介绍苹果Instruments的文档也值得看看,当然,如果你有一个免费的Apple开发者账号的话,你可以看一下WWDC2010-Session306–使用Instruments进行用户界面自动化测试的幻灯片或者视频。

除此之外,包括在Xcode中的OCUnit测试框架也可以用来为你的应用程序编写单元测试。

1.第一个UIAutomation测试脚本

2.处理UIAElement和元素可访问性(Accessibility)

4.高级交互

5.总结

1.你的第一个UIAutomation测试脚本

UIAutomation的功能测试代码是用Javascript编写的。UIAutomation和Accessibility有着直接的关系,你将用到通过标签和值的访问性来获得UI元素,同时完成相应的交互操作。

下面让我们来编写我们的第一段测试代码。

使用iOS模拟器

1.下载示例应用程序TestAutomation.xcodeproj,并打开它。这个项目是一个很简单的包含2个tab的tabbar应用程序。

2.确保选中如下图所示的“TestAutomation>iPhone5.0Simulator”模式(或许你已经切换成5.1了,因此它可能是iPhone5.1模拟器)。

3.启动Instruments(Product>Profile),或者通过I。

4.选择左边的iOSSimulator,然后再选择Automation模板,然后点击“Profile”。

5.Instruments就已经启动好后,然后直接开始录制了。这里先停止录制,(红包按钮或者R)。

6.在左边的Scripts窗口,点击“Add>Create”创建新的脚本。

7.在脚本编辑器里,输入下面的代码

8.重新运行这段脚本R(不需要保存)。脚本跑起来后,你可以在日志打完后停止它。

赞一个!我们就这样完成了我们的第一个UIAutomation测试用例。

使用iOS设备

你除了将你的测试用例运行模拟器上,也可以将它运行在一个真实的设备上。不过,自动化测试用例只能运行在支持多任务的:iPhone3GS,iPad,iOS>4.0等设备上。遗憾的是不管iPhone3G的系统版本是什么,都不支持。

下面是如何操作:

1.通过USB接口连接上你的iPhone。

2.选择“TestAutomation>iOSDevice”模式。

3.确保Developperprofile设置成Release模式(而不是Ad-HocDistributionprofile)。默认情况下,profiling是设置成Release模式的(因为没有必要将profile设置成Debug模式)。

4.启动测试(I)

5.后面的步骤请参考前面模拟器部分。

UIAElement层次结构

你可以通过InterfaceBuilder,或者通过在程序里设置isAccessibilityElement属性的方式来设置一个控件的Accessibility或者可被自动化。当你设置containerview(即:一个视图包含其它的UIKit元素)的accessibility时,你必须注意。你设置了整个View的accessibility将会“隐藏”它的子视图的accessibility,例如:在示例项目中,你不能将outlet视图设置成可访问的,否则它所有的子控件将都不可以访问了。在任何时候,logElementTree都是你忠实的朋友:它将当前界面的所有可被访问的元素都打印在日志里。

每一个可以被访问的UIKit控件都可以用一个Javascript对象来描述,它就是一个UIAElement。UIAElement有几个属性:name,value,elements,parent。你的主窗口包含很多的控件,它们是以UIKit层次的方式定义的,这些UIKit层次结构对应的是UIAElement的层次树。例如:前面的测试代码中,通过调用logElementTree,我们可以得到如下面所示的树结构:

+-UIATarget:name:iPhoneSimulatorrect:{{0,0},{320,480}}

|+-UIAApplication:name:TestAutomationrect:{{0,20},{320,460}}

||+-UIAWindow:rect:{{0,0},{320,480}}

|||+-UIAStaticText:name:FirstViewvalue:FirstViewrect:{{54,52},{212,43}}

|||+-UIATextField:name:UserTextvalue:TapSomeTextHere!rect:{{20,179},{280,31}}

|||+-UIAStaticText:name:Thetextis:value:Thetextis: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:Firstvalue:1rect:{{2,432},{156,48}}

||||+-UIAButton:name:Secondrect:{{162,432},{156,48}}

你可以通过下面的代码来访问文本框:

vartextField=UIATarget.localTarget().frontMostApp().mainWindow().textFields()[0];你可以选择通过从0开始的索引或者这个元素的名称来访问这个元素,例如:你也可以通过下面的代码来访问文本控件。

vartextField=UIATarget.localTarget().frontMostApp().mainWindow().textFields()["UserText"];后一种方式更加清晰明了,应该多使用。你可以通过InterfaceBuilder设置UIAElement的name属性,

或者通过编写代码的方式:

myTextField.accessibilityEnabled=YES;myTextField.accessibilityLabel=@"UserText";你现在可以看到,通过accessibility属性可以被UIAutomation用来找到不同的控件。这非常的清晰,因为,第一,你只要学习一个测试框架;第二,通过编写自动化测试代码,你同时还可以保证你的程序是可以被访问的。因此,每一个UIAElement对象的子控件可以通过下面的方法进行访问:

buttons(),images(),scrollViews(),textFields(),webViews(),segmentedControls(),sliders(),staticTexts(),switches(),tabBar(),tableViews(),textViews(),toolbar(),toolbars()等等……

你可以通过如下代码在tabbar上访问第一个tab:

vartabBar=UIATarget.localTarget().frontMostApp().tabBar();vartabButton=tabBar.buttons()["First"];UIAElement结构层次非常的重要,你以后会常常用到它。而且你还要记住,你可以在随时通过调用UIAAplication的logElementTree来获得它的结构。

UIATarget.localTarget().frontMostApp().logElementTree();在模拟器上,你还可以激活Accessibility的检测器。启动模拟器,找到“Settings>General>Accessibility>AccessibilityInspector”,然后将它设为“打开”状态。

这个彩色的小框框就是Accessibility检测器了。当它收起来的时候,Accessibility就被关闭了,当它展开的时候,Accessibility就是打开的。你只要点击上面的箭头按钮就可以激活或者屏蔽Accessibility。现在,打开我们的示例程序,激活检测器。

然后,点击文本框,检查UIAElement的name和value属性(其实就是accessibilityLabel和accessibilityValue对应的NSObject类型的值)。这个检测器可以帮助你调试和编写你的测试代码。

模拟用户操作

让我们更进一步,模拟一些用户的交互操作。你可以简单地调用按钮的tap()来作一个点击操作:

vartabBar=UIATarget.localTarget().frontMostApp().tabBar();vartabButton=tabBar.buttons()["First"];//Tapthetabbar!tabButton.tap();你还可以调用UIAButtons的doubleTap(),twoFingerTap()。如果你不想操作具体的某个元素,你也可以直接根据屏幕上指定的坐标点进行操作,你可以这么用:

现在,让我们来练习一下:

下面是Test-1.js代码:

你还知道了如何访问键盘上的按钮,然后作点击操作:

本文由知平软件的DawsonLiu翻译,转载请注明出处。

知平软件致力于移动平台自动化测试技术的研究,我们希望通过向社区贡献知识和开源项目,来促进行业和自身的发展。

==============================

翻译:子玉冰,JX,为爱西行,杰西,bennaReview:蓝羽

所有的开发人员都需要测试他们的软件,并且,许多聪明的人为此创建了测试套件。测试套件是一组测试用例,也被称为单元测试,针对小“单元”代码,通常是一个特殊的方法或者类。

所以,如果你能设置一个系统能自动构建、测试,然后提交你的应用程序到测试人员,你会感兴趣吗?如果会,那么继续阅读吧!

GitHub-公共免费Git存储库,合作者管理,问题追踪,维基,下载,代码评审、图形,还有更多功能。

在本教程中,您将创建一个自动化的构建和测试系统GuildBrowser。GuildBrowser是一个简单的应用程序,允许您从受欢迎的游戏《魔兽世界》里浏览一个公会的成员们。您可以输入一个工会和一个域名看到UICollectionViewController上所有成员列表,正如你下图所示:

这个应用程序是由暴雪免费提供的魔兽世界API驱动的。您将使用AFNetworking框架对WOWAPI进行平稳的调用、获得JSON数据,这些数据包含工会和角色信息。

开始

在这篇教程中首先你将在GitHub上建立一个远程存储库。它将是你的远程“原始”存储库。它允许你在本地照常工作,并且当你准备与团队成员同步或发送一条新的构建给测试人员时,你将把所有你的本地修改提交到这个存储库。

尽管没有为原始地址输入密码,不过不要慌张。你会使用Git的SSH来进行访问,所以不需要密码。

你现在已经建立好了一个远程存储库!当然你也可以使用同样的步骤来为其他所有的Xcode工程进行设置。虽然远程存储库已经建立好,但是你仍然没有从本地Git存储库推送任何文件到远程Git存储库。我们接下来使用Xcode来完成这个任务。

回到你的工程,首先确定你已经提交了所有的本地修改。如果你有修改没有提交,那么Xcode将不允许你推送的远程存储库。下面是具体的步骤:

一旦推送完成,回到浏览器中,刷新界面,你提交的修改应该会显示在你的GitHub存储库中:

恭喜你,你已经学会如何将本地Git存储库连接到GitHub上的远程存储库,并将本地修改推送到远端。

持续集成

安装Jenkins

有几种不同的方法可以在Mac安装Jenkins:

1.你可以使用Jenkins网站上的安装器,它会作为守护进程启动并且运行Jenkins。这种方式很不错,因为它采用了MacOSX系统本身的启动系统,但是它会导致你需要做更多的步骤,才能让Xcode的编译正常运行。

2.你可以在终端里使用WAR文件(Java打包文件类型),它会用内建的servlet容器winstone来运行Jenkins。

3.你可以把WAR文件部署到你已经建立的应用容器内,比如Tomcat、JBoss等。

注:以上的命令是假设你的JenkinsWAR文件在你的下载目录里。如果你把WAR文件下载到了不同的目录,需要相应地更改命令中的路径。

注:你可能会发现为启动Jenkins创建一个别名是很有帮助的。在终端里,或是文本编辑器中显示隐藏文件,打开/Users/(username)/.bash_profile并且输入以下几行:

保存.bash_profile,打开一个新的终端,然后输入jenkins来启动Jenkins。

这会在8081端口上启动Jenkins服务。nohup是一个UNIX的命令,它可以让一个进程在你登出或是shell退出的时候,仍然保持运行状态。

以上的命令也会在/tmp/jenkins.log文件中记录日志。我会尽量去配置与已有的服务不冲突的端口。在浏览器中打开以下URL就能进入Jenkins:

配置Jenkins插件

这个就是你想要的:

当它完成安装后,你就可以看到以下界面:

现在在筛选框中输入ChuckNorris,然后找到ChuckNorris引用插件。

注:我的朋友叫我Charlie,但是我的真实名字是Charles。我父亲的中间名字叫做Norris。所以我曾经正式地宣称要把我的儿子命名为ChuckNorrisFulton…但是不幸的是我老婆没让我这样做:)

设置Jenkins的邮件通知

现在你可以收到来自Jenkins关于编译失败的通知。

创建一个Jenkins任务

注:ChuckNorris的程序没有版本号,因为他只写一次。如果用户反馈了一个bug或是一个需求,他们不会活着见到太阳升起的。

不要忘了点击保存按钮

如果一切正常,编译#1应该为蓝色,表示编译成功。

你的终端输出应该如下图所示,说明代码已从GitHub存储库导出到本地。

至此,你已经连接上GitHub,并且设置了邮件通知。下面紧接着我们来添加一些感兴趣的功能:测试,编译和上传项目工程到TestFlight。

Jenkins自动Xcode编译

在命令窗口输入下列代码:

你的代码窗口应该如图所示:

如果你错过了弹出的提示(例如,你正在追逐拿走你iPhone的两岁小孩^_^),你将会在终端输出中看到如下信息:

如果这发生了,重新运行项目,但是这次不要再错过提示(或者再不要让你两岁小孩拿走你的iPhone)。

当撰写这篇博文时,我真的不得不用findmyiPhone来定位我的iPhone。这个小家伙已经把手机塞进他玩具车的后备箱里!!

假设你没有错过提示,那么你会看到输出如下所示:

注:有一款叫做Xcodeplugin的用来构建iOS软件的Jenkins插件,它很不错,但我认为最好了解程序编译期间发生了什么。你可以用一些自己的编译脚本来达到与插件相同的效果。

更重要的是,依赖插件会带来一些风险。假设Apple改变运行机制,导致插件运行不正常,并且插件不再提供更新,如果你知道运行的来龙去脉,那么你依然能够适应。

单元测试

单元测试可以确保正在开发时代码输出保持不变。在建立了一个类将要做什么的期望后,我们编写单元测试以验证这些期望是否正确。单元测试也可以让你逐步看到输出,来逐步修改代码,这使得开发新功能和作大的修改更容易。

在项目中运用单元测试的另外一些好处是:

稳定性–一旦发现bug,可以加入新的测试,以确保相同的bug不再发生。

Xcode在SenTestingKit框架中内置了单元测试。当编写单元测试时,需注意以下两个方面:

应用程序VS逻辑测试target

接下来看一下Xcode中两种可用的类型不同的单元测试。

应用程序单元测试

应用程序单元测试基本上指需要使用UIKit控件或者在主应用程序环境中运行的任何代码。当创建一个包含单元测试的新项目时,这种类型的单元测试target是你得到的默认类型。

逻辑单元测试

从命令行运行测试,注意——没有触摸!

不幸的是,自Xcode4.5起,我们不被“官方”允许通过xcodebuild命令运行应用程序单元测试。这令人沮丧,因此你显然能在Xcode中运行应用程序的单元测试。因此,你将在下一节创建一个特定的逻辑测试target。

一些有创意的开发者已经针对Xcode.app内容中的测试脚本做了补丁。本教程中,你将坚持通过Jenkins运行你的逻辑测试并且通过Xcode运行应用程序测试。如果你对那些补丁很好奇,可以看看这些文件:

你将会得到一个错误信息,因为我们不能在模拟器中通过命令行工具运行应用程序单元测试(记住这在Xcode中能成功执行)。

一些聪明的骇客已经能运行应用程序测试,但是从Xcode4.4到Xcode4.5,脚本已经改变了,如果这么做的话结果需自己负责。

添加逻辑测试target

现在你要创建一个新的测试target用于你创建的脚本调用。

你应该看到构建成功了,但是测试失败了

根据错误信息的显示,单元测试还未被实现。让我们去修正它!

你的屏幕应该看起来像这样:

你现在准备好给你的测试target添加单元测试类。接着你就能通过jenkins任务调用这个target。在这个盛宴的下一部分你会做到这些。保持学习欲望……和不满足!

何去何从?

在这几天,我们将发布这个教程的第二部分。同时,如果你有任何问题和意见,请加入如下的论坛讨论!

THE END
1.快速记忆英语单词的方法和技巧英语单词记忆方法记忆法3遗忘速度快:即使暂时记住了单词,但由于缺乏有效的复习和应用,单词很快被遗忘。为了解决这些难题,我们推荐使用“英乐通”小程序,这是一个专为英语单词记忆设计的智能学习工具。它通过科学的记忆方法和趣味的学习方式,帮助孩子在短时间内快速提升单词记忆能力。1科学记忆法:采用艾宾浩斯遗忘曲线原理,通过智能算法安排复习https://m.163.com/dy/article/JIG5C9UB0556AN3J.html
2.一种崭新的长尾分布下分类问题的通用算法NeurIPS2020三.Recipe (快速食用指南) 在介绍本文复杂的因果图构建和后续推导实现,让同学们失去耐心之前,对于想赶紧快速食用我们方法的同学,我给个4步速成指南吧: 1)训练时需要De-confound Training,说人话就是classifier需要使用multi-head normalized classifier,即每个类的logits计算如下:,其中是超参,K是multi-head的数量。分https://blog.csdn.net/zandaoguang/article/details/108878239
3.自制小蛋糕的做法自制简单快速的小蛋糕自制小蛋糕怎么做拿出来时,要小心哦,很烫的 小窍门 1、我这里用的蛋糕粉,超市都有的卖,我只用了一小包,又和面粉加在一起的,本来是一包蛋糕粉加一个蛋,我加了两个蛋,又加了普通的面粉,这样做出来量会多出一半。 2、加了面粉后记住白糖要加一点,否则不够甜的 来自 美食天下槡树https://home.meishichina.com/recipe-129149.html
4.智慧让你的家常菜肴更加迷人SugarVinegarPorkRibsRecipe如果条件允许的话,那么直接放置24小时甚至更长时间都会是不错选择,但请记住,如果超过48小时,那么可能会导致肌肉变硬因此需要适当调整腌制时间以避免发生这样的问题哦! 烧开水: 在进行焯水之前,你应该把所有腌制好的五花肉全部放在大锅里,用冷水淫没,然后用火点燃木炭等燃料加热直到水开锅翻腾时倒入其中再快速煮沸5https://www.hgddesks.cn/zi-xun/562661.html
5.第四章:自己动手指南(学习的革命)书评(The1000RecipeChineseCookbook)的每一页,你只读你需要了解的内容。单单这一提示就会帮助你在浏览一份报纸所需的等量时间里读4本书。 另一提示:不要“慢条斯理、不慌不忙”地读。马上往窗外看一下,然后想一下你大脑能马上吸收所有这些信息的神奇能力。记住你每只眼睛中都有1.3亿个光接收器,记住这些光接收器https://book.douban.com/review/1408857/
6.UNIX环境编程GCC编译器Makefile基础入门GDB调试把它看成是 recipe 的简单表示,而不是实际文件的名称。这里的 recipe: rm $(target) $(objects) 1. 删除目标文件和当前目录下的所有对象文件。 为什么使用 PHONY?为了避免意外情况!比如:如果你的一个文件叫 clean 怎么办? 【一个经常出现的错误】 https://blog.51cto.com/u_15153240/6150687
7.张某很快速的按照recipe手册建立完成,并准确得到了测量结果。以上刷刷题APP(shuashuati.com)是专业的大学生刷题搜题拍题答疑工具,刷刷题提供张某很快速的按照recipe手册建立完成,并准确得到了测量结果。以上描述了体现了作业观察中的哪几项()。A.执行B.熟练C.分歧D.结果E.异常的答案解析,刷刷题为用户提供专业的考试题库练习。一分钟https://www.shuashuati.com/ti/f39c473f3de0442abb9b3b3635dfea8f.html?fm=bdbds451929a85fae6acf3ec52ca4595c742f
8.recipe芦荟胶喷雾怎么用recipe芦荟胶喷雾使用方法recipe芦荟胶喷雾怎么用 这款芦荟胶喷雾近喷和远喷的质地是不一样的,近喷喷出来是泡沫的质地,远喷喷出来是水雾的质地,水珠比较分散,主要看自己是要怎么使用,近喷远喷都是可以的。这款芦荟胶喷雾可以随身携带,随时随地拿出来喷一喷,化妆前喷一喷可以快速补水保湿,缓解肌肤敏感脆弱的状态。皮肤https://zhidao.baidu.com/question/2084129317033976548.html
9.AIRecipeGeneratorGPT商店AI工具集导航1000+AI工具导航AI Recipe Generator食谱生成器提供了一个快速和简单的方法来创建自定义食谱。你所需要做的就是创建一个账户,输入你家里的食材,网站就会把一份独特的食谱发送到你的电子邮箱。 AI Recipe Generator食谱生成器提供了一个快速和简单的方法来创建自定义食谱。你所需要做的就是创建一个账户,输入你家里的食材,网站就会把https://www.tuidog.com/sites/20651.html
10.reception什么意思怎么读?单词用法记忆法发音音标反义词单词:reception发音、音标、怎么读? reception 音标:[ri'sep?n] 你的浏览器不支持播放 单词:reception的单词意思解释释义 n. 接待, 接受, 招待会【医】 接受, 感受【经】 接待, 接收, 接受 单词:reception的快速记忆法 ◆记忆方法一:谐音:若赛跑胜 若赛跑胜利,将受到热情的接待。◆记忆方法二:联想https://english.downyuan.com/index.php?m=home&c=View&a=index&aid=y1507
11.快速编译第三步出现问题·Issue#88·c停止。 make[1]: 离开目录“/home/akira/code/test/buildroot/buildroot/buildroot-ded3f9954f158b5d9cd08ae76749eade72fcca3a” Makefile:52: recipe for target 'all' failed make: *** [all] Error 2 从错误信息看,似乎是要make menuconfig,明天试试看。 make CONF=thead_610_compat_next_glibc_br_https://github.com/c-sky/forum/issues/88
12.HealthyFoodRecipes&EasySmartCookRecipeDiet- 最好的着名和受欢迎的食谱。 - 每个食品食谱写一个简单的方式,让读者可以享受,并尝试做饭。 - 高品质的春天动画图像和照片使用,所以读者可以下降凉爽和放松。 - 最适合所有年龄组的人,孩子或老年或大学和大学生 - 您可以将食谱添加到您的“收藏夹列表”快速找到他们。 https://apps.apple.com/cn/app/healthy-food-recipes-easy-smart-cook-recipe-diet/id1178330848