iOS — Separation of XCUnit & XCUITest jobs in CircleCI for single & multi app regions/variants

Suparna Khamaru
5 min readAug 14, 2020

--

In this article, each Test Bundle in iOS with/without varieties of “Build Configurations” is arranged to run in separate CircleCI jobs smoothly and effortlessly.

Aim of this article is to help iOS professionals in configuring & running multiple iOS Test Bundles (such as Unit tests, UI tests, Visual tests etc..) independently in segregated CircleCI jobs (instead of running all tests in one job itself, when configured through the documented steps of CircleCI docs).

Which means this article also provides the solution to configure running of separate tests dealing with multiple build-and-test configurations (denoting single as well as multi app variants) in an existing iOS project.

Configured using Fastlane, Scan and CircleCI

Pre-requisites:

  • Basic Set up of an existing Build & Test configurations in iOS project for running in CircleCI
  • Create separate schemes (such as UITests, UnitTests,..) for each Test Bundles in Xcode
  • All the test bundles should be executing fine locally on all the build configurations in Xcode

Fastlane (Fastfile)

  • Create new lanes for each Scheme and Build Configurations
  • Usage of Build Configuration field is optional for single app project
  • Usage of Build Configuration (Debug, Release,..) is helpful and recommended for multi app project

╰☆╮For convenience and ease of understanding, let us name our sample iOS app’s new test bundle names as below in Xcode:

  • UI test bundle as “UITests(Add as Scheme, upon creation)
  • Unit test bundle as “UnitTests(Add as Scheme, upon creation)

Test Lanes in Fastlane file — Fastfile

  1. Create a reusable test method for passing parameterised schemes and build configurations to test lanes
private_lane: Parameterised do |options|
scan(
workspace: “XYZ.xcworkspace”,
device: “iPhone 12”,
scheme: options[:scheme],
configuration: options[:build_configuration],
output_directory: “output/scan”,
clean: true
)
end

2. Create a test lane — ‘UITestOfAppA’ to reuse above parameterised function for running a job in CircleCI specifically for UI tests on App ‘A’

#Lane 1:desc “Execute — UI Tests - App A
lane: UITestOfAppA do
Parameterised(scheme: “UITests”, build_configuration: “DebugAppA”)
end

3. Create another test lane — ‘UITestOfAppBfor running a job in CircleCI specifically for UI tests on App ‘B’

#Lane 2: desc “Execute — UI Tests — App B
lane: UITestOfAppB do
Parameterised(scheme: “UITests”, build_configuration: “DebugAppB”)
end

4. Create another test lane — ‘UnitTestOfAppAfor running a job in CircleCI specifically for Unit tests on App ‘A’

#Lane 3:desc “Execute — Unit Tests — App A
lane: UnitTestOfAppA do
Parameterised(scheme: “UnitTests”,build_configuration: “DebugAppA”)
end

5. And similarly go on creating separate test lanes for each Test Bundle with required varieties of test schemes, targets and build configurations.

Note:

  • Above build_configuration values should match with the build configurations of your test scheme in Xcode as can be observed from the sample reference below:

(Xcode → Choose UITests Bundle in scheme → Edit Scheme → Test → Info )

Example: If in Xcode - the scheme is ‘UITests’, and the ‘build configuration’ values are ‘Debug’ for App ‘A’ and/or ‘DebugAppB’ for App ‘B’, then the same values must be used in fastlane file too - for App: ‘A’ and ‘B’

In case of single iOS app variant project, usage of ‘build_configuration’ is optional and one may choose to skip its usage in fastlane file.

Also, make sure that the test scheme target is configured correctly to let the tests run independently, when required by checking — ‘Test’ & ‘Run’ as highlighted in the reference below:

(Xcode → Choose UITests Bundle in scheme → Edit Scheme → Build)

CircleCI (config.yml)

Although the prime configurations are already done in fastfile, the set up of jobs and workflow of the jobs running in CircleCI pipeline is to be defined in config.yml.

There are many ways and approaches to do it. Below ones are just for reference of one of the many ways/approaches used by teams.

  1. Configure a generic command for running the tests

2. Configure a series of generic steps for every test run in CI

Note: ‘parallelism’ can be skipped, if test targets are not more than 1 iOS device at a time for each job

3. Add new jobs for all the tests to configure separate runs in CI

4. Add the above configured jobs in ‘workflows’ for ACI pipeline with the exact laneNames added in fastfile.

Configuration of CRON jobs in CircleCI for iOS tests

This is an optional test step and comes in handy when we want to run specific tests on a scheduled manner daily/weekly/monthly based on project’s requirement.

Most companies run all automated test suites every night, so that stakeholders can watch the test run reports by morning everyday.

As can be observed from the above working copy of the scheduled job — We have also filtered GitHub branch for running the “UI Test of App A” alone every night.

In the above syntax, we can also observe that we can filter based on generic as well as pre-defined branch names, where CRON job shall run every night on all the GitHub branches that contains “ui-test” text in any branch names, while anyway running on master consistently.

At the end, CRON jobs look something like this in CircleCI when run by scheduled job

Thanks for reading this article! Leave a comment below if you have any questions. Be sure to click on the 👏 icon to let me know that you encourage my writing.

Connect with me:

--

--