UI 测试中集合视图的错误单元格计数

Posted

技术标签:

【中文标题】UI 测试中集合视图的错误单元格计数【英文标题】:Wrong cells count for collection view in UI Tests 【发布时间】:2015-11-12 19:36:03 【问题描述】:

我有一个像这样工作的集合视图的测试:

func testDeleteItem() 
    app.collectionViews.staticTexts["Item"].tap()
    app.buttons["Delete"].tap()

    XCTAssertEqual(app.collectionViews.cells.count, 2)
    XCTAssertFalse(app.collectionViews.cells.staticTexts["Item"].exists)

点击后,会出现一个带有删除按钮的新屏幕。点击按钮时,屏幕会自行关闭并重新加载集合视图。 UI 中的一切都按预期进行,但我的两个断言都失败了。在第一个计数中它仍然是 3,在第二个项目中它仍然存在。

【问题讨论】:

我在模拟器中看到了测试,它应该没问题。屏幕截图还显示还剩下 2 个项目。我认为它可能会失败,因为它不会等待完成屏幕关闭,但 expectationForPredicatewaitForExpectationsWithTimeout 也会失败。 日志没有显示任何乱序。 这个测试也失败了,当直接在collectionView:didSelectCell: 上删除单元格时,将断言放入旧好的dispatch_async 使测试通过。它似乎不是一个合适的解决方案,但也指出了线程。有趣 我无法通过dispatch_async,您是如何做到的? 我用dispatch_async(dispatch_get_main_queue())包装了断言,无论如何dispatch_async是不行的,它只会导致断言不被考虑XCTAssertFalse(true)也通过了;)你试过了吗?相同的场景,但使用 tableView?如果这可行,则可能表明确实存在一些错误 【参考方案1】:

我找到了解决方案,但它是错误 API 行为的解决方法。集合视图正在缓存单元格,这可能就是我有 3 个单元格的原因,即使我已经删除了一个。删除的单元格不在屏幕上,所以你可以测试它是否是hittable

XCTAssertFalse(app.cells.staticTexts["Item"].hittable)

为了找到一个计数,我创建了扩展:

extension XCUIElementQuery 
    var countForHittables: UInt 
        return UInt(allElementsBoundByIndex.filter  $0.hittable .count)
    

我的测试看起来像这样:

func testDeleteItem() 
    app.collectionViews.staticTexts["Item"].tap()
    app.buttons["Delete"].tap()

    XCTAssertEqual(app.collectionViews.cells.countForHittables, 2)
    XCTAssertFalse(app.collectionViews.cells.staticTexts["Item"].hittable)

【讨论】:

刚刚也遇到了这个问题。不幸的是,需要解决方法,但解决方法有效,这很棒。谢谢!【参考方案2】:

我也遇到了这个问题,但就我而言,.cells 查询没有正确评估。而不是 .cells,使用

XCUIApplication().collectionViews.element.childrenMatchingType(.Cell).count

为我工作并返回正确的计数。


更新

我还发现滚动视图以使所有单元格在获得计数之前出列,从而解决了问题。似乎可访问性框架在它们被出列之前不会找到其他单元格(我想这是有道理的)。

XCUIApplication().collectionViews.element.swipeUp()

【讨论】:

【参考方案3】:

我认为单元格查询返回当前视图层次结构中所有表中的所有单元格。尝试这样做app.tables.firstMatch.cells.count,它对我有用。

【讨论】:

【参考方案4】:

我在寻找相同答案时遇到了这个问题,但在 Objective-C 中。对于像我这样的人,我采用了@Tomasz 的方法来计算 UI 测试中的 Collection View 单元格:

-(NSInteger)countForHittables:(NSArray<XCUIElement*>*)collectionView
    __block int hittables = 0;
    [collectionView enumerateObjectsUsingBlock:^(XCUIElement * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) 
        if (obj.hittable)
            hittables++;
        
    ];
    return hittables;

调用它:[self countForHittables:app.collectionViews.cells.allElementsBoundByIndex];

【讨论】:

【参考方案5】:

我遇到了同样的问题。即使由于等待 API 响应而没有填充集合,cells.count >= 1 也始终为真。

我做了什么,基于Tomasz Bąk's answer 我创建了一个扩展来等待集合被填充:

extension XCTestCase 
    func waitForCollectionToBePopulated(_ element: XCUIElement, timeout: TimeInterval) 
        let query = element.cells
        let p = NSPredicate(format: "countForHittables >= 1")
        let e = expectation(for: p, evaluatedWith: query, handler: nil)
        wait(for: [e], timeout: timeout)
    

并且在调用者网站上会看到:

waitForCollectionToBePopulated(collection, timeout: timeOut)

【讨论】:

以上是关于UI 测试中集合视图的错误单元格计数的主要内容,如果未能解决你的问题,请参考以下文章

Xcode中集合视图的单元格未出现

swift中集合视图单元格内的按钮操作

如何使用 Swift 在 XCode UI 自动化中选择随机表格视图单元格

UI测试滑动删除表格视图单元格

swift - 快速按下集合视图单元格时如何修复自定义视图中的约束

Swift UI 测试,如何检查单元格是不是有图像视图