Getting Started with Xcode Cloud
Learn how to use Xcode Cloud to test and deploy your app on TestFlight. By Josh Berlin.
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Contents
Creating a Workflow to Run Tests
Unit tests and user interface tests — also known as UI tests — are important to ensure you ship stable code. Whenever you change code in the main Git branch, it’s a good idea to run your test suite. Wouldn’t it be nice if your tests ran automatically when code changed?
Good news — Xcode Cloud is here to help! Xcode Cloud can run your tests on code changes, leaving your development machine free for other tasks.
The workflow you’ll configure in this section runs both the unit and UI tests whenever you update the main branch. Xcode Cloud builds your app and runs all your tests. You’ll receive a full report of the tests once they complete. The report shows which tests passed or failed, and it shows screenshots of any failed test.
The Coffee app has a suite of unit and UI tests. Open the Coffee starter project and navigate to CoffeeViewModelTests.swift
. The CoffeeViewModel
saves new coffees and updates existing coffees. The tests make sure your coffee is always saved properly. Run the test case using the diamond to the left of the test case name.
The tests in the test case run in the simulator. Once complete, the empty diamonds change to green check marks.
Next, navigate to CoffeeUITests.swift
. The CoffeeUITests
contains one UI test to confirm the Add Coffee button works. Run the test using the diamond to the left of the test name.
The test runs in the simulator, and the empty diamond changes to a green check mark.
Next, you’ll set up a workflow to run these tests. Navigate to the Report Navigator.
In the previous section, you set up a default workflow that built the project. You can now edit it to run tests instead. Right-click Default and select Edit Workflow.
The Edit Workflow window is where you’ll find all the options to configure a workflow.
Edit Workflow contains a variety of configuration options:
- General configures high-level options such as the workflow name and description.
- Environment configures the Xcode and macOS versions for the build machine. You can also set environment variables for custom build scripts or test actions.
- Start Conditions defines the conditions that trigger the workflow. You can trigger the workflow when code changes on a git branch, or when you create a Pull Request or Tag in GitHub. You can also trigger workflows on a specific schedule.
- Actions defines the workflow steps, such as Build, Test, Analyze or Run.
- Post-Actions defines any steps after the workflow completes. Workflows can deploy your app to TestFlight or notify via Slack or email on success or failure.
As you can see, Edit Workflow contains a lot of configuration options. For your unit and UI test workflow, you’ll focus on General and Actions. Navigate to General, and change the Name to Test
.
The workflow currently has an archive action in the Actions section. The test workflow only runs tests, so you can delete the archive action. Navigate to Archive – iOS and delete the action using the trash icon in the top right.
Next, add a test action using the + next to the Actions section title.
Select Test to add a test action.
The test action allows you to configure various options:
- Platform defines which platform the tests run on. You can create a separate test action for each platform you want to test.
- Scheme defines the scheme to use for the tests.
- Requirement configures whether the tests need to pass or not. You want this workflow to fail if any tests fail, so Required To Pass is the right option.
The last section configures which devices the tests run on. Click the + to add iPads to your workflow.
Last, click Save to finish creating your test workflow.
Great job! You configured a workflow to run any time you change code on the main branch. Now no one can forget to run the tests, since Xcode Cloud will always run them for you :]
Testing the Test Workflow
In this section, you’ll put your new test workflow to the test. First, you’ll manually run the workflow. Then, you’ll update a test and watch Xcode Cloud start the workflow automatically.
Navigate to the Report Navigator and select the Cloud tab. Right-click main, and select Start Build to start the Test workflow on the main branch.
Select Start if Xcode asks you to confirm.
Xcode switches your view to the build overview. The overview shows the status of your build, including details and progress.
The build runs on Apple’s build machines and runs the tests on various iPhone and iPad devices. This might take a few minutes. Grab a coffee or tea while you wait for the build to finish. :]
After Xcode Cloud finishes your test build, Xcode updates to show a green check mark because all the tests passed! Next, you’ll add a unit and UI test to make sure saving a coffee with an empty name shows an error.
Open the CoffeeViewModelTests.swift
file. At the end of CoffeeViewModelTests
, add the following unit test:
func testSaveCoffeeWithEmptyName() async throws {
// 1
var coffeeToSave = CoffeeViewModel.newCoffee
coffeeToSave.name = ""
do {
// 2
try await model.saveCoffee(coffeeToSave)
XCTFail("Coffee with no name should throw empty name error")
} catch CoffeeViewModel.CoffeeError.emptyName {
// 3
XCTAssert(model.showCoffeeErrorAlert)
XCTAssertEqual(model.saveCoffeeError, .emptyName)
} catch {
// 4
XCTFail("Coffee with no name should throw empty name error")
}
}
Here’s how the test works:
- You create a coffee to save using the default
CoffeeViewModel.newCoffee
.newCoffee
is configured using default values when saving a new coffee. Next, you change thename
to an empty string. - You try to save the coffee with the empty name. The
saveCoffee(_:)
method isasync
andthrows
errors. So, you have to addtry await
before saving. - You catch the specific
CoffeeViewModel.CoffeeError.emptyName
error fromsaveCoffee(_:)
. You also check that the view model’sshowCoffeeErrorAlert
istrue
. This means the view model is currently showing an error alert, and thesaveCoffeeError
value is.emptyName
. - The test fails for any other errors besides the
emptyName
error.
Open CoffeeUITests.swift
and add this new UI test at the end of CoffeeUITests
:
func testAddCoffeeWithNoNameShowsAlert() {
// 1
CoffeesScreen()
.tapAddCoffeeButton()
// 2
CoffeeScreen()
.tapSaveCoffee()
.tapCloseSaveCoffeeErrorAlertButton()
}
Here’s how the UI test works:
- On the Coffees screen, the test taps the + button to add a new coffee.
- On the Coffee Editor screen, the test taps the Save button to save the coffee. The default name is empty, so the coffee is saved without a name. Next, the test tries to close the Save Coffee error alert.
CoffeesScreen
and CoffeeScreen
encapsulate the actions to perform the UI test. Browse CoffeesScreen.swift
and CoffeeScreen.swift
for a look at how they work.
Next, you’ll commit and push your new code to the main branch and watch Xcode Cloud run the tests. Open Terminal and navigate to the Coffee starter project folder. Run the following commands to commit and push your changes:
git commit -am "Adding a new unit and UI test"
git push -u origin main
Open the Coffee project and navigate to the Report Navigator. Select the Cloud tab.
Xcode Cloud automatically ran the Test workflow after you changed code on the main
branch. Now, you can move on to the next section while Xcode Cloud runs your tests. :]