ui自动化和接口自动化化可以取代ui自动化吗

自动化测试之小心做UI自动化一定要跨过这些坑
UI自动化,在移动互联网时代的今天,一直都是在各大测试测试社区最为火爆的一个TOPIC。甚至在测试同行面前一提起自动化,大家就会自然而然的问:“恩,你们是用的什么框架?appium?还是robotium?”
其实在笔者看来,UI自动化是一个ROI较低的测试项(ROI即return on investment,中文意思是投资回报率)。但UI自动化相比接口自动化、白盒测试等,它更贴近手工业务测试行为。对于刚起步测试左移、效率提升的团队来说,是最迅速的切入点,也是广大黑盒tester,提升自身技术能力的起跑线。
笔者接触UI自动化一年多,兼顾业务测试的同时断断续续地投入,曾经无数次的想放弃:
“才刚写完用例,怎么开发大哥又改了UI了?”
“维护这些破用例的时间,都够我手工测三遍了,真的有意义么?”
“测试框架自己有bug,我改用例也没用啊……”
“我调试的时候这个用例还是通的,放到daily里面跑就不通,到底怎么回事嘛!”
“adb怎么这么不稳定啊,老是断!!!”
“怎么跑着跑着就crash了,到底是被测应用有问题,还是测试代码有问题啊?”
“明明界面上有这个元素,怎么就是查不到呢?”
“这破手机,能不能别老是系统弹框……”
“这手机真是渣,adb screencap截个图,居然要三分钟才返回!”
“这些控件都没有id,没有text,层级还三天两头改,要我怎么查……”
“查了这么多论坛,怎么就没有人遇到过类似的问题呢?”
这些问题让笔者一度怀疑,UI自动化这个TOPIC,是不是根本没用,只是tester为了涨薪,或者为了摆脱重复无聊的手工业务测试,而YY出来自我欺骗的。
二、问题分类及目标明确
笔者将以上所有的问题简单分成三类:设计类、环境类、细节类。一个好的设计模式,能够避免一部分问题;一套好的环境,可以让我们从乏味的维护工作中解脱;精益求精的细节,让测试用例更加可靠稳定。
图一UI自动化常见问题
填掉这三类坑,基本上就获得了一套低成本高产出、少量维护、稳定可靠的UI自动化用例集。
三、设计类问题分析与解决
“才刚写完用例,怎么开发大哥又改了UI了?”
“测试框架自己有bug,我改用例也没用啊……”
这类问题,我们需要从根上治。UI自动化开发,也应该是严谨的开发工作,它也需要设计模式,也是磨刀不误砍柴工。这里的设计,主要包括选工具、框架分层等。很多前辈都分析过UI自动化各类工具的优缺点,对工具选用笔者不再赘述。主要依托uiautomator来介绍下笔者认为比较巧妙的用例框架设计。
1、优化测试代码框架
无论你选择appium、uiautomator、robotium还是espresso,刚入门时,看到的sample应该大致都是这样的。
图二 uiautomator和espresso逻辑样例
问题在哪里?这些sample过于简单,都只教了我们UI自动化三元素:怎么查找元素、怎么操作元素、怎么校验结果。如果我们按照大多数分享帖或GitHub sample来写作自己的case。最后这种没有任何设计模式的框架,肯定会面临重构。拿上面的espresso来说:
1.假如action_save这个id开发改了,而你的用例集中,有30个步骤用例到了这个id,一个个去改,是不是要疯?
2.不厌其烦的重复写onView(withXX(xxx)).perform(click())这一长串,你不烦?
笔者是如何做的呢?
分层设计和PageObjects模式。这两个方法,基本解决了笔者遇到的图一中所有的设计类问题。
图三 框架设计建议
按照图三进行分层设计后,得到如图四的测试代码包。
图四 分层后的用例框架
PageObjects模式发源于selenium社区,它的目的是减少重复代码,当开发修改UI时,测试只需在有限的位置修改代码。如果大家想深入了解PageObjects,请参照如下wiki:
(/SeleniumHQ/selenium/wiki/PageObjects
http://blog.csdn.net/kittyboy0001/article/details/)。
我们来看一下,现在手管首页Page包中的代码和页面。
图五 手管首页Page层部分代码
回忆一下上面的google提供的sample,再对比引入分层设计和PO模式前后的代码,点击图五中的一键加速:
图六 引入PO前后代码对比
带来的好处,当然不仅仅是业务用例代码更清爽。
1、通过将查找和操作封装到基础层中,这部分代码就具体业务无关了,即使拿到其他产品中也可以复用;
2、通过page层的分离,所有的与业务相关的id,text等都被限定在了page包中,哪怕开发改了UI,修改page包特定的页面中对应的元素就好了。
3、对page包进行合理的业务拆分,比如将手管分成 MainPage(主页),SoftwareManagerPage(软件管理页),WiFiManagerPage(WiFi管理页)等,在开发改了某个具体业务的界面后,测试能够迅速知道测试代码需要改哪里。
2、兼容资源混淆的测试代码
除了整个框架的设计,有时候一些小问题也可以经过巧妙设计。比如资源混淆的问题。
图七 资源混淆
如图七,在手机管家的发布包中,用uiautomatorviewer dump下来发现,一键优化的button,其resource-id是o3,但其实开发coding时,定义的id显然不会用这种没有任何字面意义的代号,它在混淆之前叫optimize_button。
纯黑盒的UI自动化,也许你会摒弃optimize_button,直接写o3,但这样显然不够科学,既带来了严重的代码可读性问题,同时一旦版本迭代,混淆变了,o3也许就变成了o4。或者你会让开发给你测试的包,不要混淆,但如果想用UI自动化测试已发布的apk呢?
解决该问题,也得从PageObjects说起。回到图五中OPTIMIZE_BTN的定义,这个静态变量并未在page中初始化,只有一个@FindBy的注解。其实,在框架层驱动测试开始前,框架会先调用如下图八所示的setAllField来初始化所有的page页面。
1、如果被测应用未混淆资源,该方法只是将@FindBy中的值赋值给Field。
2、如果被测应用已混淆资源,该方法则会从mObfuscationMap(未贴出全部代码,实际是解析一个开发提供的混淆表,以原始id为key,混淆id为value的HashMap)中读出对应的id对应关系,将混淆后的id赋值给Field。
图八 Page层动态初始化
四、环境类问题分析与解决
“adb怎么这么不稳定啊,老是断!!!”
“明明界面上有这个元素,怎么就是查不到呢?”
“这破手机,能不能别老是系统弹框……”
“这手机真是渣,adb screencap截个图,居然要三分钟才返回!”……
引子中提到的这些问题,根据经验,多半你的环境执行环境还不够稳定。
1、ADB相关问题已知的ADB不稳定原因如:电压不稳,各类手机助手的干扰,系统版本与ADB版本不匹配、ADB crash等等。如果我们迎难而上,去重写ADB,投入将无限扩大。所以建议主要的解决方案,还是尽量规避。
1)、选用可靠硬件规避电压不稳定。github上的STF项目组有过成熟的经验,选用性能更优的USB分接器,电压和可靠性会有更稳定的表现。(附上链接,wiki Recommended hardware一节中有不同硬件详细的性能对比:/openstf/stf)。
2)、屏蔽各类手机助手的干扰。91助手、豌豆荚等,基本都在adb上做了二次开发,它们会与原生adb间有兼容性问题。建议直接使用Linux/MAC系统作为运行环境以屏蔽这类干扰。
3)、降低用例在执行过程中对环境的依赖。Appium这类自动化工具,每一个测试步骤都需要PC端的appium server和测试手机端的bootstrap交互消息。测试过程中只要USB连接不稳定,都会导致整个测试套的失败。所以笔者认为,使用更原生的uiautomator会是更好的选择;同时,测试过程中的日志、截图等,也尽量在测试手机上做持久化。
2、弹框问题的解决
权限弹框,是手管UI自动化中的一个大坑。如下图,是测试手管过程中,在华为手机上遇到的部分权限弹框。这些弹框,并不会用例每次执行都弹出,不同厂商的弹出框也不一致。显然点击弹框的逻辑,写在case逻辑中,只会导致自动化变得更复杂更不稳定。
图九 各类权限弹框
uiautomator的watcher,能够完全实现点击弹框和用例逻辑的解耦。当前笔者的实现逻辑是,监听弹框上的某个控件,当该控件出现时,执行action来点击掉其中的取消或确定按钮。这样,用例就只需关注业务逻辑,而任何时候的弹框,都由watcher来自动点击。如下图中,checkForCondition关注条件,action是操作。
图十 查找型Watcher
将所有的watcher分不同的手机厂商进行注册后,再调用runWatchers(),然后再执行用例。该方法可以在@BeforeClass中或者RunListener的testRunStarted中调用。当然,如果某个用例不想某个具体的弹框被watcher点击掉,也可以调用removeWatcher()反注册。
图十一 注册监听器
Watcher并不能解决所有的弹框问题。例如,在开启WiFi的场景中,由于WifiManager的setWifiEnabled和UI上的弹框点击是同步的(意思是调用了setWifiEnabled之后,如果界面上不点允许,该方法是不会返回的),使用上面的watcher方式并不会点击WiFi权限申请的允许。这时,就需要用到线程方式来解决(如下图十二),调用setWifiEnabled前,先启动一个线程等待弹框弹出。
图十二 多线程方式点掉弹框
五、细节类问题分析与解决
“我调试的时候这个用例还是通的,放到daily里面跑就不通,到底怎么回事嘛!”
出现上述问题,多半是因为我们的用例细节不够严谨。这类问题,往往决定着我们自动化用例集,是不是能从90%的case通过率,提升到100%。
1、顺序逻辑的用例
自动化相比手工,它只会关注code告诉它的验证点,所以选择逻辑在用例中应该是禁用的。如下图十三中右侧的case,如果用例执行到if中,也许else流程中存在BUG,反之亦然。此时考虑拆分用例,左侧才是理想的用例逻辑。
图十三 用例逻辑
另外,写作case时,一定要牢记,只有我们告知程序要assert,它才会去assert。查找,操作,断言,UI自动化三要素缺一不可。
2、解耦的用例
在testng中,会提供dependsOnMethods注解,似乎在鼓励写作用例时,使用用例间依赖。但笔者认为,用例间的依赖,会带来不必要的维护成本。只有高度解耦的用例逻辑,才能够更加健壮的支撑用例执行顺序调整、用例增删、出现异常场景后,A用例失败不会导致B用例也失败。
3、优化等待
有时候会遇到以下场景,虽然原生的自动化工具提供了等待元素可见的方法,但使用起来,还是无法真正等到元素可见。针对这个问题,如下图的waitCondition方法是一个不错的方案,它相对于thread.sleep来说,更节省时间。
图十四 反复等待方法
4、不用绝对坐标点击绝对坐标点击,在不同尺寸屏幕上无法兼容。
第一方案应该是,推动开发对需要用到的控件添加ID或Accessibility。但根据经验还是会有一些场景需要用到坐标点击:
1、考虑投入产出比,为所有控件添加id的成本过高;
2、动态布局添加的ID都一样;
3、存在非xml布局的界面(代码中直接布局)。
这时,笔者依然不建议mDevice.click(100,200)这样的坐标点击。有以下两种值得一试的方案。
1、找到相邻控件坐标,计算当前控件的绝对坐标。如下图十四,uiautomatorviewer中点击右上角警告小三角,会得到有一些元素(黄色控件),是可能无法找到的。而使用相对坐标就是说,我们可以获取它相邻控件的坐标,然后减去或加上一个比较小的px值,再点击计算后的坐标即可。
图十五相对坐标
2、使用屏幕尺寸计算相对位置。在测试开始,将屏幕尺寸存下来,使用百分比的方式计算得到需要点击的位置。如下代码,点击【50%屏幕宽度,80%屏幕高度】的位置。
CODE: mDevice.click( screenWidth/2 , screenHeight*80/100 )。
UI自动化测试是一门学起来很简单,用起来很麻烦的测试技术。
想要入门,两周就可以了解清楚uiautomator或espresso这类工具。UI自动化,无非就是查找元素、操作元素或设备、验证结果。这三个步骤循环多次,就是一个用例。
但要用好,并产出能效,需要走的路其实很长。由于篇幅限制和知识有限,这里不可能把所有的问题一一列出。对于所有这些问题,无非两个思路:一是绕过,二是解决。
1、选一个尽量简化,尽量底层的工具(uiautomator或espresso),从根上绕过一些工具会存在的问题;
2、采用良好的设计模式,让自己的框架更稳定,生命周期更长,维护成本更低;
3、明知道会耗费很多时间精力,收效却很小的环境问题,尽量绕过;
4、优化用例逻辑和细节,使之稳定可靠,更能说服别人相信自动化的测试结论。
不知您是否也曾在UI自动化过程中遇到过难以解决的问题呢?
欢迎大家留言讨论。
也祝愿大家在UI自动化的道路上越走越顺!
将我们公众号置顶 不会漏掉我们的原创干货哦!
责任编辑:
声明:本文由入驻搜狐号的作者撰写,除搜狐官方账号外,观点仅代表作者本人,不代表搜狐立场。
今日搜狐热点UI自动化,你值得拥有 - Flyleaves - 博客园
  去年春节联欢晚会,为了那张&敬业福&,全家都卯足了劲儿&咻一咻&,连节目都顾不上看了。当时我就想,要是能自动化该多好,不停点击屏幕,屏幕不疼手还疼呢,何况还不好分心,生怕错过了&敬业福&。玩&咻一咻&,是靠不停点击按钮来检查是否得到&敬业福&,而工作中的UI自动化,大抵也和&咻一咻&差不多,都是通过不断地输入,验证系统的输出是否正确。然而做UI自动化,效果并不好,收益低就算了,执行速度还慢。比如打开一个浏览器,可能就要等3-5秒,如果等浏览器访问网址,返回网页内容,就需要更长的时间。要是遇到问题,还要排除各种干扰才能定位。而要是做接口或者单元测试,不但定位问题范围小,响应也基本都是毫秒级的,即使遇到慢的,差不多1秒钟也能返回结果了。这么一对比,UI自动化就像是一件吃力不讨好的事儿,所以去做UI自动化,大概是因为它独特的角度:从用户体验来验证系统的正确性。  要做UI自动化,以web方向来说,要是有一个好框架,就方便多了。如果编程基础好,可以自己写框架或者修改现有框架,封装常用业务逻辑和代码,提高测试效率。要是不会编写框架,也可以使用开源的工具,比如Robot Framework,它既支持关键字驱动、数据驱动,也支持接口测试,在官网稍做学习,就能初步使用。要是既不会写框架,也不会用工具,那你也可以看看吴老的《Selenium WebDriver实战宝典》,里面有很多小实例,比如操作下拉框、输入框等等。有了这些小实例,你就可以把它们复制到文档,形成一个有目录的代码库。这样即使你不会封装代码,也能在需要的时候找到它,再修改下常用的参数,就能实现一个简单的自动化测试了。
  挑选UI自动化用例也有讲究,一般都选择比较稳定、重要的功能作为切入点,要是易于编写就更好了。但一提到项目改版,UI经常首当其冲!可能改动特别大,有时候与其维护自动化用例,还不如重新写。遇到这种大刀阔斧地改变,代码库的优势就很明显了,它形式灵活,可以根据需要随时组装,极大地加快了编写速度。并且随着小代码块的积累,组合代码块的经验也不断增长,当尝试去封装函数,进一步提高代码的复用程度时,一些小的框架设计思想也会随之出现。这样循序渐进,在实践中思考总结,不断优化学习,汲取一些先进的实现思想,慢慢地,UI自动化会做的越来越好。  有朋友说:&手工测试都来不及,哪有时间做自动化?&话虽如此,但抽出时间,做一些局部自动化,提高测试效率,还是很值得的。比如准备测试数据,就要进行大量的重复操作。手工制造上百条数据,可能需要大半天。而使用自动化来实现,在编完代码的那一刻,你就已经解放了!数据源源不断地涌出,只要运行几分钟甚至更短的时间,我们就能完成目标!所以学习UI自动化,总会有用武之地。如果现在还不会,可以慢慢学,千万不要因为现在做的不好,就半途而废了。在工作中,我们可以和同事相互鼓励,一起学习和探讨,甚至带动整个测试团队一起提高,一起进步。希望大家都能使用自动化,为自己争取到更多的福利!
  ---记光荣之路吴老4月9日清晨分享
