IOS UI自动化测试初探

前言


最近我们的项目赶在圣诞前上线,测试这关一直过不去。我们的项目是一个类似电商项目,因此支付这块一直都是重中之重。由于产品经理脑洞大开,支付方式多种多样,钱包金额、优惠券、支付宝、银联支付、多次支付等等,排列组合一下竟然有80多种,再加上退款流程,维护起来简直就是灾难。于是就出现了这么奇葩的一幕:测试团队加技术团队加运营排排坐周末加班加点,人手一张A4样例纸测支付。更可怕的是,如果发现一个金额问题,后台一改代码,还得回归测试!!!!

宝宝好怕怕

折磨了整整2周之后,我们老大痛定思痛,给每人下达了一个任务,去寻找UI自动化测试的方法,于是就有了这篇文章。

UI Tests


IOS的UI自动化测试由于系统封闭的原因,一直不太成熟。UI Tests是Xcode7推出的一项UI自动化测试功能,毕竟是apple官方推出,相对来说比较稳定,它可以通过编写代码、或者是记录开发者的操作过程并代码化,来实现自动点击某个按钮、视图,或者自动输入文字等功能。

使用方法


  • 添加UI Tests
    如果是新项目,在创建项目的时候只要把Include UI Tests勾上就行。
勾选上UI Tests

不过大部分项目都是老项目,那么就要通过添加target的方式添加UI Tests。

添加target
添加target

之后在你的项目中就会出现xxxxUITests.m文件,那么UI Tests就添加完毕了。

完成
  • 测试用例
    如果有过单元测试经验的同学应该很熟悉这个文件,UI Test测试其实就详单与单元测试,一上来。这个文件就会生成2个函数:- (void)setUp- (void)tearDown ,分别会在测试开始和测试完成的时候调用。下面就是一些测试用例,可以自己写方法生成。如图:
测试用例
测试用例

这里值得一提的是,UI测试中也可以下断点,这极大帮助开发者分析用例不通过的原因。

  • 断言

既然是单元测试,判断测试通过不通过当然需要断言。这里列举一些常用的断言:

XCTFail(format…) 生成一个失败的测试;

XCTAssertNil(a1, format...)为空判断,a1为空时通过,反之不通过;

XCTAssertNotNil(a1, format…)不为空判断,a1不为空时通过,反之不通过;

XCTAssert(expression, format...)当expression求值为TRUE时通过;

XCTAssertTrue(expression, format...)当expression求值为TRUE时通过;

XCTAssertFalse(expression, format...)当expression求值为False时通过;

XCTAssertEqualObjects(a1, a2, format...)判断相等,[a1 isEqual:a2]值为TRUE时通过,其中一个不为空时,不通过;

XCTAssertNotEqualObjects(a1, a2, format...)判断不等,[a1 isEqual:a2]值为False时通过,

XCTAssertEqual(a1, a2, format...)判断相等(当a1和a2是 C语言标量、结构体或联合体时使用,实际测试发现NSString也可以);

XCTAssertNotEqual(a1, a2, format...)判断不等(当a1和a2是 C语言标量、结构体或联合体时使用);

XCTAssertEqualWithAccuracy(a1, a2, accuracy, format...)判断相等,(double或float类型)提供一个误差范围,当在误差范围(+/-accuracy)以内相等时通过测试;

XCTAssertNotEqualWithAccuracy(a1, a2, accuracy, format...) 判断不等,(double或float类型)提供一个误差范围,当在误差范围以内不等时通过测试;

XCTAssertThrows(expression, format...)异常测试,当expression发生异常时通过;反之不通过;(很变态)

XCTAssertThrowsSpecific(expression, specificException, format...) 异常测试,当expression发生specificException异常时通过;反之发生其他异常或不发生异常均不通过;

XCTAssertThrowsSpecificNamed(expression, specificException, exception_name, format...)异常测试,当expression发生具体异常、具体异常名称的异常时通过测试,反之不通过;

XCTAssertNoThrow(expression, format…)异常测试,当expression没有发生异常时通过测试;

XCTAssertNoThrowSpecific(expression, specificException, format...)异常测试,当expression没有发生具体异常、具体异常名称的异常时通过测试,反之不通过;

XCTAssertNoThrowSpecificNamed(expression, specificException, exception_name, format...)异常测试,当expression没有发生具体异常、具体异常名称的异常时通过测试,反之不通过
  • XCTest UI Testing API

要想写好测试用例代码,当然得知道UI Test的API。主要分为XCUIApplicationXCUIElementXCUIElementQuery

XCUIApplication

