diff --git a/Misc/NEWS.d/next/Tests/2025-02-20-13-50-07.gh-issue-130292.RvK2Ou.rst b/Misc/NEWS.d/next/Tests/2025-02-20-13-50-07.gh-issue-130292.RvK2Ou.rst new file mode 100644 index 00000000000000..0805058544abac --- /dev/null +++ b/Misc/NEWS.d/next/Tests/2025-02-20-13-50-07.gh-issue-130292.RvK2Ou.rst @@ -0,0 +1,2 @@ +The iOS testbed will now run successfully on a machine that has not +previously run Xcode tests (such as CI configurations). diff --git a/iOS/testbed/__main__.py b/iOS/testbed/__main__.py index 08fbe90a1c6aef..d12a5ab065b517 100644 --- a/iOS/testbed/__main__.py +++ b/iOS/testbed/__main__.py @@ -82,19 +82,29 @@ async def async_check_output(*args, **kwargs): # Return a list of UDIDs associated with booted simulators async def list_devices(): - # List the testing simulators, in JSON format - raw_json = await async_check_output( - "xcrun", "simctl", "--set", "testing", "list", "-j" - ) - json_data = json.loads(raw_json) - - # Filter out the booted iOS simulators - return [ - simulator["udid"] - for runtime, simulators in json_data["devices"].items() - for simulator in simulators - if runtime.split(".")[-1].startswith("iOS") and simulator["state"] == "Booted" - ] + try: + # List the testing simulators, in JSON format + raw_json = await async_check_output( + "xcrun", "simctl", "--set", "testing", "list", "-j" + ) + json_data = json.loads(raw_json) + + # Filter out the booted iOS simulators + return [ + simulator["udid"] + for runtime, simulators in json_data["devices"].items() + for simulator in simulators + if runtime.split(".")[-1].startswith("iOS") and simulator["state"] == "Booted" + ] + except subprocess.CalledProcessError as e: + # If there's no ~/Library/Developer/XCTestDevices folder (which is the + # case on fresh installs, and in some CI environments), `simctl list` + # returns error code 1, rather than an empty list. Handle that case, + # but raise all other errors. + if e.returncode == 1: + return [] + else: + raise async def find_device(initial_devices):