iOS 中使用 KIF 测试 UI

1862 查看

用户期待从iOS应用获得一个高水平的体验,因而需要你来设计,开发和测试你的应用来满足这一不断上升的期望. 想想只是为了这一刻: 你会投进入多少时间进行原始人工的用户界面测试?你知道这活儿怎么干…从Xcode启动你的应用,并不断的用手指点击同一些按钮来确保你的设计中没有让应 用退步的体验. 当然,还有其它一些你更愿意做的事情?

取而代之,考虑考虑Xcode 5中增强的UI测试吧,还有 OS X Server中支持的持续集成 这篇文章展示了苹果公司为开发者贡献的最好的工具. 你也许会说,那很棒,而你如何让那些简单的用户动作测试变得自动化呢,就像确保一个在合适区域的双击或触摸后会进入正确的视图?即使是测试脚本和机器人也不会有能在屏幕上滑动的电容式触摸手指…或者…它们会有么?

在这篇教程中,你将会学习到所有有关 KIF 的东西(“保持功能 Keep it Functional”), 它是一个开源的用户界面测试框架. 使用 KIF, 并利用 iOS中的辅助功能 API, 你将能够编写模拟用户输入,诸如点击,触摸和文本输入,这样的测试. 这些给予你的应用自动化的,真实的用户界面操作, 并比帮助放松你的心情,因而你就可以只去关注自己的杀手级应用了 – 不用在UI测试上耗费你生涯的一半时间.

让我们来开始测试工作吧!

入门

示例是一个叫做茄薯Solanum(一个马铃薯品种的名字)的的计时器应用,它基于Pomodoro 时间盒子方法. 这是是它的运作方式: 按照设定好的分钟数你工作的一段时间,休息一下,然后重复工作和休息. 进过这样若干个循环之后, 你就会休息一段更长的时间. 这个应用只是一个能够持续跟踪时间区段的简单计时器. 轻松的使用了这款应用之后,就能使得你的开发工作变得更加高效!

220140318104938

从 这里 下载并解压缩入门项目.注意 KIF 是一个分开独立的项目, 而它的角色是为茄薯应用构建一个用于测试目标的库. 你需要双击 solanum.xcworkspace 来在Xcode中打开项目,而不是 solanum.xcodeproj. 在项目导航视窗中找到这两个项目,应该如下面图示中这样.

320140318104958

将应用的目标设置到solanum,并选择3.5或者4英寸的iPhone模拟器目标.不要使用64位构建,因为在写这篇教程的时候,KIF貌似还不能完全兼容.构建并运行这个应用.各处都瞧一瞧,然后切换到设置Settings面板.

420140318105011

应用有一个能够加速时间的调试模式,因此你可以设置一个20分钟的计时器,而它将会在测试中用10秒钟走过这段时间. 这只是为了帮助你测试应用.你应该不会想花20分钟等着看它运行吧!

开启调试模式来加速计时器.接下来点击Clear History按钮,然后在确认弹出视图上点击Clear.这几步确保了你是在一个干净,对测试有的环境中开始测试作业.返回到Xcode并把应用停下来.

测试前操作

在项目浏览器中,展开solanum项目. 右击UI测试文件夹并点击New File…来加入你的新测试用例.

520140318105026

选择 iOS\Cocoa Touch\Objective-C class 并点击 Next. 将类命名为 UITests 并使其成为 KIFTestCase 的子类.

620140318105049

点击Next 并确保文件已经被添加到 UI Tests 目标中, 而不是 solanum 目标. 最后,点击接下来屏幕上的 Create 以保存文件.

KIFTestCase是SenTestCase的一个子类. 那意味着你拥有了大部分的标准 OCUnit 测试方法和机制可以使用, 考虑到你已经很熟悉的 单元测试.

打开UITests.m 并在@implementation 一行添加如下的方法:

beforeAll 是一个实际上只是在所有测试运行之前被调用一次的特殊方法. 你可以为你这里运行的测试设置任何实体变量和初始化条件.

tester 对象是指定的KIFUITestActor 类的一个缩略名称. 这个类包含了可以模拟用户动作的方法,包括触及还有在视图上滑动.

tapViewWithAccessibilityLabel: 也许是最常被用到的测试动作方法. 正如其名称所揭示的,它使用在给定的可访问标签上模拟在视图上的触击. 在大多数情况下,可访问标签都是匹配诸如按钮这种组件的可视的文本标签. 如果不是这样的,那就会如你在下一节将会看到了,你将需要手动设置访问标签.

一些控件,诸如 UISwitch, 相较而言更加复杂而比仅仅只需要简单的触击更甚的动作. KIF 提供了一个特殊的 setOn:forSwitchWithAccessibilityLabel: 方法来改变一个切换的状态.

总结起来:这个方法对测试动作进行了四步操作:

  • 触击“Settings” 选项卡按钮条.
  • 将 “调试模式Debug Mode” 切换到它的“开启”状态.
  • 触击 “Clear History” 按钮.
  • 在UIAlertView上触击“Clear”按钮.

这几部看起来很眼熟? 应该是熟悉的! 它们就是之前章节中你手动进行的操作!

