UPGRADE YOUR SKILLS: Learn advanced Swift and SwiftUI on Hacking with Swift+! >>

SOLVED: UI Tests, screenshots, and fastlane

Forums > iOS

I've just spent the past two days wrestling with fastlane and with my laptop's ruby installation, but now I've got my project set up so that it can generate all my app screenshots for the App Store. Yay!

Except.

Some of the necessary screen shots are for devices that have a Home button, and some are for devices that do not. For example, the 3rd generation iPad Pro (12.9" display) doesn't have a Home button and the screen shot will therefore have the little widget at the bottom, while the 2nd generation iPad Pro (12.9" display) does have a Home button, and so those screen shots will not have a bar at the bottom.

Which is fine, in itself, as we have simulators for all these devices and can run the UI tests against them all, and take the screen shots. But, and this is the part that's tripping me up, the widget hierarchy on the screen is different, depending on which of these device types we've got!

In order to get the corner tile in my game board and tap on it, to show what the screen looks like when a tile is selected, here's what I do for a classic iPad with a home button:

    func testWithHomeButton() throws {
        snapshot("01MainMenu")
        app.buttons["Medium Board"].tap()

        snapshot("02MediumBoard")
        let element = app.windows.children(matching: .other)
            .element.children(matching: .other)
            .element.children(matching: .other)
            .element

        element.children(matching: .image).matching(identifier: "1").element(boundBy: 0).tap()
        snapshot("03SelectATile")
        element.children(matching: .image).matching(identifier: "1").element(boundBy: 1).tap()
        snapshot("04SelectAMatch")
    }

Now, here's what I have to do on a device with no home button:

    func testWithoutHomeButton() throws {
        snapshot("01MainMenu")
        app.buttons["Medium Board"].tap()

        snapshot("02MediumBoard")
        let element = app.windows.children(matching: .other)
            .element.children(matching: .other)
            .element.children(matching: .other)
            .element.children(matching: .other)
            .element

        element.children(matching: .image).matching(identifier: "1").element(boundBy: 0).tap()
        snapshot("03SelectATile")
        element.children(matching: .image).matching(identifier: "1").element(boundBy: 1).tap()
        snapshot("04SelectAMatch")
    }

The only difference is that the game board is nested one layer deeper without a Home button. This makes me think there must be a better way to get hold of these things, better than this .element.children(matching: .other)... for a magic number of times. Is there a label I should be applying in my SwiftUI code, that the test could then look for?

3      

Aha! It was as simple as changing one children to descendants, and using the shallower tree.

        element.descendants(matching: .image).matching(identifier: "1").element(boundBy: 0).tap()

Thanks for the article, Paul!

3      

TAKE YOUR SKILLS TO THE NEXT LEVEL If you like Hacking with Swift, you'll love Hacking with Swift+ – it's my premium service where you can learn advanced Swift and SwiftUI, functional programming, algorithms, and more. Plus it comes with stacks of benefits, including monthly live streams, downloadable projects, a 20% discount on all books, and free gifts!

Find out more

Sponsor Hacking with Swift and reach the world's largest Swift community!

Archived topic

This topic has been closed due to inactivity, so you can't reply. Please create a new topic if you need to.

All interactions here are governed by our code of conduct.

 
Unknown user

You are not logged in

Log in or create account
 

Link copied to your pasteboard.