Xcode has two template types of testing: Unit Test Targets and UI Test Targets, which run the host application differently. Looking online, I don't see any clear distinction of how these host targets are run differently, just that the unit tests will import a testable bundle to invoke specific classes, while the UI test bundle will create an instance of XCUIApplication at runtime.
Picture from Xcode target creation flow:
If I could find somewhere describing the differences between these targets more technically, then I could start looking at how to change my cmake script to setup each target to match.
CMake has xctest_add_bundle
as part of FindXCTest, which seems to create an Xcode Unit Test Target.
There doesn't appear to be a specific way to create a UI Test Target directly with CMake, but how can I alter a xctest_add_bundle
test bundle in my CMake script such that I can create a UI Test Target that matches Xcode "UI Testing Bundle"?
There are two key things here.
First:
It's not very well documented, but CMake has a target property called XCODE_PRODUCT_TYPE
(see here), but it doesn't say any of the typical values. If you manually open up a project file project.pbxproj
in another IDE (I couldn't find this exposed anywhere in the Xcode GUI), you can find that a UITests target will have productType = com.apple.product-type.bundle.ui-testing
. Setting this is the key part for making the target seen by Xcode as a UI Tests bundle instead of a unit tests bundle.
Second: Another SO post about unit testing pointed me to a retired Apple document which discusses "Application unit tests" instead of "UI tests". So old Xcode refers to both of these types as "unit tests".
CMake's xctest_add_bundle
takes the test target name and testee target name. This automatically adds the "Test Host" and "Bundle Loader" build settings mentioned in those apple docs. So xctest_add_bundle
seems to be actually creating some sort of hybrid of a "UI Testing Bundle" and a unit test bundle.
Pulling that all together, in order to make a proper "UI Testing Bundle" as Xcode would make it, you can do:
# MyApp is your defined app
find_package(XCTest REQUIRED)
xctest_add_bundle(UITests MyApp
Tests/Tests.swift
)
set_target_properties(UITests PROPERTIES
XCODE_ATTRIBUTE_TEST_HOST ""
XCODE_ATTRIBUTE_BUNDLE_LOADER ""
XCODE_ATTRIBUTE_TEST_TARGET_NAME MyApp
XCODE_PRODUCT_TYPE com.apple.product-type.bundle.ui-testing
)
This still gives the UI test target icon in the Xcode targets list and now properly allows the XCUIApplication to run.