作者:出处:参考声源:本文版权归作者、微信公众号光荣之路和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。自动化UI测试
使用自动化工具来自动化用户界面测试你的iOS应用程序通过测试脚本编写。 这些脚本模拟用户操作通过调用UI自动化、一个JavaScript编程接口,指定要执行的动作在你的应用程序运行。 在测试过程中,系统日志信息返回给你。
UI交互的自动化测试时,您免费其他工作的关键人员和资源。 这样你最小化程序错误,缩短开发产品更新所需的时间。
本章描述了如何使用仪器的自动化模板执行脚本。 它还描述了如何网与UI自动化脚本编程接口来验证应用程序可以执行以下操作:
访问它的UI元素的层次结构
添加时间灵活性通过超时时间
日志和验证返回的信息工具
妥善处理警报
优雅地处理设备的变化方向
处理多任务
当你完成这一章,寻找更多关于每个类的详细信息&。
自动化仪表的一个重要的好处是,您可以使用它与其他工具来执行复杂的测试,如跟踪内存泄漏和隔离性能问题的原因。
注意:&自动化仪器仅适用于应用程序代码与开发配置概要文件签署。 应用程序与分布配置概要文件签署不能与UI自动化自动化编程接口。
重要的是:&模拟操作可能不会阻止测试装置auto-locking。 在设备上运行测试之前,您应该将Auto-Lock偏好设置为从不。
编写自动化测试脚本
您的测试脚本必须是一个有效的可执行JavaScript文件访问主机上的仪器。 因为外面的脚本运行你的应用程序,您正在测试的应用程序版本可以你提交的应用程序商店。
因为每个应用程序都是不同的,通常为一个应用程序是一个脚本不能接受在另一个应用程序使用。在这种情况下,您可以创建自己的脚本里面的仪器。
创建一个脚本
创建一个脚本后,您想要使用它在你的应用程序的开发。这可以通过导入保存的脚本和自动化仪表运行它。&图十一&显示了一个使用脚本运行完成。
图十一&通过脚本运行iOS应用程序
测试自动化脚本
你在JavaScript编写自动化测试,使用UI自动化JavaScript库指定动作应该表现在你的应用程序运行。
您的测试脚本必须是一个有效的可执行JavaScript文件访问主机上的仪器。 外面运行你的应用程序,所以测试版本的应用程序可以是相同的版本,您提交到iTunes应用程序商店。
您可以创建尽可能多的脚本,但是一次只能运行一个。 这个API提供一个&#进口&指令,允许您编写更小、可重用的离散的测试脚本。 例如,如果你是定义在一个文件中常用的函数命名&TestUtilities.js&这些功能,你可以使用在您的测试脚本,包括脚本
#进口&& path-to-library-folder & / TestUtilities.js&
导入以前保存的脚本
自动化跟踪模板执行一个脚本,模拟用户界面交互的iOS应用程序启动仪器。 它只包括自动化仪表。
配置自动化仪表自动控制启动和停止脚本工具栏中的工具记录的按钮,选择复选框的运行记录。
如果你的应用程序崩溃或背景,您的脚本被阻塞,直到应用程序再次frontmost,此时脚本继续运行。
重要的是:&您必须显式地停止记录。 完成或终止您的脚本不关掉录音。
访问和操作UI元素
Accessibility-based机制UI自动化特性代表了每一个控制在你的应用程序作为一个独特的识别元素。 执行一个操作在你的应用程序的一个元素,您明确地识别该元素的应用的元素的层次结构。 为了充分理解这一节中,您应该熟悉的信息&。
本节说明元素层次结构,指的是菜谱iOS应用程序所示&图成分&的代码示例&从iOS开发中心。
图成分&菜谱应用(食谱屏幕)
UI元素的可访问性
每个访问元素从基本元素是遗传的,&UIAElement&。 每个元素可以包含零个或多个其他元素。
如下详细,脚本可以访问单个元素在元素的位置层次结构。 不过,您可以通过设置每个元素分配一个唯一的名称标签属性并确保可访问性是选择界面构建器的控制为代表的元素,如所示&图取得&。
图取得&设置可访问性标签界面构建器
UI自动化使用可访问性标签(如果它是集)获得一个名称为每个元素属性。 除了明显的好处,使用这样的名字可以极大地简化您的测试脚本的开发和维护。
四个属性的名称属性是这些元素,可以在您的测试脚本中非常有用。
的名字。&来自易访问性的标签
价值。&当前值的控制,例如,一个文本字段中的文本
元素。&任何子元素包含在当前元素,例如,细胞在表视图中
的父母。&包含当前元素的元素
理解元素层次结构
顶部是元素的层次结构&UIATarget&类,它代表了高层用户界面元素的被测系统(SUT),即设备(或模拟器)以及iOS应用程序上运行的设备。 出于测试的目的,你的应用程序是frontmost应用程序(或目标应用程序),确认如下:
UIATarget.localTarget().frontMostApp();
达到应用程序窗口,应用程序的主窗口中,您将指定
UIATarget.localTarget().frontMostApp().mainWindow();
在启动时,菜谱应用程序窗口所示&。
在窗口中,菜谱列表提出了个人的观点,在这种情况下,表视图,请参阅&。
图剩下的&配方表视图
这是第一个表视图应用一系列的表视图,因此您指定它使用零指数([0]),如下:
UIATarget.localTarget().frontMostApp().mainWindow().tableViews()[0];
在表视图,每个配方由不同的单个细胞。 以类似的方式您可以指定单个细胞。 例如,使用零指数([0]),您可以指定第一个单元格如下:
UIATarget.localTarget().frontMostApp().mainWindow().tableViews()[0].cells()[0];
每一个个体细胞元素被设计成包含配方记录作为一个自定义子元素。 在第一个细胞是巧克力蛋糕的记录,您可以访问的名字与这行代码:
UIATarget.localTarget().frontMostApp().mainWindow().tableViews()[0].cells()[0].elements()["Chocolate Cake"];
显示元素层次结构
您可以使用&logElementTree&任何元素方法列出它的所有子元素。 下面的代码演示了清单主要的元素(配方)食谱的屏幕(或模式)应用程序。
// List element hierarchy for the Recipes screen
UIALogger.logStart("Logging element tree &");
UIATarget.localTarget().logElementTree();
UIALogger.logPass();
命令的输出捕获日志中显示的自动化仪器,如&图11-5&。
图11-5&输出从logElementTree方法
注意每个元素的数量开始行项目,表明元素的层次的。 这些水平可能认为从概念上说,是&图11:6&。
图11:6&元素层次结构(食谱屏幕)
虽然屏幕不是技术上的iOS编程构造和不显式地出现在层次结构,它是一个有用的概念理解的层次结构。 开发单位转换选项卡的标签栏显示单位转换屏幕(或模式),所示图到第二天早上7点&。
图到第二天早上7点&菜谱应用(单位转换屏幕)
下面的代码水龙头中的单位转换选项卡标签栏显示屏幕,然后记录相关元素相关联的层次结构:
// List element hierarchy for the Unit Conversion screen
var target = UIATarget.localTarget();
var appWindow = target.frontMostApp().mainWindow();
var element =
appWindow.tabBar().buttons()["Unit Conversion"].tap();
UIALogger.logStart("Logging element tree &");
element.logElementTree();
UIALogger.logPass();
由此产生的日志显示中所示的层次结构&图11 - 8&。 与前面的示例一样,&logElementTree&叫做为目标,但当前的结果在这种情况下,单位转换屏幕。
图11 - 8&元素层次结构(单位转换屏幕)
简化元素层次结构导航
前面的代码示例介绍了使用的变量来表示部分元素的层次结构。 这种技术允许短,简单的命令在您的脚本。
以这种方式使用变量还允许一些抽象,产生代码使用和重用的灵活性。 下面的示例使用一个变量(&destinationScreen&)控制改变之间的两个主要屏幕(食谱和单位转换)的配方应用:
// Switch screen (mode) based on value of variable
var target = UIATarget.localTarget();
var app = target.frontMostApp();
var tabBar = app.mainWindow().tabBar();
var destinationScreen = "Recipes";
if (tabBar.selectedButton().name() != destinationScreen) {
tabBar.buttons()[destinationScreen].tap();
只有细微的不同,这段代码代码工作,例如,对于一个标签栏与更多的标签或标签的名字。
执行用户界面的手势
一旦你了解如何访问所需的元素,这是相对简单和直接操纵该元素。
UI自动化API提供了执行大多数UIKit用户操作的方法,包括多点触控手势。 综合这些方法的详细信息,请参阅&。
攻丝。&也许最平易近人的姿态是一个简单的点击。 实现一个手指单点击一个已知的UI元素是非常简单的。 例如,利用正确的按钮,标有一个加号(+),导航栏的菜谱应用程序,显示一个新的屏幕用于添加一个新的配方。
这个命令所需的全部操作按钮点击:
UIATarget.localTarget().frontMostApp().navigationBar().buttons()["Add&].tap();
注意,它使用这个名字&添加&确定按钮,可访问性标签已设置适当的假设,如上所述。
当然,更复杂的利用手势需要彻底测试任何复杂的应用程序,您可以指定任何标准丝锥的手势。 例如,利用一次在屏幕上的任意位置,你只需要提供屏幕坐标:
UIATarget.localTarget().tap({x:100, y:200});
这个命令水龙头在指定的x和y坐标,无论什么在这个位置在屏幕上。
更复杂的水龙头也可以。 手势是相同的位置,您可以使用这段代码:
UIATarget.localTarget().doubleTap({x:100, y:200});
知道并执行一个测试缩放,例如,你可以使用这段代码:
UIATarget.localTarget().twoFingerTap({x:100, y:200});
捏。&一小撮开放姿态通常是用来放大或扩展一个对象在屏幕上,和必要时关闭手势是用来相反的效果放大或缩小一个对象在屏幕上。 您指定的坐标定义的开始捏捏结束关闭手势或开放的姿态,后跟一个动作持续时间的秒数。 时间参数允许您一些灵活性在指定的速度关头行动。
UIATarget.localTarget().pinchOpenFromToForDuration({x:20, y:200}, {x:300, y:200}, 2);
UIATarget.localTarget().pinchCloseFromToForDuration({x:20, y:200}, {x:300, y:200}, 2);
拖动和闪烁。&如果你需要滚动一个表或在屏幕上移动一个元素,您可以使用&dragFromToForDuration&方法。 你提供的起始位置和结束位置坐标,以及持续时间,以秒为单位。 下面的示例指定一个拖动手势从位置160年,200年到160年的位置,400年,在一段时间内1秒:
UIATarget.localTarget().dragFromToForDuration({x:160, y:200}, {x:160, y:400}, 1);
电影的姿态是相似的,但是它被认为是快速行动,所以它不需要一个时间参数。
UIATarget.localTarget().flickFromTo({x:160, y:200}, {x:160, y:400});
输入文本。&您的脚本可能需要测试你的应用程序在处理文本输入正确。 这样做,它可以将文本输入到一个文本字段,只需指定目标文本字段和设置它的值&setvalue方法。 下面的示例使用一个局部变量提供一长串作为第一个文本字段的测试用例(指数[0])在当前屏幕:
var recipeName = "Unusually Long Name for a Recipe";
UIATarget.localTarget().frontMostApp().mainWindow().textFields()[0].setValue(recipeName);
在你的应用程序选项卡导航。&测试之间的导航屏幕在你的应用程序,你很可能需要开发一个标签在一个标签栏。 开发一个标签就像开发一个按钮,您访问适当的标签栏,指定所需的按钮,和水龙头,按钮,如以下示例所示:
var tabBar = UIATarget.localTarget().frontMostApp().mainWindow().tabBar();
var selectedTabName = tabBar.selectedButton().name();
if (selectedTabName != "Unit Conversion")
tabBar.buttons()["Unit Conversion"].tap();
首先,声明一个局部变量来表示标签栏。 使用该变量,脚本访问标签栏来确定所选选项卡并得到标签的名字。 最后,如果选择选项卡的名称匹配所需的标签的名称(在本例中&单位转换&),该脚本水龙头,选项卡。
滚动一个元素。&滚动的很大一部分是与许多应用程序用户的交互。 UI自动化提供了各种方法来滚动。 滚动到下一个元素的基本方法允许左,右,或下降。 更复杂的方法支持更大的灵活性和特异性滚动操作。 其中一个方法是&scrollToElementWithPredicate&,它允许您滚动到您指定的元素,满足某些标准。 这个例子通过元素访问适当的表视图层次结构和卷轴的配方表视图的名称始于&海龟派&。
UIATarget.localTarget().frontMostApp().mainWindow().tableViews()[0].scrollToElementWithPredicate(&name beginswith &Turtle Pie&&);
使用&scrollToElementWithPredicate&方法允许滚动一个元素的确切名称可能不知道。
使用谓词的功能可以大大扩展脚本的功能和适用性。 使用谓词的更多信息,请参阅&。
其他有用的方法灵活地滚动&scrollToElementWithName&和&scrollToElementWithValueForKey&。 看到&获得更多信息。
添加时间的灵活性与超时时间
您的脚本可能需要等待一些行动完成。 配方的应用,例如,用户水龙头的食谱标签返回单位转换屏幕到屏幕的食谱。 然而,UI自动化可能检测Add按钮的存在,使测试脚本试图利用之前按钮实际上是吸引和挖掘的应用实际上是准备接受。 准确的测试必须确保食谱屏幕完全吸引,这个应用程序是准备接受用户交互与控件在屏幕之前。
提供一些灵活性,在这种情况下,给你更好的控制时间,UI自动化提供了超时时间,在这段期间里它会反复尝试失败之前执行指定的操作。 如果在超时期间操作完成,这行代码的回报,和脚本可以继续。 如果操作不完整的超时期间,就会抛出一个异常。 默认超时时间是5秒,但你的脚本可以在任何时候改变。
使这个功能尽可能容易使用,UI自动化使用堆栈模型。 你推一个定制的超时周期堆栈的顶部,与下面的代码,缩短两秒的超时时间。
UIATarget.localTarget().pushTimeout(2);
然后运行代码执行的操作和流行的超时值堆栈。
UIATarget.localTarget().popTimeout();
使用这种方法你最终得到一个健壮的脚本,一个合理的时间内等待事情发生。
注意:&尽管使用显式的延迟通常不鼓励,有时它可能是必要的。 下面的代码显示了如何指定一个延迟2秒:
UIATarget.localTarget().delay(2);
记录测试结果和数据
脚本报告日志信息自动化仪表,它收集和报告分析。
在编写测试时,您应该记录尽可能多的信息,如果只是为了帮助您诊断出现的任何故障。 在最低限度,您应该记录每个测试开始和结束的时候,确定测试执行和记录通过/失败状态。 这种最小日志几乎是自动在UI自动化。 你只是叫&logStart&您的测试的名称,运行您的测试,然后调用&logPass&或&logFail&作为适当,如以下示例所示:
var testName = "Module 001 Test";
UIALogger.logStart(testName);
//some test code
UIALogger.logPass(testName);
但它是一个很好的实践日志的情况当脚本与控制。 无论你是确认的部分应用程序执行正确或你还追踪bug,很难想象太多日志信息分析。 为此,您可以登录任何出现使用&logMessage&,你甚至可以补充的文本数据截图。
以下代码示例扩展日志的前面的示例包括一个自由格式的日志消息和截图:
var testName = "Module 001 Test";
UIALogger.logStart(testName);
//some test code
UIALogger.logMessage("Starting Module 001 branch 2, validating input.");
//capture a screenshot with a specified name
UIATarget.localTarget().captureScreenWithName("SS001-2_AddedIngredient");
//more test code
UIALogger.logPass(testName);
屏幕截图示例请求将被保存在仪器与指定的文件名(&SS001-2_AddedIngredient&在这种情况下)。
注意:&目前不支持屏幕截图时针对iOS模拟器。 捕获屏幕快照的尝试,然而,表明一个日志消息指示一个失败的尝试。
验证试验结果
测试的关键是能够确认每个测试已经完成,并通过或失败。 这段代码示例运行测试&testName&确定一个有效的元素配方的名字从&称号&存在于配方表视图。 首先,一个局部变量用于指定细胞标准:
var cell = UIATarget.localTarget().frontMostApp().mainWindow().tableViews()[0].cells()
.firstWithPredicate(&name beginswith &Tarte&&);
接下来,脚本使用&isValid&匹配这些标准的方法来测试是否有效元素存在于配方表视图。
if (cell.isValid()) {
UIALogger.logPass(testName);
UIALogger.logFail(testName);
如果找到一个有效的细胞,日志的传递消息的代码&testName&测试;如果不是,这日志失败消息。
请注意,这个测试指定&firstWithPredicate&和&&名字beginsWith称号&&。 这些标准产量的引用单元的称号aux障碍物,这是默认的数据已经在食谱示例应用程序。如果,然而,用户添加一个秘方挞aux复盆子,这个例子可能会或可能不会给期望的结果。
除了验证应用程序的提示正确执行,您的测试应该容纳警报出现出乎意料地从外部应用程序。例如,它是不寻常的一条短信,检查天气或者玩游戏。 更糟糕的是,一个电话销售自动拨号可以接你的电话的电话号码就像你启动脚本。
处理外部生成的警报
尽管它可能看起来有点矛盾,你的应用程序和测试应该料到会发生意想不到的警报当应用程序正在运行。 幸运的是,UI自动化包括违约警报处理程序,使外部警报脚本很容易应付。 您的脚本调用处理程序函数提供了一个警告&onAlert&,这叫做警报发生时,在这段时间里,它可以采取适当的行动,然后然后简单地返回解雇的默认处理程序。
下面的代码示例说明了一个非常简单的警报的例子:
UIATarget.onAlert = function onAlert(alert) {
var title = alert.name();
UIALogger.logWarning("Alert with title '" + title + "' encountered.");
// return false to use the default handler
所有这些处理程序是日志消息,这种类型的警报发生然后返回&假&。 返回&假&指导UI自动化违约警报处理程序把警报。 在警报的情况下收到短信,例如,UI自动化点击关闭按钮。
注意:&默认处理程序停止解雇通知到达上限后顺序的警报。 在可能的情况下,您的测试达到这一限制时,你应该调查可能出现的问题与您的测试环境和程序。
处理内部生成的警报
作为应用程序的一部分,您将警报,需要处理。 在这些情况下,警报处理程序需要执行适当的响应并返回&真正的&默认处理程序,表明警报已经被处理。
以下代码示例小幅扩大基本警报处理程序。 日志记录警报类型后,测试警报是否特定的预期。 如果是这样,它可以继续按钮,这是已知的存在,并返回&真正的&跳过默认解雇行动。
UIATarget.onAlert = function onAlert(alert) {
var title = alert.name();
UIALogger.logWarning("Alert with title '" + title + "' encountered.");
if (title == "The Alert We Expected") {
alert.buttons()["Continue"].tap();
//alert handled, so bypass the default handler
// return false to use the default handler
这个基本警报处理程序可以广义响应任何警报,同时允许脚本继续运行。
检测并指定设备定位
行为端正的iOS应用预计将优雅地处理设备定位的变化,所以你的脚本应该为这种变化预测和测试。
UI自动化提供了&setDeviceOrientation&模拟设备的改变方向。 该方法使用常量中列出&表十一&。
注意:&至于设备定位处理,值得重复的功能是完全模拟软件。 硬件特性,比如原始加速度计数据都不可用于此UI自动化功能,不受其影响的。
表十一&设备定位常量
UIA_DEVICE_ORIENTATION_UNKNOWN
设备的方向不能确定。
UIA_DEVICE_ORIENTATION_PORTRAIT
设备在肖像模式下,设备直立和底部的home键。
UIA_DEVICE_ORIENTATION_PORTRAIT_UPSIDEDOWN
设备是在肖像模式但发生了天翻地覆的变化,与设备直立和顶部的home键。
UIA_DEVICE_ORIENTATION_LANDSCAPELEFT
横向模式的设备,设备直立和按钮在右边。
UIA_DEVICE_ORIENTATION_LANDSCAPERIGHT
横向模式的设备,设备直立和按钮在左边。
UIA_DEVICE_ORIENTATION_FACEUP
设备与屏幕平行于地面面临向上。
UIA_DEVICE_ORIENTATION_FACEDOWN
设备与屏幕平行于地面面临下行。
与设备方向界面取向,代表所需的旋转保持应用程序的面向接口的正确旋转装置。 注意,在横向模式,设备方向和界面方向是相反的,因为旋转设备需要旋转相反的方向的内容。
UI自动化提供了&interfaceOrientation&方法来获取当前界面取向。 该方法使用常量中列出&成分表&。
成分表&面向接口的常量
UIA_INTERFACE_ORIENTATION_PORTRAIT
接口是在肖像模式下,接近底部按钮。
UIA_INTERFACE_ORIENTATION_PORTRAIT_UPSIDEDOWN
接口是在肖像模式但发生了天翻地覆的变化,与接近顶部按钮。
UIA_INTERFACE_ORIENTATION_LANDSCAPELEFT
横向模式的界面,左边靠近主按钮。
UIA_INTERFACE_ORIENTATION_LANDSCAPERIGHT
接口是在景观模式,最靠近右边按钮。
下面的示例更改设备方向(在这种情况下,景观左),然后改变它(肖像):
var target = UIATarget.localTarget();
var app = target.frontMostApp();
//set orientation to landscape left
target.setDeviceOrientation(UIA_DEVICE_ORIENTATION_LANDSCAPELEFT);
UIALogger.logMessage("Current orientation now " + app.interfaceOrientation());
//reset orientation to portrait
target.setDeviceOrientation(UIA_DEVICE_ORIENTATION_PORTRAIT);
UIALogger.logMessage("Current orientation now " + app.interfaceOrientation());
当然,一旦你旋转,需要旋转回来。
当执行一个测试,包括改变设备的方向,这是一个很好的实践设置测试的开始旋转,然后把它回到原来的旋转结束时您的测试。 这种做法可以确保您的脚本总是回到一个已知状态。
您可能已经注意到的取向日志的例子。 这样的日志提供了额外的保证你的测试和testers-don不迷失方向。
当用户退出你的应用程序利用家庭按钮或导致其他一些应用前景,应用程序暂停。 模拟这个发生,UI自动化提供了&deactivateAppForDuration&方法。 你调用这个方法,指定持续时间,以秒为单位,为你的应用程序暂停,如下例所示:
UIATarget.localTarget().deactivateAppForDuration(10);
这一行代码使程序释放了10秒,就好像一个用户退出应用程序并返回10秒后。
阅读(...) 评论()}

我要回帖

更多关于 vbui接口 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信