到 Product\Test 或者在键盘上敲 Command-U 来运行测试. 你会看到应用运行了起来; 而后你会看到 KIF 接手,自动开启调试模式并清除历史记录.

如果你开启了通知,Xcode也将会告知你测试的状态:

720140318105113

有时候测试运行器或者说KIF可能会有一点过分讲究,而拒绝你运行测试, 在此状况下你将只能看到一个空白的模拟器屏幕. 如果发生了这样的事情:

  • 清理一下这样个项目(Product\Clean)
  • 构建并运行
  • 等待应用启动
  • 在Xcode中终止应用的运行

这一过程确保了模拟器正在运行,并且你正在最新的构建上进行操作. 在经过上面的几步之后,试试再一次运行测试. 问题应该没有了.

如果你还是继续遇到这样的麻烦, 再检查下 KIF 故障排除步骤.

现在你已经在 beforeAll 中有了一个测试前置动作, 是时候加入你的第一个测试了!

一个简单的测试:点击周围

该应用程序在这三个选项卡中,每一个均有标准的选项卡控制器层UINavigationController。在接下来的练习中,你将会做个热身,来决定是否:

  • 把面板适当地连接起来
  • 选项卡展示正确的视图

选项栏按钮自动地设置成类似文本标签这样的可访问标签,所以KIF可以通过设置选项栏中的“历史(History)”、“定时器(Timer)”、“设置(Settings)”标签找到历史、计时器和设置。

历史选项卡有一个显示所有定时器执行任务的表视图。从solanum组里打开HistoryViewController.m,在viewDidLoad末尾处添加以下几行:

表视图的可访问标签就设置好了,KIF也因此能够找到它。通常情况下,一个表视图仅在空的情况下才能被访问。如果是表视图的单元格有可能被当做是一个目 标,所以表视图它本身会被藏在可访问的API之下。本来可访问的API在默认情况下假设表视图是不重要的。可能有这样的用例需要根据可访问性,但是如果你 想在KIF中引用表视图就需要使它成为可访问的。setIsAccessibilityElement:要求确保表视图始终是可访问的,而不管其内容。

不同的应用中,如果用户使用了可访问特性(例如:VoiceOver)访问非空的表格视图会使得问题更加复杂化.在你的应用中,你可以把几行代码套 在#ifdef DEBUG 和 #endif 指令之间,以便这几行代码只被编译到你的调试构建中.DEBUG 预处理器宏已经在Xcode项目模板中被提前定义好了.

Timer 选项卡有几个你可以观察观察的控件,而“Task Name”文本域则被便利的放在了视图的顶部. 不同于通过代码来设置标签属性, 可以打开 Main.storyboard 并找到Timer View Controller 视图. 选择task name 选择文本域,再来进行设置.

820140318105131

打开 Utilities  面板,如果它没有显示出来的话 — 并选择Identity Inspector. 提示:它是从左边数第三个图标, 或者使用快捷键‘⌥ ⌘ 3′.

920140318105142

在这个窗口的 Accessibility 一栏的Lable域中输入“Task Name“. 要警惕一点,因为可访问选项对大小写是敏感的. 确保输入如显示的,是大写的 T 和 N!

1020140318105154

Settings 面板已经用Accessibility选项将视图设置好了, 因此你已经万事俱备,可以进入到下一步操作了!

在你的项目中,你将会需要继续在Accessibility选项中进行设置,通过代码方式或者如前面已经在Interface Builder中已经做过的. 为了方便,示例应用余下来的选项已经设置好了.

回到 UITests.m, 看看在 beforeAll之后的这个方法:

测试运行器会在运行时寻找所有以”test“开头的方法, 然后按字母顺序运行它们. 这个方法以名字“test00″ 开头,因此它会在你稍后加入的方法之前运行, 因为它们是以诸如“test10″, “test20″ 这样的名字开头的.

每三个一组的方法会进行类似一些动作: 在一个选项卡按钮条上触击, 并检查期望看到的视图被显示在屏幕上. 10 秒是waitForViewWithAccessibilityLabel:设置的默认时间. 如果在这段指定的时间没有显示预期的东西,测试就告失败.

选择 Product\Test 或者敲击 Command-U键运行这些测试. 你会看到beforeAll 中的步骤会清除掉历史记录, 而后test00TabBarButtons 会接手并按顺序切换到History, Timer 和 Settings 选项卡.

1120140318105212

那么,你怎么意识到测试已经发生了呢? 你只需要编写并运行一个借口测试, 就会看到你的小应用自己在“启动”了!恭喜了! 你正在掌控自动化UI测试的征程上.

用户输入

当然,切换标签是非常好看的,但是是时候去关注更加真实的动作:输入文本,触发模式对话框并选择一个表视图的行。

该测试应用程序有一些内置的可以更改工作时间、休息时间、一组推荐值的重复次数的预设。如果你想看看他们的定义,可以看看在PresetsViewController.m中的presetItems。

选择一个预设,这个自己本身就可以成为一个测试,但是这个动作成为其他测试的一部分会更有效。在这种情况下是值得把它独立开来成为一个辅助方法。

把以下的方法添加到UITests.m的实现模块中去: