How to automatically take Screenshots with Fastlane Snapshot

Grabbing screenshots for store display can become an exhausting work. Clicking button X to open screen B and take a screenshot, or input a username & password then wait for the login process or taking an exact screen which deeply nested. Multiply it by how many localisation that’s supported. Also, don’t forget the revision or new design for next month. Now if you didn’t automate your way to do all this, then you’re doing it wrong.

Introducing Fastlane Snapshot (for iOS & tvOS), tools for automating all this hard work for taking app snapshots.

Setup

To install Fastlane, you need to have Ruby installed first (which is installed by default in MacOS) and then run the command

gem install fastlane

This will install all the Fastlane tools including Snapshot and Screengrab.

iOS Project Setup

For this tutorial, we’ll be using project that we’ve created. You can git clone it here or download the zip file here. This app contains 2 screen with en-US & fr-FR localisation.
To start with Fastlane snapshot, open your terminal and type

fastlane snapshot init

This command will add 2 files, SnapshotHelper.swift is a class that contains helper methods to get snapshots. Snapfile is a configuration file for Fastlane Snapshot.

Now open the app project and add SnapshotHelper.swift inside HelloAppUITests folder. Next, open HelloAppUITests.swift and remove everything inside setUp method except super.setUp(), then add this lines to setup Snapshot

let app = XCUIApplication()
setupSnapshot(app)
app.launch()

Next, we will add Localization.strings and a helper method to get Localisation strings inside UI Tests. Click on HelloApp project, head to HelloAppUITests target. Go to Build Phase, expand Copy Bundle Resources and press + button then choose Localizable.strings.

Now open HelloAppUITests.swift and add this method :

func localizedString(key: String) -> String {
    let localizationBundle = Bundle(for: HelloAppUITests.self)        

    // handle "en-US" localisation
    if let path = localizationBundle.path(forResource: deviceLanguage, ofType: "lproj") {
        let deviceBundle = Bundle(path: path)
        let result = NSLocalizedString(key, bundle: deviceBundle!, comment: "")
        return result
    }

    // handle "Base.lproj" localisation
    if let path = localizationBundle.path(forResource: "Base", ofType: "lproj") {
        let deviceBundle = Bundle(path: path)
        let result = NSLocalizedString(key, bundle: deviceBundle!, comment: "")
        return result
    }

    // handle "en" localisation
    if let path = localizationBundle.path(forResource: NSLocale.current.languageCode, ofType: "lproj") {
        let deviceBundle = Bundle(path: path)
        let result = NSLocalizedString(key, bundle: deviceBundle!, comment: "")
        return result
    }
    return "?"
}

This method helps us to locate the Localizable strings inside UI Test and return the localised string from the defined key. Now move your cursor inside testExample(), this will activate the Record button on the bottom left.

Next, Click that button (this will build and run your app on emulator). Then click on “Continue” and in Product Detail page, click on “ADD TO CART“, and press Stop Record button. Above actions will add UI test scenarios inside testExample().

For our Snapshot localisation to work, we need to change the hardcoded strings into its localised version. On the “Continue” change it into

localizedString(key: "Continue")

And on the “Add To Cart” change it into

localizedString(key: "Add To Cart").uppercased()

Next, we will add codes to take & save our snapshots. Modify the code inside testExample() to be like this :

let app = XCUIApplication()
snapshot("01Welcome")
app.buttons[localizedString(key: "Continue")].tap()
snapshot("02Home")
app.buttons[localizedString(key: "Add to cart").uppercased()].tap()
snapshot("03Alert", timeWaitingForIdle: 2)

snapshot(“FileName”) is to take a snapshot and then save it with “FileName.png”. For our alert after tapping “Add to card”, because there’s a 2 seconds delay before alert is shown, we use snapshot(“FileName”, timeWaitingForIdle: n_seconds)

Next, open Snapfile with your text editor. As you can see, there are configurations for device types to be used, languages and others. For optimal results, we want iPhone 8 Plus and iPhone X. For other iPhone sizes, AppStore Connect will resize the screenshots from iPhone 8 Plus and even though iPhone X screenshots is optional, it’s nice to have those, especially with snapshot automation. Next for the language, we will add “en-US” and “fr-FR”. Then we set clear_previous_screenshots to true because we don’t need older screenshots. The final setting for Snapfile is like this :

devices([
    "iPhone 8 Plus",
    "iPhone X"
])

languages([
    "en-US",
    "fr-FR"
])

clear_previous_screenshots(true)

Now open the Terminal and type :

fastlane snapshot

This command will build your app, run it inside the simulators matching the devices setting, run your UI test, take and save snapshots. After done, you should see these results.

Fastlane also generates a nice html page containing all your screenshots for selected devices & localisations.

Leave a Reply

Your email address will not be published. Required fields are marked *