What’s New in Testing

概述

Session-409的主题为[What’s New in Testing],主要包括:

  • Enhancement
    优化了macOS、xcodebuild在UT中的性能
  • New Asynchronous Testing API
    提供新的接口和新的等待方式,让异步测试更加灵活
  • Multiple App Testing
    编写测试代码,实现在多个App间自动跳转、测试
  • Implements For UITesting
    改进UITest,优化element选取的算法
  • New Technologies
    新的Activities、attachments、screenshot技术

demo地址

Enhancement

  1. Xcode8:XCUISiriTest用于便携SiriKit的Unit Test;支持Touchbar的UITest
  2. Xcode9:改良了swift4的接口,基于block的 Teardown API
  3. 改进macOS的菜单栏的UI test
  4. 使用命令行进行测试,直接启动core simulator进行测试,不会再看到在测试过程中启动模拟器了
  5. 持续集成场景下,Xcodebuild支持多个设备平行测试,Xcode server可以取代macOS server,进行持续化集成,App测试
  6. 对于有国际化需求的App,在Xcode9的scheme中可以选择语言和地区。应用场景:写UI Test case生成不同国家对应的截图,用于App Store的图片介绍界面,可以节约大量的时间,否则只能统一是用一种展示方式:


    Xcode scheme中选择语言和地区

New Asynchronous Testing API

新老API比较

早在Xcode6中就已经有了异步测试API,使用上也比较简单,性能方面也算可以,但是有几个缺点:

  • 等待超时会被视为测试失败,在某些情况下我们想对超时的情况做一些特殊的逻辑处理时,老API无法满足这个需求

  • 等待代码中需要持有XCTestExpectation对象,等待的代码往往与测试逻辑的代码混杂在一起,想要把测试代码与支持代码变得困难

[[Downloader new] downloadWithCompletion:^(BOOL success, NSError *err) {
    XCTAssert(success, @"failed");
     [_exception fulfill];
}];
// 隐式等待,内部可能持有了expectation对象
[self waitForExpectationsWithTimeout:10 handler:^(NSError * _Nullable error) {
    NSLog(@"timeout");
}];
  • 需要等到所有处于活跃XCTestExpectation对象全部执行 fulfill后才会返回
  • 老的设计模式不支持嵌套waiting

所以,Apple推出了新的API: XCTWaiter,它将waitingXCTestCaseXCTestExpectation解耦,除此之外:

  • 指明等待的XCTestExpectation对象,
 [XCTWaiter waitForExpectations:@[donwloadException] timeout:0.5 enforceOrder:NO];
  • delegate回调, 返回结果XCTWaiterResult,允许指定顺序
 XCTWaiterResult result = [[XCTWaiter alloc] initWithDelegate:self] waitForExpectations:@[donwloadException] timeout:0.5 enforceOrder:YES];
  • 支持嵌套
    新的异步测试API
- (void)test_asyncDownload_newAPI {

   Downloader *loader = [Downloader new];
 
     // download 时间为1s
     XCTestExpectation *donwloadException = [[XCTestExpectation alloc] initWithDescription:@"download"];
     [loader downloadWithCompletion:^(BOOL success, NSError *err) {
         [donwloadException fulfill];
     }];

     // upload 时间为3s
     XCTestExpectation *uploadException = [[XCTestExpectation alloc] initWithDescription:@"upload"];
     [loader uploadWithCompletion:^(BOOL success, NSError *err) {
         [uploadException fulfill];
     }];
 
     XCTWaiterResult result = [XCTWaiter waitForExpectations:@[donwloadException, uploadException] timeout:4 enforceOrder:NO];
 XCTAssert(result == XCTWaiterResultCompleted, @"failed: %ld", (long)result);
}

Multiple app test

Xcode9允许通过Bundle ID 和 fileURL(macOS)来创建一个XCUIApplication对象,以便于多个App测试。launchactivate可用来将APP从后台拉到前台,区别在于:如果app在运行中,activate不会打断app

