如何使用UIAutomation进行iOS自动化测试

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何使用UIAutomation进行iOS自动化测试相关的知识,希望对你有一定的参考价值。

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();
参考技术A 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. 在脚本编辑器里,输入下面的代码
  var target = UIATarget.localTarget();
  var app = target.frontMostApp();
  var window = app.mainWindow();
  target.logElementTree();
  clip_image007[4]

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

  clip_image009[4]

  赞一个!我们就这样完成了我们的第一个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. 启动测试
  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

  clip_image001[6]

  你可以通过下面的代码来访问文本框:
  var textField =
  UIATarget.localTarget().frontMostApp().mainWindow().textFields()[0];
  你可以选择通过从0开始的索引或者这个元素的名称来访问这个元素,例如:你也可以通过下面的代码来访问文本控件。
  var textField =
  UIATarget.localTarget().frontMostApp().mainWindow().textFields()["User Text"];
  后一种方式更加清晰明了,应该多使用。你可以通过Interface Builder设置UIAElement的name属性,

  clip_image002[6]
参考技术B 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. 在脚本编辑器里,输入下面的代码
  var target = UIATarget.localTarget();
  var app = target.frontMostApp();
  var window = app.mainWindow();
  target.logElementTree();
  clip_image007[4]

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

  clip_image009[4]

  赞一个!我们就这样完成了我们的第一个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. 启动测试
  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

  clip_image001[6]

  你可以通过下面的代码来访问文本框:
  var textField =
  UIATarget.localTarget().frontMostApp().mainWindow().textFields()[0];
  你可以选择通过从0开始的索引或者这个元素的名称来访问这个元素,例如:你也可以通过下面的代码来访问文本控件。
  var textField =
  UIATarget.localTarget().frontMostApp().mainWindow().textFields()["User Text"];
  后一种方式更加清晰明了,应该多使用。你可以通过Interface Builder设置UIAElement的name属性,

  clip_image002[6]

  或者通过编写代码的方式:
  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:
  var tabBar = UIATarget.localTarget().frontMostApp().tabBar();
  var tabButton = tabBar.buttons()["First"];
  UIAElement结构层次非常的重要,你以后会常常用到它。而且你还要记住,你可以在随时通过调用UIAAplication的logElementTree来获得它的结构。

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

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

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

  模拟用户操作

  让我们更进一步,模拟一些用户的交互操作。你可以简单地调用按钮的tap()来作一个点击操作:
  var tabBar = UIATarget.localTarget().frontMostApp().tabBar();
  var tabButton = tabBar.buttons()["First"];
  
  // Tap the tab bar !
  tabButton.tap();
  你还可以调用UIAButtons的doubleTap(), twoFingerTap()。如果你不想操作具体的某个元素,你也可以直接根据屏幕上指定的坐标点进行操作,你可以这么用:

  UIATarget.localTarget().tap(x:100, y:200);
  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);
  拖拽与划动:
  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代码:

  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)方法指明你的测试脚本已经成功的完成测试了。

  你还知道了如何访问键盘上的按钮,然后作点击操作:
  
  app.keyboard().buttons()["return"].tap();本回答被提问者采纳
参考技术C 你好那时你就会发现爱的价值所在了。爱一个人并不难,就怕你不是真

iOS 的 Javascript UIAutomation 如何用于导航原生应用的 oAuth 流程?

【中文标题】iOS 的 Javascript UIAutomation 如何用于导航原生应用的 oAuth 流程?【英文标题】:How can iOS's Javascript UIAutomation be used to navigate a native app's oAuth process? 【发布时间】:2012-11-11 06:15:32 【问题描述】:

上下文

许多原生应用程序让用户使用 Facebook 进行身份验证,而不是使用自己的身份验证系统。这对我使用 Javascript 绑定编写 iOS UIAutomation 测试用例来说是个问题。从用户的角度来看,我们的场景通常如下所示。

场景

    用户点击“连接到 Facebook”。 (目标)应用程序移至后台,Safari 浏览器移至前台,因此用户可以使用 oAuth 进行身份验证。 用户输入他们的身份验证数据并提交。 Safari 浏览器窗口移至后台,目标应用程序移回前台。

问题

在运行测试之前,Instruments 让用户在顶部菜单栏中设置“目标应用”。 当目标应用程序移入后台而 Safari 应用程序移入前台(步骤 #2)时,在 Instruments 中使用 Automation 会出现问题。此时,仪器报告

目标应用程序似乎已经死了

我认为这就像轮询/测试UIATarget.localTarget().frontMostApp()(或类似的东西)中的更改一样简单,但似乎并非如此——测试运行停止执行。

如何使用 Instruments 成功测试此场景? 这是一个使用 UIAutomation 的 Javascript 绑定的可测试场景吗?

【问题讨论】:

【参考方案1】:

唉,这是不可能的。 Instruments 失去了与应用程序的连接,因为应用程序在后台冻结并且无法继续。此外,无法将触摸事件发送到 Safari,因为 UI 自动化不适用于您自己构建的应用程序。

如果您使用的是预构建的 SDK,那么您就很不走运了。但是,如果您将自己的 Oauth 连接滚动到它们,您可以呈现一个带有 Web 视图的模态视图控制器,该控制器将转到 Facebook 的 Oauth 身份验证页面,而不是将用户一直踢到移动 Safari。

这样,应用程序永远不会退出。然后,您可以找出要发送到 web 视图的事件并尝试从那里进行测试。

【讨论】:

有趣,感谢您的完整回答。我正在使用Facebook iOS SDK,它提供了两种选择,让用户使用 Safari 或 Facebook iOS 应用程序进行 oAuth。这意味着无法进行涉及 Facebook iOS SDK 的 UIAutomation 测试。

以上是关于如何使用UIAutomation进行iOS自动化测试的主要内容,如果未能解决你的问题,请参考以下文章

如何使用UIAutomation进行iOS 自动化测试

如何在 iPhone 模拟器中工作的 UIAutomation 中获取 captureScreenWithName?

iOS 的 Javascript UIAutomation 如何用于导航原生应用的 oAuth 流程?

IOS中的UIAutomation错误

即使在应用退出后,如何使用 UIAutomation 工具继续测试 iOS 应用?

使用 UIAutomation javascript 进行地图视图测试