Guides

Running XCTest on Android

This guide shows how to run XCTest-based Swift Package tests on Android with the SCADE toolchain.

Introduction

XCTest is one of the most established and trusted testing frameworks in the Swift ecosystem. It is familiar to most Swift developers, integrates naturally into everyday development, and provides a solid foundation for writing reliable unit and integration tests.

Swift Package Manager (SPM) includes built-in XCTest support, with convenient test discovery and execution workflows out of the box. In practice, this means teams can organize tests in standard Tests/ targets and run them with minimal setup.

Starting with Swift Android Toolchain 6.2.1-2 and scd 2.16.0, SCADE introduced support for running XCTest on Android in its Swift toolchain and build system.

In this guide, we will show how to create a small Swift Package Manager project with XCTest tests and run them on Android using scd.

Create a New Swift Package

We will start by creating a new Swift Package Manager library project. Run the following command in an empty directory:

swift package init --type library

This creates the standard SPM project structure, including the Sources/ and Tests/ directories that we will use in the next steps.

Add a Small Library API

Next, we will add a very small function that we can test. Replace the contents of Sources/FooPackage/FooPackage.swift with the following code:

public struct MathUtils {
    public init() {}

    public func add(_ lhs: Int, _ rhs: Int) -> Int {
        lhs + rhs
    }
}

This gives us a simple public API that returns the sum of two integers.

Add XCTest Tests

Next, we will update the test file in Tests/FooPackageTests/FooPackageTests.swift and add an XCTest case for the add function:

import XCTest
@testable import FooPackage

final class FooPackageTests: XCTestCase {
    func testAddTwoNumbers() {
        let math = MathUtils()
        XCTAssertEqual(math.add(2, 3), 5)
    }
}

At this point, we have a minimal Swift package with a small library API and an automated test that verifies its behavior.

Run Tests on macOS

Before running the tests on Android, it is useful to verify that the package works correctly in the standard Swift development workflow on macOS.

From the package root, run:

swift test

Swift Package Manager will automatically build the library target, discover the XCTest cases, and run them.

If everything is configured correctly, you should see output showing that the test suite was executed successfully and that the testAddTwoNumbers test passed.

Test Suite 'All tests' started at 2026-04-04 20:07:30.853.
Test Suite 'FooPackagePackageTests.xctest' started at 2026-04-04 20:07:30.854.
Test Suite 'FooPackageTests' started at 2026-04-04 20:07:30.854.
Test Case '-[FooPackageTests.FooPackageTests testAddTwoNumbers]' started.
Test Case '-[FooPackageTests.FooPackageTests testAddTwoNumbers]' passed (0.001 seconds).
Test Suite 'FooPackageTests' passed at 2026-04-04 20:07:30.855.
	 Executed 1 test, with 0 failures (0 unexpected) in 0.001 (0.001) seconds
Test Suite 'FooPackagePackageTests.xctest' passed at 2026-04-04 20:07:30.855.
	 Executed 1 test, with 0 failures (0 unexpected) in 0.001 (0.001) seconds
Test Suite 'All tests' passed at 2026-04-04 20:07:30.855.
	 Executed 1 test, with 0 failures (0 unexpected) in 0.001 (0.002) seconds

Run Tests on Android

Now we can run the same XCTest-based package on Android by using scd, the SCADE Build Tool.

From the package root, run:

scd test --platform android-arm64-v8a

This command automatically builds the package and its tests for the android-arm64-v8a platform, deploys the test application to a connected or already running Android device, and starts the test run.

If you want to select a specific device or Android Virtual Device (AVD), you can use the optional --device argument:

scd test --platform android-arm64-v8a --device <device_or_avd_name>

When --device is provided, scd uses the specified device for the test run. If the given AVD is not currently running, scd will start it automatically before launching the tests.

This makes the Android test flow very close to the standard swift test workflow, while using the SCADE toolchain to build and execute the XCTest bundle on Android.

After starting the command, you will see XCTest output in the terminal, including the test suite name, individual test cases, and the final summary with the number of executed tests and failures.

Performing Streamed Install
Success
Starting tests on device...
Starting: Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] cmp=com.foopackage.foopackage/.MainActivity }
--------- beginning of main
04-04 20:14:32.872 29312 29312 I kage:testrunne: Late-enabling -Xcheck:jni
04-04 20:14:32.886 29312 29312 E kage:testrunne: Unknown bits set in runtime_flags: 0x8000
04-04 20:14:33.371 29312 29312 W linker  : Warning: "/data/app/com.foopackage.foopackage-kILijvpFnd1NG_QbDxAkgw==/base.apk!/lib/arm64-v8a/libc++_shared.so" unused DT entry: unknown processor-specific (type 0x70000001 arg 0x0) (ignoring)
04-04 20:14:33.371 29312 29312 I chatty  : uid=10182 com.foopackage.foopackage:testrunner identical 17 lines
04-04 20:14:33.371 29312 29312 W linker  : Warning: "/data/app/com.foopackage.foopackage-kILijvpFnd1NG_QbDxAkgw==/base.apk!/lib/arm64-v8a/libc++_shared.so" unused DT entry: unknown processor-specific (type 0x70000001 arg 0x0) (ignoring)
04-04 20:14:33.398 29312 29312 I SwiftFoundation: SwiftFoundation.Initialize
04-04 20:14:33.398 29312 29312 I SwiftFoundation: SwiftFoundationInitialize initialize
04-04 20:14:33.401 29312 29312 I SwiftFoundation: create assets directory: swift
04-04 20:14:33.418 29312 29369 D SwiftTestFoundation: XCTMain started
04-04 20:14:33.422 29312 29369 D SwiftTestFoundation: Test Suite 'All tests' started at 2026-04-04 20:14:33.407
04-04 20:14:33.422 29312 29369 D SwiftTestFoundation: Test Suite 'swift.xctest' started at 2026-04-04 20:14:33.422
04-04 20:14:33.422 29312 29369 D SwiftTestFoundation: Test Suite 'FooPackageTests' started at 2026-04-04 20:14:33.422
04-04 20:14:33.422 29312 29369 D SwiftTestFoundation: Test Case 'FooPackageTests.testAddTwoNumbers' started at 2026-04-04 20:14:33.423
04-04 20:14:33.424 29312 29369 D SwiftTestFoundation: Test Case 'FooPackageTests.testAddTwoNumbers' passed (0.002 seconds)
04-04 20:14:33.424 29312 29369 D SwiftTestFoundation: Test Suite 'FooPackageTests' passed at 2026-04-04 20:14:33.425
04-04 20:14:33.424 29312 29369 D SwiftTestFoundation: 	 Executed 1 test, with 0 failures (0 unexpected) in 0.002 (0.002) seconds
04-04 20:14:33.424 29312 29369 D SwiftTestFoundation: Test Suite 'swift.xctest' passed at 2026-04-04 20:14:33.425
04-04 20:14:33.424 29312 29369 D SwiftTestFoundation: 	 Executed 1 test, with 0 failures (0 unexpected) in 0.002 (0.002) seconds
04-04 20:14:33.425 29312 29369 D SwiftTestFoundation: Test Suite 'All tests' passed at 2026-04-04 20:14:33.425
04-04 20:14:33.425 29312 29369 D SwiftTestFoundation: 	 Executed 1 test, with 0 failures (0 unexpected) in 0.002 (0.002) seconds
04-04 20:14:33.425 29312 29369 D SwiftTestFoundation: XCTMain finished
XCTest run finished

Conclusion

In this guide, we created a small Swift Package Manager project, added a simple XCTest case, and verified that it can be executed both with swift test on macOS and with scd test --platform android-arm64-v8a on Android.

With XCTest support now available on Android in the SCADE toolchain, it becomes much easier to reuse familiar Swift testing workflows across platforms. Existing Swift packages that already use XCTest can follow the same general structure and be tested on Android with the same framework and similar developer experience.

This also makes it possible to integrate Android test execution into continuous integration workflows. Teams can run the same XCTest-based test suites automatically on macOS during regular Swift development and on Android as part of cross-platform validation, helping catch platform-specific issues earlier in the development process.

By bringing XCTest to Android, SCADE makes cross-platform Swift development more robust, since the same testing practices used in everyday Swift development can now be applied consistently across platforms.

Running XCTest on Android | Scade.io