iOS UI测试中元素lastSnapshot的子属性总是为空,为啥?

Posted

技术标签:

【中文标题】iOS UI测试中元素lastSnapshot的子属性总是为空,为啥?【英文标题】:Property of children from lastSnapshot of an element in iOS UI Testing is always being empty, why?iOS UI测试中元素lastSnapshot的子属性总是为空,为什么? 【发布时间】:2017-10-09 09:48:41 【问题描述】:

我正在研究来自 facebook 的 UI 测试框架 WebDriverAgent。它非常棒而且很有帮助。几乎囊括了ios UI测试的所有知识。

XCTest 有许多非公开的类和属性。例如,XCUIElement 有一个名为 lastSnapshot 的属性,lastSnapshot 也有很多有用的属性,如 labelidentifierframeparent 儿童pathDescription等。问题来了:

children 属性用于从某个元素中获取所有子元素,就像视图中的子视图一样。但是当我试图从元素的 lastSnapshot 中获取 children 的值时,它总是为空的。虽然我可以正确地获取标签、标识符、父级等其他属性的值。这确实困扰了我好几天。这是示例代码:

- (void)testExample 
    XCUIApplication *app = [[XCUIApplication alloc] init];
    XCUIElement *windowElement = [app.windows elementBoundByIndex:2];
    XCUIElement *statusBarElement = [windowElement.query elementBoundByIndex:0];
    XCUIElement *otherElement = [statusBarElement.query elementBoundByIndex:1];
    XCUIElement *timeElement = [otherElement.query elementBoundByIndex:2];

    [timeElement query];
    [timeElement resolve];
    NSLog(@"lastSnapshot = %@", timeElement.lastSnapshot);
    NSLog(@"children = %@", timeElement.lastSnapshot.children);

【问题讨论】:

在学习WebDriverAgent之前,我使用了XCUIElement的一个类来递归元素树: 【参考方案1】:

在学习WebDriverAgent之前,我使用了XCUIElement的一个类来递归元素树:

- (XCUIElementNode *)recursiveUIElementsWithLevel:(NSInteger)elementLevel 
    XCUIElementNode *node = [XCUIElementNode new];
    node.elementLevel = elementLevel;
    node.elementValue = self;
    NSArray *arrayNotIncludeSelf = [self recursiveUIElementsNotIncludeSelfWithLevel:elementLevel];
    node.subNodes = [NSMutableArray arrayWithArray:arrayNotIncludeSelf];

    return node;


- (NSArray *)recursiveUIElementsNotIncludeSelfWithLevel:(NSInteger)elementLevel 
    NSMutableArray *elementArray = [NSMutableArray new];

    XCUIElementQuery *childrenQuery = [self childrenMatchingType:XCUIElementTypeAny];

    for (NSUInteger elementIndex = 0; elementIndex < childrenQuery.count; elementIndex ++) 
        XCUIElement *element = [childrenQuery elementBoundByIndex:elementIndex];
        XCUIElementNode *subNode = [XCUIElementNode new];
        subNode.elementLevel = elementLevel + 1;
        subNode.elementValue = element;
        subNode.subNodes = [NSMutableArray arrayWithArray:[element recursiveUIElementsNotIncludeSelfWithLevel:subNode.elementLevel]];
        [elementArray addObject:subNode];
    

    return [NSArray arrayWithArray:elementArray];

这种方式确实行得通,但是递归遍历体验需要很多时间,不能接受。

【讨论】:

如果你升级到 Xcode 9 和 iOS 11 模拟器,查询时间已经优化,所以快照和重复遍历不再那么慢了。 我升级到Xcode 9和iOS 11模拟器后再次尝试,通过childrenMatchingType类遍历子元素仍然很慢:

以上是关于iOS UI测试中元素lastSnapshot的子属性总是为空,为啥?的主要内容,如果未能解决你的问题,请参考以下文章

iOS Webview UI 测试

是否可以在其他 UI 元素后面显示 Popover?

自定义 UIView 的子视图未出现在 UI 测试中

在 Swift 3 UI 测试中访问自定义视图组件中的元素

Unity中的UI

如何使用 XCTest UI 测试区分 iOS 13 中的标题和静态文本