Running XCTests from the Command Line
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
xcodebuild
- The Scheme argument
- The Destination argument
- iOS Simulator
- iOS Physical Device
- Listing Destination options
- Other
xcodebuild
arguments - 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
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 selectingProduct > Test
in Xcode.-project
or-workspace
: The path to your Xcode Project (.xcodeproj
) or Xcode Workspace file (.xcworkspace
).-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.
iOS Simulator
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 name
or id
must be provided, but not both. If you have multiple devices plugged into your machine, id
is convenient to use.
For example:
$ xcodebuild \
test \
-project NewTaukTestProject.xcodeproj \
-scheme NewTaukTestProject \
-destination 'platform=iOS,name=Nathan's iPhone'
or
$ 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.
Other xcodebuild
Arguments
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:
-only-testing:TestBundle/TestSuite/TestCase
- 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.
For example:
$ xcodebuild \
test \
-project NewTaukTestProject.xcodeproj \
-scheme NewTaukTestProject \
-destination 'platform=iOS Simulator,name=iPhone 13' \
-only-testing:NewTaukTestProjectUITests/NewTaukTestProjectUITests/testGetStockPriceForCompany
Member discussion