iOS UITesting (Objective-C Version) (一)

来源:互联网 发布:淘宝活动促销词 编辑:程序博客网 时间:2024/04/30 10:41

UI Testing

UI Testing是2015年苹果公司新公开的一项自动化测试技术,集成在XCode 7中,不过目前版本的UI Test是一个非常Buggy的测试框架。

        就如同移动端开发倾向于RN化,软件测试现在也倾向于自动化测试。随着项目或者App的功能不断的扩展,功能越来越多,无论是开发新功能、修改旧功能还是维护都可能在意想不到的地方产生Bug,正因如此,QA在每个版本之后仍然要反复的做许许多多的回归测试来保证程序的健壮性。而在每一个开发周期,增加或修改的内容相对于整个程序来说都是相对较小的,这样我们就可以通过维护自动化测试代码,减少回归测试的人力劳动,通过运行自动化测试样例来帮助我们完成。

苹果也是很棒的为我们提供了录制的功能,我们可以通过操作设备,XCode就能为我们生成测试代码(当然,现在这个功能等于没有,自动生成的代码几乎没有用。),我们可以通过录制的方式达到不用写代码也能实现自动化测试,目前来说通过自己编写的测试代码基本能够满足功能测试的需求,至于性能测试、压力测试,目前我了解的程度来看,应该比较难以实现。

UI Test 和 Unit Test

对于iOSer来说,Unit Test已经不再陌生了。UI Test和Unit Test都使用XCTestCase这个类进行编码,但它们之间是不同的,最主要的区别是,Unit Test能够像开发者一样,能够获得所有应用程序内的数据;而UI Test只能像用户一样,对设备进行操作并获取屏幕上所展示的数据。
这里提点别的,因为Unit Test已经诞生好几年了,应用情况比较乐观。GitHub上已经有了不少相应的开源测试框架如Kiwi,Specta(需要混合OCMock进行使用)等,还有2个Swift的开源框架(- -没用过,名字都忘记了),这些框架的可读性非常强,且功能比苹果原声测试框架强。但是这些框架都有一个弊端,在跑Case的时候必须按CMD + U跑尽所有的Case,不能单独跑自己想运行的Case,是一个非常麻烦的事情。所以各有利弊,自行抉择。

两个相关的辅助工具

1. Accessibility 这是苹果官方从iOS 3.0之后为了帮助残疾人所引进的API(详情可见Voice Over),可以通过设置元素的Accessibility,使其可以通过Accessibility进行访问。如果App设置了Accessibility会显著帮助UI Test查询控件的效率,当然实际上大部分的App都没有进行设置,于是我们只能依靠系统设置的Accessibility和Type去查询UI了。

2. Accessibility Inspector,这是Xcode自带的一个插件,可以用来查询控件的Accessibility等信息。具体打开方式XCode -> Open Developer Tool -> Accessibility Inspector就可以打开,使用方法简单就不再赘述,这是UI Test最常用的一个插件,我们可以使用它来查看控件的AccessibilityTitle, AccessibilityValue(尤其的图片和Hybrid页面)等属性,从而帮助编写测试代码。


图1 Accessbility Insepector

从AI中可以轻松地读取控件的各种属性,当然对UITest最常用的属性还是AccessibilityTile、AccessibilityValue和AccessibilityRoleDescription(Type)。

当然这些都对中文支持程度不及英文,很可能查询出奇怪的字符等以及生成的代码的'\u'是'\U'每次都得重新修改录制的代码(目前录制的代码不好用)等对中文不够友好的情况。


运行方法

当运行UITest时,会生成一个新的App(一般叫做XXXUITest,当然你也可以自己命名),这个测试App和被测试的App分别在两个线程运行,简单地说就是两个进程的数据交互和操作同步。测试App会对被测试的App发送和接收信息,在需要进行操作时,会进行进程同步让被测试的App接收事件响应。测试进程能够执行任何你需要他完成的任务,但不能执行任何UI操作(例如初始化一个VC并PUSH等),(具体我也不知道,猜测大概因为只有被测试App的主线程才是UI线程)。


测试机制

宿舍电脑没有PPT- -,改天我再补~还是用图比较好说话。。


工具介绍完了,接下来是一些相关的类:

首先是XCTestCase,这是实际编写测试样例的类,大致结构如下(添加UI Testing Bundle自动生成的代码)。

#import <XCTest/XCTest.h>@interface wise_choiceUITests : XCTestCase@end@implementation wise_choiceUITests- (void)setUp {    [super setUp];        // Put setup code here. This method is called before the invocation of each test method in the class.        // In UI tests it is usually best to stop immediately when a failure occurs.    self.continueAfterFailure = NO;    // UI tests must launch the application that they test. Doing this in setup will make sure it happens for each test method.    [[[XCUIApplication alloc] init] launch];        // In UI tests it’s important to set the initial state - such as interface orientation - required for your tests before they run. The setUp method is a good place to do this.}- (void)tearDown {    // Put teardown code here. This method is called after the invocation of each test method in the class.    [super tearDown];}- (void)testExample {    // Use recording to get started writing UI tests.    // Use XCTAssert and related functions to verify your tests produce the correct results.}@end

