Getting Started with Xcode Cloud

Learn how to use Xcode Cloud to test and deploy your app on TestFlight. By Josh Berlin.

5 (2) · 1 Review

Download materials
Save for later
Share
You are currently viewing page 2 of 3 of this article. Click here to view the first page.

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.

Xcode Cloud automated tests workflow

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.

Xcode run unit tests

The tests in the test case run in the simulator. Once complete, the empty diamonds change to green check marks.

Xcode unit tests passed

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.

Xcode run UI tests

The test runs in the simulator, and the empty diamond changes to a green check mark.

Xcode UI tests passed

Next, you’ll set up a workflow to run these tests. Navigate to the Report Navigator.

Xcode navigate to 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.

Xcode Cloud edit workflow

The Edit Workflow window is where you’ll find all the options to configure a workflow.

Xcode Cloud edit workflow overview

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.

Xcode Cloud change name of Test workflow

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.

Xcode Cloud archive action in Test workflow

Next, add a test action using the + next to the Actions section title.

Xcode Cloud test workflow add test action

Select Test to add a test action.

Xcode Cloud test workflow test action added

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.

Xcode Cloud add iPads to test action

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.

Xcode Cloud start Test workflow build

Select Start if Xcode asks you to confirm.

Xcode Cloud start Test workflow build

Note: Check the Don’t ask again checkbox if you’d like future builds to start without confirmation.

Xcode switches your view to the build overview. The overview shows the status of your build, including details and progress.

Xcode Cloud test build overview

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. :]

Xcode Cloud test build succeeded

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:

  1. 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 the name to an empty string.
  2. You try to save the coffee with the empty name. The saveCoffee(_:) method is async and throws errors. So, you have to add try await before saving.
  3. You catch the specific CoffeeViewModel.CoffeeError.emptyName error from saveCoffee(_:). You also check that the view model’s showCoffeeErrorAlert is true. This means the view model is currently showing an error alert, and the saveCoffeeError value is .emptyName.
  4. 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:

  1. On the Coffees screen, the test taps the + button to add a new coffee.
  2. 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.
Note: 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 test build running

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. :]