XCUITest Multiple matches found error
Asked Answered
D

4

30

I am writing tests for my app and need to find the button "View 2 more offers" there are multiple of these buttons on my page but I would just like to click on one. When I try this, an error comes saying "Multiple matches found" So the question is, what ways can I go around this so my test will search and tap on only one of the buttons called "View 2 more offers".

Here is my current code

let accordianButton = self.app.buttons["View 2 more offers"]
    if accordianButton.exists {
        accordianButton.tap()
    }
    sleep(1)
}
Diandiana answered 12/9, 2016 at 10:49 Comment(3)
This isn't XCTest, it's XCUITest.Canoodle
Can you check the hierarchy and see if multiple elements are present? Also, have you made the UIButton accessible and given it the same accessibility label as that on the UIButtonLabel?Canoodle
@Canoodle , hi thanks for the help, yes multiple elements are present and using the label name causes the same error. Do you know if there is a way so it selects the first button of the element type?Diandiana
J
46

You should use a more elaborated way to query your button, since there is more than one button who's matching it.

    // We fetch all buttons matching "View 2 more offers" (accordianButtonsQuery is a XCUIElementQuery)
    let accordianButtonsQuery = self.app.buttons.matchingIdentifier("View 2 more offers")
    // If there is at least one
    if accordianButtonsQuery.count > 0 {
        // We take the first one and tap it
        let firstButton = accordianButtonsQuery.elementBoundByIndex(0)
        firstButton.tap()
    }

Swift 4:

    let accordianButtonsQuery = self.app.buttons.matching(identifier: "View 2 more offers")
    if accordianButtonsQuery.count > 0 {
        let firstButton = accordianButtonsQuery.element(boundBy: 0)
        firstButton.tap()
    }
Jinx answered 12/9, 2016 at 11:37 Comment(4)
This has fixed the solution! Thanks!Diandiana
You're welcome. If this answer solved your problem, please mark it as accepted (by clicking on the checkmark beside it).Jinx
If your tests have started failing after updating to XCode 8.3, this will be because of a previous bug that has been fixed by Apple. "Fixed a bug in the handling of XCTestExpectations that waited on predicates evaluated against XCUIElements. As a result, some tests which were previously succeeding despite ambiguous (incorrect) queries will start to fail."Assimilative
The correct approach to solve this issue is to assign a unique different accessibilityIdentifier to each UIButton. For example you can use a string of the type "(button.title)_(index)", where index is an index number associated to the button. If the UIButton is a subview of a custom UITableViewCell or UICollectionViewCell, remember to reset the accessibilityIdentifier to nil in the prepareForReuse function.Focalize
L
11

There are a couple of ways to go about solving this issue.

Absolute Indexing

If you absolutely know the button will be the second one on the screen you can access it by index.

XCUIApplication().buttons.element(boundBy: 1)

However, any time the button moves on the screen, or other buttons are added, you might have to update the query.

Accessibility Update

If you have access to the production code you can change the accessibilityTitle on the button. Change it something more specific than the title text and then access the button via test using the new title. This property only shows up for testing and won't be presented to the user when reading off the screen.

More Specific Query

If the two buttons are nested inside of other UI elements you can write a more specific query. Say, for example, that each button is inside of a table view cell. You can add accessibility to the table cells then query for the button.

let app = XCUIApplication()
app.cells["First Cell"].buttons["View 2 more offers"].tap()
app.cells["Second Cell"].buttons["View 2 more offers"].tap()
Libretto answered 12/9, 2016 at 11:38 Comment(1)
Thank you for the documentation, you were correct in myself needing to specify the query more. BTW good job on the blog, been helping myself lots recently while learning the testing!Diandiana
R
11

Xcode 9 introduces a firstMatch property to solve this issue:

app.staticTexts["View 2 more offers"].firstMatch.tap()
Resultant answered 8/8, 2017 at 12:52 Comment(2)
I also used to think this but somewhere I read that firstMatch is NOT for this purpose and referred to firstMatch's doc developer.apple.com/documentation/xctest/… :)Introduction
I love this solution because for some reason I was receiving the error even though I had only one element.Ridgeling
C
1

You should use matching, then element, like

let predicate = NSPredicate(format: "identifier CONTAINS 'Cat'")
let image = app.images.matching(predicate).element(boundBy: 0)
Candace answered 31/5, 2017 at 12:55 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.