其中SetUp方法会在每个测试样例之前会调用一次,一般用于初始化数据、设置环境变量等功能。当然也可以处理App启动时共有的操作,(如点击跳过移动动画等)。

其中有一个属性:continueAfterFailure : BOOL。

/*! * @property continueAfterFailure * The test case behavior after a failure. Defaults to YES. */@property BOOL continueAfterFailure;
默认值为NO,当设置这个值为YES的时候,当测试遇到了错误仍然会继续执行测试,需要根据实际的情况进行设置。不过目前所了解的情况,很难设置为YES,一旦自动化测试代码发生错误,比如点击某个按钮失败,没有进入每个界面,将导致之后所有该见面的操作通通失效。


其次tearDown方法,这个方法会在每一个测试样例运行之后调用(包括测试样例失败),具体的错误信息XCode会提出,并在失败的代码行标红提示,所以不必记录测试代码的错误信息。多用来记录测试日志的搜集、处理以及一些自己需要的操作。


最后testExample方法,该方法是实际测试样例的方法。所有测试样例必须以test为前缀进行命名,当按下->Product->Test或CMD+U运行所有测试样例时,会运行所有的测试样例,顺序是按照testXXX这个方法名的字典序进行运行。当你的XCode出现了Index Error而无法单独运行某个Case的时候,可以将方法名修改为testaXXX就可以使用CMD优先运行这个测试样例。


接下来就是测试相关类,这类类以XCUI为前缀命名,如XCUIApplication、XCUIElement、XCUIDevice、XCUIElementQuery、XCUICoordinate等。

XCUIApplication:

@interface XCUIApplication : XCUIElement/*! * Launches the application. This call is synchronous and when it returns the application is launched * and ready to handle user events. Any failure in the launch sequence is reported as a test failure * and halts the test at this point. If the application is already running, this call will first * terminate the existing instance to ensure clean state of the launched instance. */- (void)launch;/*! * Terminates any running instance of the application. If the application has an existing debug session * via Xcode, the termination is implemented as a halt via that debug connection. Otherwise, a SIGKILL * is sent to the process. */- (void)terminate;/*! * The arguments that will be passed to the application on launch. If not modified, these are the * arguments that Xcode will pass on launch. Those arguments can be changed, added to, or removed. * Unlike NSTask, it is legal to modify these arguments after the application has been launched. These * changes will not affect the current launch session, but will take effect the next time the application * is launched. */@property (nonatomic, copy) NSArray <NSString *> *launchArguments;/*! * The environment that will be passed to the application on launch. If not modified, this is the * environment that Xcode will pass on launch. Those variables can be changed, added to, or removed. * Unlike NSTask, it is legal to modify the environment after the application has been launched. These * changes will not affect the current launch session, but will take effect the next time the application * is launched. */@property (nonatomic, copy) NSDictionary <NSString *, NSString *> *launchEnvironment;@end

XCUIApplication和整个测试查询的入口,用户可以通过XCUIApplicaiton进行路径查询如App -> Window -> View(XCUIElementTypeOther) -> Button -> ……等进行类似的查询,即可得到UI所有的UI控件,再根据控件提供的相关属性读取信息(如文本(UILabel等)的内容、输入(UITextField等)的内容、Button的选中状态(isSelected)等。由于有了这些信息,我们不仅仅可以读取控件的Frame或ScreenPoint等信息验证程序的UI布局、也可以自定义输入并根据UI显示的输出做黑盒功能测试等。至于其他的,压力测试等、由于两个进程之间同步比较缓慢,操作效率并不是很高,如果想要快速点击按钮等、是否可以通过UI Test实现,我暂时还不了解(你们可以告诉我嘛~)。


XCUIElement < XCUIElementAttributes , XCUIElementTypeQueryProvider>

这三个部分几乎包含了绝大部分的测试代码,XCUIElement提供了一系列与UI交互的API(如单击、双击、滑动等等)、而XCUIElementAttributes提供了访问UI控件部分属性信息的API(如Identifier、frame、Value、Label等)、而XCUIElementTypeQueryProvider提供了一系列的查询SubElment(SubView) (DescendantsMatching NOT ChildrenMatching)的APi,当然这些都是为了编写代码的简便缩写(如app.buttons 和 [app descendantsMatchingType:XCUIElementTypeAny]是等价的)。- -又过12点了~~







睡觉了...空了再补..

0 0
原创粉丝点击