I have a test for a collection view that works like this:
func testDeleteItem() {
app.collectionViews.staticTexts["Item"].tap()
app.buttons["Delete"].tap()
XCTAssertEqual(app.collectionViews.cells.count, 2)
XCTAssertFalse(app.collectionViews.cells.staticTexts["Item"].exists)
}
After the tap, there is a new screen with the delete button. When the button is tapped, the screen dismisses itself and reloads the collection view. Everything goes as expected in the UI, but I get both asserts failing. In the first count it is still 3 and in the second item it still exists.
I have found the solution, but it's a workaround for wrong API behavior. Collection view is caching cells, that's probably why I have 3 cells, even if I have removed one. Deleted cell is offscreen, so you can test if it is hittable
:
XCTAssertFalse(app.cells.staticTexts["Item"].hittable)
To find a count, I have created extension:
extension XCUIElementQuery {
var countForHittables: UInt {
return UInt(allElementsBoundByIndex.filter { $0.hittable }.count)
}
}
and my test looks like this:
func testDeleteItem() {
app.collectionViews.staticTexts["Item"].tap()
app.buttons["Delete"].tap()
XCTAssertEqual(app.collectionViews.cells.countForHittables, 2)
XCTAssertFalse(app.collectionViews.cells.staticTexts["Item"].hittable)
}
I also came across this issue, but in my case, .cells query wasn't evaluating correctly. Instead of .cells, using
XCUIApplication().collectionViews.element.childrenMatchingType(.Cell).count
worked for me and returned the correct count.
Update:
I also found that scrolling the view so that all the cells are dequeued before getting the count fixed the issue. It seems the accessibility framework does not find the other cells until they have been dequeued (I guess that makes sense).
XCUIApplication().collectionViews.element.swipeUp()
I ran into this question when I was looking for the same answer, but in Objective-C. For those like me, I adapted @Tomasz's method to count Collection View cells in UI tests:
-(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;
}
To call it: [self countForHittables:app.collectionViews.cells.allElementsBoundByIndex];
.
I had the same issue. Even if the collection hasn't been populated because it was waiting for the response of an API, cells.count >= 1 was always true.
What I did, based on Tomasz Bąk's answer I created an extension to wait for the collection to be populated:
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)
}
}
And on the caller site will look:
waitForCollectionToBePopulated(collection, timeout: {timeOut})
来源:https://stackoverflow.com/questions/33679817/wrong-cells-count-for-collection-view-in-ui-tests