这是你正在测试的应用的代理。它能让你启动应用,这样你就能执行测试了。它每次都会新起一个进程,这会多花一些时间,但是能保证测试应用时的状态是干净的,这样你需要处理的变量就少了些。这里面主要有2个方法:

- (void)launch;//启动程序
- (void)terminate;//终止程序
XCUIElement

继承NSObject,实现协议XCUIElementAttributes, XCUIElementTypeQueryProvider

可以表示系统的各种UI元素,比如UIView、UIButton、UITestField等。
主要方法:

- (BOOL)exists;//判断该元素是否存在
- (XCUIElementQuery *)descendantsMatchingType:(XCUIElementType)type;//取某种类型的元素以及它的子类集合
- (XCUIElementQuery *)childrenMatchingType:(XCUIElementType)type;//取某种类型的元素集合,不包含它的子类

//交互类方法
- (void)tap;//单击,还能使testField获得焦点
- (void)doubleTap;//双击
- (void)swipeUp;//pan手势
- (void)typeText:(NSString *)text;//输入文字
- (void)pressForDuration:(NSTimeInterval)duration;//长按
  • 自动录制代码
    Xcode很贴心的给开发者一个偷懒的机会,可以录制,并自动生成代码,开发者只要在界面上点点点就能生成对应代码。
录制代码

但是这个功能很鸡肋,因为生成代码大概像这样:

  XCUIApplication *app = [[XCUIApplication alloc] init];
    XCUIElement *element = [[[[app childrenMatchingType:XCUIElementTypeWindow] elementBoundByIndex:0] childrenMatchingType:XCUIElementTypeOther].element childrenMatchingType:XCUIElementTypeOther].element;
    [element tap];

简单的点击就生成了一大堆代码,而且如果界面一变,代码就不可用了。。。不过如果一时不知道怎么敲的话,可以拿来参考下,然后修改成自己的代码。

  • demo
    这里主要测试一个登陆功能是否正常作为例子,界面很简单,先看一下演示过程。
流程1
流程2
流程3

测试样例代码

- (void)testExample {

    XCUIApplication *app = [[XCUIApplication alloc] init];
    [app.buttons[@"点击"] tap];

   XCUIElement * textFiled = [app.textFields elementMatchingType:XCUIElementTypeTextField identifier:@"test"];
    [textFiled tap];
    [textFiled typeText:@"user"];

    XCUIElement * textFiled2 = [app.textFields elementMatchingType:XCUIElementTypeTextField identifier:@"hello"];
    if ([textFiled2 exists]){
        [textFiled2 tap];
        [textFiled2 typeText:@"123456"];
    }  
     [app.buttons[@"点击"] tap];    
}

从上面代码不难看出,我们主要的任务就是找到某一个元素(UIButton或者UITextFiled),然后执行单击、长按、输入等操作。这里可以简单得通过app.buttons[@"点击"]获得界面上一个title为点击的按钮,或者通过elementMatchingType:identifier:来获取。经过我尝试,这个identifier的设置位置如下图

identifier

也就是说Accessibility中设置的内容都能在XCUIElement拿来利用和定位。比方设置了Accessibility中的label,就可以写一个函数遍历获取这个元素。

- (XCUIElement *)getElemWithLabel:(NSString *)str type:(XCUIElementType)type{
    XCUIApplication *app = [[XCUIApplication alloc] init];
   XCUIElementQuery * list = [app descendantsMatchingType:type];
    for (int i = 0 ; i < list.count ; i++) {
        XCUIElement * tmpElem =[list elementBoundByIndex:i];
        if ([tmpElem.label isEqualToString:str]) {
            return tmpElem;
        }
    }
    return  nil;
}

ps:我发现elementMatchingType:identifier:中identifier如果是纯英文能拿到,但是英文加数字组合就拿不到了。。不知道算不算bug。

总结


UI Tests虽然能完成UI自动化测试,但是还仅仅是单元测试的层面,想要做到系统测试还远远不够。用来测试能不能登录可以,但是要想解决上面的支付问题还有明显的不足,比如截图,日志等(也许可以,没有深究)。

UI Tests还是在一定程度上增加了开发人员的工作,而且对开发人员有一定的技术要求。至于值不值在生产环境中使用,只能因人而异了。

我是翻滚的牛宝宝,欢迎大家评论交流~

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 218,451评论 6 506
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,172评论 3 394
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,782评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,709评论 1 294
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,733评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,578评论 1 305
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,320评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,241评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,686评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,878评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,992评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,715评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,336评论 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,912评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,040评论 1 270
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,173评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,947评论 2 355

推荐阅读更多精彩内容