Start Building for Free
CircleCI.comAcademyBlogCommunitySupport

Testing iOS applications on macOS

1 month ago6 min read
Cloud
On This Page

This document describes how to set up and customize testing for an iOS application with CircleCI.

Overview

CircleCI offers support for building, testing, and deploying iOS projects on 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.

Refer to iOS code signing projects and getting started on macOS pages for further information.

Supported Xcode versions

Supported Xcode versions for Apple silicon

ConfigXcode VersionmacOS VersionVM Software ManifestRelease Notes

16.2.0

Xcode 16.2 Beta 2 (16C5013f)

14.6.1

Installed software

Release Notes

16.1.0

Xcode 16.1 (16B40)

14.6.1

Installed software

Release Notes

16.0.0

Xcode 16.0 (16A242d)

14.6.1

Installed software

Release Notes

15.4.0

Xcode 15.4 (15F31d)

14.3.1

Installed software

Release Notes

15.3.0

Xcode 15.3 (15E204a)

14.3.1

Installed software

Release Notes

15.2.0

Xcode 15.2 (15C500b)

14.1

Installed software

Release Notes

15.1.0

Xcode 15.1 (15C65)

14.1

Installed software

Release Notes

15.0.0

Xcode 15 (15A240d)

13.5.1

Installed software

Release Notes

14.3.1

Xcode 14.3.1 (14E300b)

13.2.1

Installed software

Release Notes

14.2.0

Xcode 14.2 (14C18)

12.6.3

Installed software

Release Notes

14.1.0

Xcode 14.1 (14B47b)

12.6.1

Installed software

Release Notes

14.0.1

Xcode 14.0.1 (14A400)

12.6.1

Installed software

Release Notes

13.4.1

Xcode 13.4.1 (13F100)

12.6.1

Installed software

Release Notes

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:

  1. In Xcode, choose Product -> Scheme -> Manage Schemes

  2. Select the "Shared" option for the scheme to share, and select Close

  3. Ensure the myproject.xcodeproj/xcshareddata/xcschemes directory is checked into your Git repository and push the changes

Simple projects should run with minimal configuration.

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 configuration file:

# .circleci/config.yml
version: 2.1
jobs:
  build-and-test:
    macos:
      xcode: 14.0.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: 14.0.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, visit the iOS code signing page.

Using Ruby

Our Xcode images ship with multiple versions of Ruby installed. The versions we install are the latest stable versions of Ruby, according to Ruby-Lang.org downloads page, at the time the image is built. The versions of Ruby that are installed in each image, along with the default Ruby selected for that image, are listed in the software manifests of each container (see supported Xcode versions).

Installing gems with the system Ruby is not advised due to the restrictive permissions enforced on the system directories. As a general rule, CircleCI advises using one of the alternative Rubies provided by Chruby (as configured by default in all images) for jobs.

Switching Rubies with the macOS orb

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 configuration:

# ...
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: "3.1"

Replace 3.1 with the version you require from the Software Manifest file. You do not need to specify the full Ruby version, 3.1.3 for example, just the major version. This will ensure your configuration 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"

Switching Rubies manually

For Xcode version 14.2 and higher, add the following to the beginning of your job.

steps:
  # ...
  - run:
      name: Set Ruby Version
      command: rbenv global 3.1.3 && rbenv rehash

Replace 3.1.3 with the version of Ruby required.

To revert back to the system Ruby, specify system as the Ruby version.

For Xcode versions 14.1 and lower, add the following to the beginning of your job.

steps:
  # ...
  - run:
      name: Set Ruby Version
      command: sed -i '' 's/^chruby.*/chruby ruby-3.1.3/g' ~/.bash_profile

Replace 3.1.3 with the version of Ruby required.

To revert back to the system Ruby, specify system as the Ruby version.

Installing additional Ruby versions

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.

For Xcode versions 14.2 and higher, this can be done with the rbenv install command, ensuring you pass the version of Ruby required. If a newer version of Ruby is not available, you will need to update the ruby-build package (brew upgrade ruby-build) to ensure the latest Ruby version definitions are available.

For Xcode versions 14.1 and lower, 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 compatible 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 (see supported Xcode versions).

These images are also compatible 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


Suggest an edit to this page

Make a contribution
Learn how to contribute