Update: I've created a Discord server for discussing all things related to automation testing! Join our community today 👋:
Apple’s Xcode IDE provides a comprehensive graphical interface for developing, configuring, and running XCTests. However, in order to tests from a remote server (such as a CI/CD server), you won’t have access to the Xcode IDE and will need to run your tests from the command line. In this guide, we will walkthrough how to use the supplementary
xcodebuild command line tool so you can run your automation tests from the terminal with ease.
Contents of this Guide
- Xcode Command Line Tools
- Running tests with
- The Scheme argument
- The Destination argument
- iOS Simulator
- iOS Physical Device
- Listing Destination options
- Clean Project before running tests
- Running an individual test
Xcode Command Line Tools
When you’re developing automation tests for a iOS app, Xcode provides a convenient local GUI environment with a plethora of tools. However, this comes at the expense of disk space as it weighs in at ~40 GB. When you want to execute tests from a remote server, you won’t have access to the Xcode GUI and won’t need all of its features.
Apple provides a supplementary Xcode Command Line Tools package that is much more trim, only requires ~3 GB of disk space, and has the essentials to run tests solely from the command line. As a result, you can just install the Xcode Command Line Tools on your remote server and forgo the full Xcode installation.
To install the Xcode Command Line Tools, you can run the following command in your MacOS terminal:
$ xcode-select --install
Note: If you have already installed the Homebrew package manager on your machine, you actually already have the Xcode Command Line Tools. Homebrew relies on it as a dependency, since it needs it to build packages.
To verify that it was installed successfully, you can run the following command in your terminal:
$ xcode-select --print-path
This should return the path where the Xcode Command Line Tools were installed.
Running tests with
xcodebuild is the primary command for both building Xcode projects & running tests and accepts a variety of parameters. The essential
xcodebuild command to run a test looks like this:
$ xcodebuild \ test \ -project <Your-Project>.xcodeproj \ -scheme <Your-Scheme> \ -destination 'platform=iOS Simulator,name=iPhone 13'
I’ll provide a quick overview of the parameters and then go into further detail for each in the upcoming sections.
test: Run the test action for the specified scheme. This is like selecting
Product > Testin Xcode.
-workspace: The path to your Xcode Project (
.xcodeproj) or Xcode Workspace file (
-scheme: A scheme is a specific configuration for your target. It defines what happens when you press “Run”, “Build”, “Test”, etc. in Xcode. Each target has at least one scheme by default and you can customize this in Xcode.
-destination: A description of the simulator or physical device you want to run on.
The Scheme Argument
Xcode lets you customize what should happen when you perform an action, such as “Test”, against a target. Using
xcodebuild we can list the available schemes for a given Xcode project or workspace target by running the command.
xcodebuild -list -project <Your-Project>.xcodeproj # OR xcodebuild -list -workspace <Your-Workspace>.xcworkspace
The available schemes will be listed in the output. For example:
Information about project "NewTaukTestProject": Targets: NewTaukTestProject NewTaukTestProjectTests NewTaukTestProjectUITests Build Configurations: Debug Release If no build configuration is specified and -scheme is not passed then "Release" is used. Schemes: NewTaukTestProject
The Destination Argument
The destination argument accepts a key-value pair string. The first key is the platform, which indicates the OS and if your target is a physical device or simulator. The syntax is
key=value,key=value,... and note that there is no space separator between commas.
For the platform key, you can specify any of Apple’s supported platforms (macOS, iOS, watchOS, tvOS), but I’ll focus on iOS. For iOS, we can specify if the platform is a local Simulator or a physical device.
To target the iOS simulator, we can provide a destination string that at minimum should include a
platform key set to
iOS Simulator and a
name key for the Simulator’s name. For example:
-destination 'platform=iOS Simulator,name=iPhone 13'
You can optionally pass an
OS key as well, which is helpful if you have multiple Simulators of the same device type that differ on OS version. For example:
-destination 'platform=iOS Simulator,name=iPhone 13,OS=15.2'
iOS Physical Device
To target a physical iOS device, the
platform key will be set to
iOS and we can provide either a
name key to target the device by its name or
id to target it by its UDID. Note: either a
id must be provided, but not both. If you have multiple devices plugged into your machine,
id is convenient to use.
$ xcodebuild \ test \ -project NewTaukTestProject.xcodeproj \ -scheme NewTaukTestProject \ -destination 'platform=iOS,name=Nathan's iPhone'
$ xcodebuild \ test \ -project NewTaukTestProject.xcodeproj \ -scheme NewTaukTestProject \ -destination 'platform=iOS,id=00000000-000000000000000'
Listing Destination Options
We can get a listing of all the available device target options by running:
$ xcrun simctl list
xcrun is another companion CLI tool that the Xcode Command Line Tools provide. To get the practical gist on how to use it, please check out this blog post we published.
Clean Project Before Running Tests
If you want to ensure that the Xcode project or workspace is cleaned before running your tests you add the
clean command before
test. For example:
$ xcodebuild \ clean \ test \ -project <Your-Project>.xcodeproj \ -scheme <Your-Scheme> \ -destination <Your-Destination>
Running an Individual Test
To run an individual test case from your XCTest suite, you can use the
-only-testing argument. The format for this argument is slightly different than the others we’ve shown so far and looks like this:
- TestBundle is the group name that holds all your tests. In the Xcode GUI it would be the “folder” name containing your test files in the Project Navigator.
- TestSuite is the class name of your test.
- TestCase is the method name of the test within your TestSuite.
$ xcodebuild \ test \ -project NewTaukTestProject.xcodeproj \ -scheme NewTaukTestProject \ -destination 'platform=iOS Simulator,name=iPhone 13' \ -only-testing:NewTaukTestProjectUITests/NewTaukTestProjectUITests/testGetStockPriceForCompany