'' - (void)testMutipleApp { 
''    XCUIApplication *readApp = [[XCUIApplication alloc] initWithBundleIdentifier:@"com.sohu.TestRead"];
''     // 启动read app
''     [readApp launch];
'' 
''     XCUIApplication *writeApp = [[XCUIApplication alloc] initWithBundleIdentifier:@"com.sohu.TestWrite"];
''     // 激活
''     [writeApp activate];
'' 
''     XCUIElement *writeTextField = writeApp.textFields[@"Input"];
''     [writeTextField tap];
''     [writeTextField typeText:@"Using Testing New API To Do Multiple App UI Test"];
''     [writeApp.buttons[@"return"] tap];
''     [writeApp.buttons[@"Send"] tap];
'' 
''     // back to read
''     [writeApp.alerts[@"success"].buttons[@"OK"] tap];
''     [writeApp.statusBars.buttons[@"Return to TestRead"] tap];
'' 
''     // 等待readApp变成活跃状态
''     NSPredicate *readAppPredicate = [NSPredicate predicateWithFormat:@"state == %d", XCUIApplicationStateRunningForeground];
''     XCTNSPredicateExpectation *expection = [[XCTNSPredicateExpectation alloc] initWithPredicate:readAppPredicate object:readApp];
''     expection.expectationDescription = @"Waiting read app to become active";
''     XCTWaiterResult result = [XCTWaiter waitForExpectations:@[expection] timeout:5];
'' 
''     NSLog(@"wait result:%ld", (long)result);
'' 
''     XCUIElement *contentLabel = readApp.staticTexts[@"Using Testing New API To Do Multiple App UI Test"];
''     XCTAssert(contentLabel.exists);
'' }

Implements For UITesting

UITesting往往通过获取到某个UI控件才能进行相关测试,与voiceover相似,需要根据控件显示的内容、语义来查找,涉及生成快照,快照解包和进程间的通讯等等。Xcode9之前,采用的是快照(snapshots)技术来实现,在使用过程中,当当前屏幕下有大量控件时,例如有上千行的tableviewCell,从内存和耗费的时间两个维度来看,耗费的时间和内存占用有些大,甚至会有超时导致测试失败、内存占用过大导致闪退的情况出现…于是就有了FirstMatch

First Match

First Match:就像字面上的意思一个,只要有一个匹配到了就会马上return。
这样的话,在写查询代码的时候需要多考虑考虑怎么发挥FirstMatch的功能。
假设现在要查找navigationBar上的返回按钮:
app.buttons.firstMatch显然不是一个好的写法,这样得到的element可能不是你想要查询的;
app.buttons[@"Done"].firstMatch这样写好多了,缩小了范围,
而最好的写法则是app.navigationBars.buttons[@"Done"].firstMatch

New Technologies

Activities

用于将散落的Testing语句整理在一个Group中

attachments

测试报告中可以包含更多的信息,如:截屏

screenshots

新增XCUIScreenshotProviding,遵循了这个协议的,即可调用screenshot方法获取屏幕截图

'' - (void)testNewTechnoligies {
'' 
''     // 创建Launch Activity
''     [XCTContext runActivityNamed:@"Launch" block:^(id<XCTActivity>  _Nonnull activity) {
''         XCUIApplication *app = [[XCUIApplication alloc] init];
''         app.launchArguments = @[@"-StartFromSlate", @"YES"];
''         [app launch];
''     }];
'' 
''     // 创建ScreenShots Activity
''     [XCTContext runActivityNamed:@"ScreenShots" block:^(id<XCTActivity>  _Nonnull activity) {
''         // 生成主屏幕截图
''         XCUIScreenshot *screenShot = [[XCUIScreen mainScreen] screenshot];
''         // 将截屏添加到附件中
''         XCTAttachment *attachment = [XCTAttachment attachmentWithScreenshot:screenShot];
''         // 确保测试成功后attachment不会被自动删除, 这个同样可以在Xcode的中设置
''         attachment.lifetime = XCTAttachmentLifetimeKeepAlways;
''         // attachment添加到activity中
''         [activity addAttachment:attachment];
''     }];
'' }

测试报告中,生成了两个activity,screenshots activity还包含一张屏幕截图:

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

推荐阅读更多精彩内容