Today and yesterday, I setup and used Fastlane to automate screenshots and upload to testflight. The process was simple and complicated at the same time, and I kept hitting roadblocks. However, the actual working of the thing makes a great deal of sense. I’m going to try to explain the process here. Below this, I’ll leave my normal progress section.

Setting up Fastlane when you don’t really know what you are doing

I had seen several apps in the app store with cool screenshots with frames and titles, and I really wanted to do that. It seemed like a huge PITA given how long it takes to go through the simulator and take screenshots in the first place. When I saw a post about beautiful automated screenshots, I wanted to jump right in. Granted, the post was old, but the ideas were exactly what I needed, and it seems the tools are about the same, probably better.

Why fastlane?

Fastlane includes tools to help you automate the process of generating and cleaning up screenshots in multiple languages and for all platforms that your app targets. Not only that, but it also automates the process of managing build numbers, provisioning, and uploading your app for beta testing and release. Magic, no?

I’m assuming that if you are reading this, you might be a lot like me, yesterday morning. You have an iOS app and some experience with iTunes Connect. You’ve uploaded before, at least some app, because the fastlane value comes from saving time in these steps that you know take FOREVER once you’ve done them a few times. I’ll further assume that you are comfortable with the terminal shell and git …and you also need to not freak out about installing a bunch of stuff. You should set up fastlane if you ever plan to make changes to your app, ever make another app, or have several languages for your app. Let’s take a moment to be jealous of our future selves with all that time saved. Ahhh.

Okay, I’m ready, how?

The documentation is very useful, but it was not always accessible to me when I was trying to get things to work for the first time. You can certainly do like I did and open every single page of the fastlane webiste in a tab on your browser and try to lookup all of the things flying by you on the terminal window, or, you could relax a little and follow along here. First, go ahead and navigate your browser to the Fastlane docs for reference.

Basic setup steps

  • Fire up the terminal
  • Install fastlane - I used homebrew brew cask install fastlane
  • Navigate to your project directory - this is the outer one that includes your .xcworkspace file.
  • Initialize your project fastlane init (at this point, if you don’t have ruby, I think you will need to do some more installations)
  • Try to read through all the stuff flying by you on the terminal, but don’t sweat it. Fastlane is verbose and helpful.
  • When the terminal asks you a question, answer as makes the most sense for your project. You can always fix it later if you make a mistake here.
  • When everything stops, you should have a fastlane folder.
  • Navigate to that folder and open in your favorite text editor atom .

At this point, you have the option to do many things, but I think the best first step is to make sure that your files make sense. Fastlane accidentally assumed that my app bundle id was the first pod in my pods folder, which I had to correct. Let’s go through the files that you (with a simple app) need to check and update. Your app may require different settings or other adjustments that I don’t show here, please make sure that your settings match what you are doing, especially for export compliance and ratings. If you are missing a file, just create it. There are a couple of places where I say YOUR_UITEST_SCHEME - if you don’t know what that is…we will cover it, just leave that placeholder until you have one.

/fastlane/Appfile – basic information about your app and your itunes connect status

app_identifier "com.TEAM.YOURAPP" # The bundle identifier of your app
# You can find it in your xcode project if you are not sure
apple_id "" # Your Apple email address

itc_team_id "" # iTunes Connect Team ID
team_id "" # Developer Portal Team ID

# For more information about the Appfile, see:
#     https://docs.fastlane.tools/advanced/#appfile

/fastlane/Fastfile – sets up all the cool stuff you are going to do let’s keep it safe for now, no release You can see here that we have two “lanes”: beta and screenshots. More on that later.

default_platform(:ios)
  lane :beta do
      ensure_git_status_clean
      increment_build_number
      commit_version_bump
      add_git_tag
      build_app(
          workspace: "YOUR.xcworkspace",
          scheme: "YOURMAIN",
          clean: true
          )
      upload_to_testflight(
          app_identifier: "YOUR_BUNDLE_ID"
          )
  end

  lane :screenshots do
    capture_screenshots(workspace: "YOUR.xcworkspace", scheme: "YOUR_UITEST_SCHEME")
    frame_screenshots(white: true)
  end
end

/fastlane/Deliverfile – this one makes setup of your iTunes connect a little easier

# The Deliverfile allows you to store various iTunes Connect metadata
# For more information, check out the docs
# https://docs.fastlane.tools/actions/deliver/

price_tier 0
app_review_information(
  first_name: "YOUR",
  last_name: "YOUR",
  phone_number: "YOUR",
  email_address: "YOUR",
  demo_user: "N/A",       # add the user if testers will need to log in
  demo_password: "N/A",   # add the password if testers need it
  notes: "ANY NOTES FOR TESTING"
)
# if you app has more complex structure, check out /fastlane/metadata/review_information folder

submission_information({
    export_compliance_encryption_updated: false,
    export_compliance_uses_encryption: false,
    content_rights_contains_third_party_content: false,
    add_id_info_uses_idfa: false
})

automatic_release false

app_icon './fastlane/metadata/AppIcon.png'

app_rating_config_path "./fastlane/metadata/itunes_rating_config.json"

/fastlane/Snapfile – this one handles screenshots you don’t need to customize much

# The app bundle
app_identifier "com.TEAM.YOURS"
# A list of devices you want to take the screenshots from
devices([
   "iPhone 6",
   "iPhone 8 Plus",
   "iPhone X"
])

# languages([
#   "en-US",
#   "de-DE",
#   "it-IT",
#   ["pt", "pt_BR"] # Portuguese with Brazilian locale
# ])

# The name of the scheme which contains the UI Tests
scheme "YOUR_UITEST_SCHEME"

# Where should the resulting screenshots be stored?
output_directory "./screenshots"

# remove the '#' to clear all previously generated screenshots before creating new ones
clear_previous_screenshots false

