Skip to main content

iOS - Unit Testing

Module unit tests should live inside the Swift package for the module. The Q2DevApp should only include the minimum project wiring needed to discover and run that Swift package test target through the shared DevApp scheme.

This keeps module test code close to the module source and avoids adding each test file directly to the Q2DevApp Xcode project.

Add a Tests folder inside the module package folder, next to Sources.

q2-example-ios
├── Package.swift
├── q2-example-ios
│ ├── Sources
│ │ └── Q2Example
│ └── Tests
│ └── Q2ExampleTests
│ └── Q2ExampleTests.swift
└── Q2DevApp
├── Q2DevApp.xcworkspace
└── Q2DevApp.xctestplan

Add the Swift Package Test Target

Add a .testTarget entry in the module Package.swift file. Set the test target path to the module package test folder.

.testTarget(
name: "Q2ExampleTests",
dependencies: [
.target(name: "Q2Example")
],
path: "q2-example-ios/Tests/Q2ExampleTests"
)

Use a test target name that clearly maps to the module, for example Q2ExampleTests.

Make the Package Available to Q2DevApp

The Q2DevApp workspace must reference the package root so Xcode can discover the Swift package test target. From Q2DevApp/Q2DevApp.xcworkspace, the package root is the parent folder, so the workspace entry should point to group:...

<FileRef
location = "group:..">
</FileRef>

Do not point the workspace at the nested source folder. Xcode needs the folder that contains Package.swift.

Add the Test Target to the Q2DevApp Test Plan

Create or update Q2DevApp/Q2DevApp.xctestplan so it references the Swift package test target.

{
"configurations": [
{
"id": "Default Configuration",
"name": "Default Configuration",
"options": {}
}
],
"defaultOptions": {},
"testTargets": [
{
"target": {
"containerPath": "container:..",
"identifier": "Q2ExampleTests",
"name": "Q2ExampleTests"
}
}
],
"version": 1
}

The shared Q2DevApp scheme should use this test plan. After that, running tests for the Q2DevApp scheme also runs the module Swift package test target.

Run Tests Locally

Run the Q2DevApp scheme from Xcode or use xcodebuild from the module repository root.

xcodebuild test \
-workspace Q2DevApp/Q2DevApp.xcworkspace \
-scheme Q2DevApp \
-destination 'platform=iOS Simulator,name=iPhone 16' \
CODE_SIGNING_ALLOWED=NO

To collect local code coverage, enable code coverage for the same test run.

xcodebuild test \
-workspace Q2DevApp/Q2DevApp.xcworkspace \
-scheme Q2DevApp \
-destination 'platform=iOS Simulator,name=iPhone 16' \
-enableCodeCoverage YES \
CODE_SIGNING_ALLOWED=NO

Until CI coverage is available for module repositories, include the local test command and result summary in the merge request so reviewers can verify that the module tests ran through Q2DevApp.