Testing iOS Applications on macOS
This document describes how to set up and customize testing for an iOS application with CircleCI in the following sections:
- Supported Xcode versions
- Getting started
- Using Fastlane
- Using Ruby
- Using NodeJS
- Using Homebrew
- Configuring deployment
- Troubleshooting
- Next steps
Overview
CircleCI offers support for building, testing and deploying iOS projects in macOS virtual machines. Each image provided has a set of common tools installed, such as Ruby and OpenJDK, alongside a version of Xcode. For more information about supplied images, refer to the software manifest for each Xcode image.
There is documentation for an iOS example project and getting started on MacOS.
Supported Xcode versions
(1) Xcode 10.3 is unsupported by our dedicated hosts. See the Dedicated Host for macOS page to learn more about this resource class.
Note: macOS App UI Testing is supported on Xcode 11.7 and higher
Xcode image removal notice: In accordance with our Xcode image policy, deprecated macOS images will be removed on August 2, 2022. For a list of impacted images, refer to the Xcode Image Deprecation post in the Discuss forum.
Getting started
Select a macOS project repository you would like to build from the Projects page of the CircleCI web app.
We highly recommend using Fastlane to build and sign your apps in CircleCI. Fastlane requires minimal configuration in most cases and simplifies the build-test-deploy process.
Setting up your Xcode project
After setting up the project on CircleCI, you will need to ensure that the scheme you intend to build with Fastlane is marked as “shared” in your Xcode project. In most new projects created by Xcode, the default scheme will already be marked as “shared”. To verify this, or to share an existing scheme, complete the following steps:
- In Xcode, choose Product -> Scheme -> Manage Schemes
- Select the “Shared” option for the scheme to share, and click Close
- Ensure the
myproject.xcodeproj/xcshareddata/xcschemes
directory is checked into your Git repository and push the changes
Simple projects should run with minimal configuration. You can find an example of a minimal config in the iOS Project Tutorial.
Using Fastlane
Fastlane is a set of tools for automating the build and deploy process of mobile apps. We encourage the use of Fastlane on CircleCI as it simplifies the setup and automation of the build, test and deploy process. Additionally, it allows parity between local and CircleCI builds.
Adding a Gemfile
It is recommended to add a Gemfile
to your repository to make sure that the same version of Fastlane is used both locally and on CircleCI and that all dependencies are installed. Below is a sample of a simple Gemfile
:
# Gemfile
source "https://rubygems.org"
gem 'fastlane'
After you have created a Gemfile
locally, you will need to run bundle install
and check both Gemfile
and Gemfile.lock
into your project repository.
Setting up Fastlane for use on CircleCI
When using Fastlane in your CircleCI project, we recommend adding the following to beginning of your Fastfile
:
# fastlane/Fastfile
...
platform :ios do
before_all do
setup_circle_ci
end
...
end
The setup_circle_ci
Fastlane action must be in the before_all
block to perform the following actions:
- Create a new temporary keychain for use with Fastlane Match (see the code signing section for more details).
- Switch Fastlane Match to
readonly
mode to make sure CI does not create new code signing certificates or provisioning profiles. - Set up log and test result paths to be easily collectible.
Example Configuration for Using Fastlane on CircleCI
A basic Fastlane configuration that can be used on CircleCI is as follows:
# fastlane/Fastfile
default_platform :ios
platform :ios do
before_all do
setup_circle_ci
end
desc "Runs all the tests"
lane :test do
scan
end
desc "Ad-hoc build"
lane :adhoc do
match(type: "adhoc")
gym(export_method: "ad-hoc")
end
end
This configuration can be used with the following CircleCI config file:
# .circleci/config.yml
version: 2.1
jobs:
build-and-test:
macos:
xcode: 12.5.1
environment:
FL_OUTPUT_DIR: output
FASTLANE_LANE: test
steps:
- checkout
- run: bundle install
- run:
name: Fastlane
command: bundle exec fastlane $FASTLANE_LANE
- store_artifacts:
path: output
- store_test_results:
path: output/scan
adhoc:
macos:
xcode: 12.5.1
environment:
FL_OUTPUT_DIR: output
FASTLANE_LANE: adhoc
steps:
- checkout
- run: bundle install
- run:
name: Fastlane
command: bundle exec fastlane $FASTLANE_LANE
- store_artifacts:
path: output
workflows:
build-test-adhoc:
jobs:
- build-and-test
- adhoc:
filters:
branches:
only: development
requires:
- build-and-test
The environment variable FL_OUTPUT_DIR
is the artifact directory where FastLane logs and signed .ipa
file should be stored. Use this to set the path in the store_artifacts
step to automatically save logs and build artifacts from Fastlane.
Code Signing with Fastlane Match
We recommend the use of Fastlane Match for signing your iOS applications as it simplifies and automates the process of code signing both locally and in the CircleCI environment.
For more information on how to get started with Fastlane Match, please see our iOS code signing documentation.
Using Ruby
Our macOS images contain multiple versions of Ruby. The default version in use on all images is the system Ruby. The images also include the latest stable versions of Ruby at the time that the image is built. We determine the stable versions of Ruby using the Ruby-Lang.org downloads page. The versions of Ruby that are installed in each image are listed in the software manifests of each container.
If you want to run steps with a version of Ruby that is listed as “available to chruby” in the manifest, then you can use chruby
to do so.
Note: Installing Gems with the system Ruby is not advised due to the restrictive permissions enforced on the system directories. As a general rule, we advise using one of the alternative Rubies provided by Chruby for all jobs.
Switching Rubies with the macOS Orb (Recommended)
Using the official macOS Orb (version 2.0.0
and above) is the easiest way to switch Rubies in your jobs. It automatically uses the correct switching command, regardless of which Xcode image is in use.
To get started, include the orb at the top of your config:
# ...
orbs:
macos: circleci/macos@2
Then, call the switch-ruby
command with the version number required. For example, to switch to Ruby 2.6:
steps:
# ...
- macos/switch-ruby:
version: "2.6"
Replace 2.6
with the version you require from the Software Manifest file. You do not need to specify the full Ruby version, 3.0.2
for example, just the major version. This will ensure your config does not break when switching to newer images that might have newer patch versions of Ruby.
To switch back to the system default Ruby (the Ruby shipped by Apple with macOS), define the version
as system
:
steps:
# ...
- macos/switch-ruby:
version: "system"
Note: Xcode 11.7 images and later images default to Ruby 2.7 via chruby
out of the box. Xcode 11.6 images and earlier default to the System Ruby.
Images using Xcode 11.7 and later
To switch to another Ruby version, add the following to the beginning of your job.
steps:
# ...
- run:
name: Set Ruby Version
command: sed -i '' 's/^chruby.*/chruby ruby-3.0/g' ~/.bash_profile
Replace 3.0
with the version of Ruby required - you do not need to specify the full Ruby version, 3.0.2
for example, just the major version. This will ensure your config does not break when switching to newer images that might have newer patch versions of Ruby.
To revert back to the system Ruby, add the following to the beginning of your job:
steps:
# ...
- run:
name: Set Ruby Version
command: sed -i '' 's/^chruby.*/chruby system/g' ~/.bash_profile
Images using Xcode 11.2 and later
To select a version of Ruby to use, add the chruby
function to ~/.bash_profile
:
steps:
# ...
- run:
name: Set Ruby Version
command: echo 'chruby ruby-2.6' >> ~/.bash_profile
Replace 2.6
with the version of Ruby required - you do not need to specify the full Ruby version, 2.6.5
for example, just the major version. This will ensure your config does not break when switching to newer images that might have slightly newer Ruby versions.
Images using Xcode 11.1 and earlier
To specify a version of Ruby to use, you can create a file named .ruby-version
, as documented by chruby
. This can be done from a job step, for example:
steps:
# ...
- run:
name: Set Ruby Version
command: echo "ruby-2.4" > ~/.ruby-version
Replace 2.4
with the version of Ruby required - you do not need to specify the full Ruby version, 2.4.9
for example, just the major version. This will ensure your config does not break when switching to newer images that might have slightly newer Ruby versions.
Installing additional Ruby versions
Note: Installing additional Ruby versions consumes a lot of job time. We only recommend doing this if you must use a specific version that is not installed in the image by default.
To run a job with a version of Ruby that is not pre-installed, you must install the required version of Ruby. We use the ruby-install tool to install the required version. After the install is complete, you can select it using the appropriate technique above.
Using Custom Versions of CocoaPods and Other Ruby Gems
To make sure the version of CocoaPods that you use locally is also used in your CircleCI builds, we suggest creating a Gemfile in your iOS project and adding the CocoaPods version to it:
source 'https://rubygems.org'
gem 'cocoapods', '= 1.3.0'
Then you can install these using bundler:
steps:
- restore_cache:
key: 1-gems-{{ checksum "Gemfile.lock" }}
- run: bundle check || bundle install --path vendor/bundle --clean
- save_cache:
key: 1-gems-{{ checksum "Gemfile.lock" }}
paths:
- vendor/bundle
You can then ensure you are using those, by prefixing commands with bundle exec
:
# ...
steps:
- run: bundle exec pod install
Using NodeJS
The Xcode images are supplied with at least one version of NodeJS ready to use.
Images using Xcode 13 and later
These images have NodeJS installations managed by nvm
and will always be supplied with the latest current
and lts
release as of the time the image was built. Additionally, lts
is set as the default NodeJS version.
Version information for the installed NodeJS versions can be found in the software manifests for the image], or by running nvm ls
during a job.
To set the current
version as the default:
# ...
steps:
- run: nvm alias default node
To revert to the lts
release:
# ...
steps:
- run: nvm alias default --lts
To install a specific version of NodeJS and use it:
# ...
steps:
- run: nvm install 12.22.3 && nvm alias default 12.22.3
These images are also compatiable with the official CircleCI Node orb, which helps to manage your NodeJS installation along with caching packages.
Images using Xcode 12.5 and earlier
These images come with at least one version of NodeJS installed directly using brew
.
Version information for the installed NodeJS versions can be found in the software manifests for the image].
These images are also compatiable with the official CircleCI Node orb which helps to manage your NodeJS installation, by installing nvm
, along with caching packages.
Using Homebrew
Homebrew is pre-installed on CircleCI, so you can simply use brew install
to add nearly any dependency you require to complete your build. For example:
# ...
steps:
- run:
name: Install cowsay
command: brew install cowsay
- run:
name: cowsay hi
command: cowsay Hi!
It is also possible to use the sudo
command if necessary to perform customizations outside of Homebrew.
Configuring deployment
After the app has been tested and signed, you are ready to configure deployment to your service of choice, such as App Store Connect or TestFlight. For more information on how to deploy to various services, including example Fastlane configurations, check out the deploying iOS apps guide
Troubleshooting
If you are facing build failures while executing your jobs, check out our support center knowledge base for answers to common issues.
Next steps
- See the
circleci-demo-ios
GitHub repository for a full example of how to build, test, sign and deploy an iOS project using Fastlane on CircleCI. - See the iOS Project Tutorial for a config walkthrough.
- See the iOS code signing documentation to learn how to configure Fastlane Match for your project.
Help make this document better
This guide, as well as the rest of our docs, are open source and available on GitHub. We welcome your contributions.
- Suggest an edit to this page (please read the contributing guide first).
- To report a problem in the documentation, or to submit feedback and comments, please open an issue on GitHub.
- CircleCI is always seeking ways to improve your experience with our platform. If you would like to share feedback, please join our research community.
Need support?
Our support engineers are available to help with service issues, billing, or account related questions, and can help troubleshoot build configurations. Contact our support engineers by opening a ticket.
You can also visit our support site to find support articles, community forums, and training resources.
CircleCI Documentation by CircleCI is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License.