# Arguments to pass to the app on launch. See https://docs.fastlane.tools/actions/snapshot/#launch-arguments
# launch_arguments(["-favColor red"])

# For more information about all available options run
# fastlane action snapshot

/fastlane/metadata/itunes_rating_config.json – this one may not be in your metadata but go ahead and build it and set it to match your app

{
  "CARTOON_FANTASY_VIOLENCE": 0,
  "REALISTIC_VIOLENCE": 0,
  "PROLONGED_GRAPHIC_SADISTIC_REALISTIC_VIOLENCE": 0,
  "PROFANITY_CRUDE_HUMOR": 0,
  "MATURE_SUGGESTIVE": 0,
  "HORROR": 0,
  "MEDICAL_TREATMENT_INFO": 0,
  "ALCOHOL_TOBACCO_DRUGS": 0,
  "GAMBLING": 0,
  "SEXUAL_CONTENT_NUDITY": 0,
  "GRAPHIC_SEXUAL_CONTENT_NUDITY": 0,
  "UNRESTRICTED_WEB_ACCESS": 0,
  "GAMBLING_CONTESTS": 0
}

/fastlane/metadata/AppIcon.png – just go and copy the 1024x version of your appicon and paste it here. If you call it something else, update the path in the Deliverfile

Setup UI Tests for screenshots

At this point, your fastlane folder and files are all setup to allow you to automate screenshots. If you want to add fancy titles to them, you must add any image file that you refer to as the background in the Framefile. I’m not going to cover titles because it is laid out better by frameit and the github example than I could do here. However, I had to learn for myself that the background image could be whatever you wanted. I just created it in GIMP. Play with it. Also, you don’t have to have the font statements if you don’t want to use a special font.

Fastlane automates your screenshots by taking snapshots during UI testing. Sadly, before I wanted to do this, I had never setup UI Tests because I thought the were super complicated. If you’ve done them before, just hang with me here. You need to have a UITesting scheme set up to make this work, but we will walk through it, it’s not that hard:

  • Open your project in Xcode
  • Select File/New/Target/..find Cocoa Touch UI Testing Bundle
  • Find your new Project_UI_Tests folder
  • Click to open Project_UI_Tests.swift
  • Paste this inside the function setup, between the {}
    let app = XCUIApplication()
    setupSnapshot(app)
    app.launch()
    
  • Put your cursor in the function testExample, between the {}
  • Now, click the little red button at the bottom, a simulator will pop up, and you can navigate through your app - do all of the important things (or not, it can even be just the onboard if you want to get the hang of this)
  • When you are finished, click the red button again
  • Now, you need to go through what the simulator automated to make sure it is correct. There may be points where the simulator doesn’t get out of a text field or doesn’t select a choice in a picker.
  • When it is fine, pick a few points where you want to have a screenshot and add code like snapshot("0Login") or snapshot("2ChangeDate") - the idea is to have them ordered chronologically (for your sanity) and with a key that you can use in your Framefile, if you decide to make fancy frames later.
  • Now, create a new scheme for your tests:
    • Scheme - new scheme
    • Select your UITests
    • Name it something <- this something is what goes in those YOUR_UITEST_SCHEME placeholders above.
    • Edit it to ensure that it is shared (there’s a little checkbox)

Let’s run

So now, we’ve setup the project to use fastlane, and we’ve created UI tests to take screenshots. We are all set. Let’s try a set of screenshots first. NOTE: Xcode is super testy, and this may take a few tries, also, you may need to edit your UITest function again until all the right inputs happen. We’ll assume it works because eventually it will.

Try the Screenshots first

  • Save your project work (you actually don’t need xcode open now)
  • Navigate back to the terminal
  • Commit all of your changes
  • type bundle exec fastlane screenshots – this will run the “lane” for screenshots that we set up earlier in our Fastfile.
  • Terminal will be working for a bit. You can try to watch the output fly by or go do something else. Essentially, it is going to go into your project, run the UITests, and take screenshots. It will then combine them all in a nice HTML file.
  • Use your screenshots wherever. …maybe go checkout frameit to make them prettier and good for iTunes Connect

Now the Beta test

  • Navigate back to the terminal
  • Commit all of your changes <- this is actually important here because our beta lane will scream at us if we have a dirty directory
  • type bundle exec fastlane beta
  • Terminal will be working for awhile (took mine 24 minutes). Go do something else. Squats, anyone?
  • Celebrate when Testflight notifies you of your new app to test.

That’s it. Now, you have a better understanding and can probably use the docs to do even more cool stuff.

Your story was great and all, but I need a different resource

That’s cool. I understand. After I did all of my setup and had it working on my machine, I looked for other resources. There is a fantastic tutorial on using fastlane on RayWenderlich. It is slightly outdated, but the approach is sound and they even give you a fake app to play with if you don’t want to use yours. Or, maybe you are way ahead of the game and don’t have an app yet. Awesome for you. If the tutorial doesn’t help you, try the docs again or reach out to the community on github, stack overflow, or even twitter.

Today’s Progress

  • Uploaded another version of the Challenge application to beta testing (using fastlane) - it was awesome.
  • Updated my DayOne journals and tested out the CLI
  • Brought several more repos into Open Collective
  • Spent a few hours trying to understand TCP/IP in python. I set up a CLI using python that will say hello and stuff, but I deleted it because that was not where I wanted to go. I can still only using my python client to post and get with httpbin.org or get the time from a local server. I think that this means that I have greater understanding (or the code is simpler) for the client side, and I will need to spend more time understanding the server side.
  • Updated the Genius Tools on this site, and I think I will be moving coding resources there.
  • Yesterday, I forgot to note that I removed wakatime because I was tired of XCode bugging me about it. Nothing against wakatime.