Skip to content

Commit 42b0b06

Browse files
authored
gh-133131: Discover an appropriate iOS simulator rather than hard-coding iPhone SE 3rd gen (#133132)
Determines a candidate simulator at runtime rather than hardcoding iPhone SE.
1 parent c46635a commit 42b0b06

File tree

2 files changed

+41
-3
lines changed

2 files changed

+41
-3
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
The iOS testbed will now select the most recently released "SE-class" device
2+
for testing if a device isn't explicitly specified.

iOS/testbed/__main__.py

+39-3
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,36 @@ async def async_check_output(*args, **kwargs):
123123
)
124124

125125

126+
# Select a simulator device to use.
127+
async def select_simulator_device():
128+
# List the testing simulators, in JSON format
129+
raw_json = await async_check_output(
130+
"xcrun", "simctl", "--set", "testing", "list", "-j"
131+
)
132+
json_data = json.loads(raw_json)
133+
134+
# Any device will do; we'll look for "SE" devices - but the name isn't
135+
# consistent over time. Older Xcode versions will use "iPhone SE (Nth
136+
# generation)"; As of 2025, they've started using "iPhone 16e".
137+
#
138+
# When Xcode is updated after a new release, new devices will be available
139+
# and old ones will be dropped from the set available on the latest iOS
140+
# version. Select the one with the highest minimum runtime version - this
141+
# is an indicator of the "newest" released device, which should always be
142+
# supported on the "most recent" iOS version.
143+
se_simulators = sorted(
144+
(devicetype["minRuntimeVersion"], devicetype["name"])
145+
for devicetype in json_data["devicetypes"]
146+
if devicetype["productFamily"] == "iPhone"
147+
and (
148+
("iPhone " in devicetype["name"] and devicetype["name"].endswith("e"))
149+
or "iPhone SE " in devicetype["name"]
150+
)
151+
)
152+
153+
return se_simulators[-1][1]
154+
155+
126156
# Return a list of UDIDs associated with booted simulators
127157
async def list_devices():
128158
try:
@@ -371,12 +401,16 @@ def update_plist(testbed_path, args):
371401
plistlib.dump(info, f)
372402

373403

374-
async def run_testbed(simulator: str, args: list[str], verbose: bool=False):
404+
async def run_testbed(simulator: str | None, args: list[str], verbose: bool=False):
375405
location = Path(__file__).parent
376406
print("Updating plist...", end="", flush=True)
377407
update_plist(location, args)
378408
print(" done.", flush=True)
379409

410+
if simulator is None:
411+
simulator = await select_simulator_device()
412+
print(f"Running test on {simulator}", flush=True)
413+
380414
# We need to get an exclusive lock on simulator creation, to avoid issues
381415
# with multiple simulators starting and being unable to tell which
382416
# simulator is due to which testbed instance. See
@@ -453,8 +487,10 @@ def main():
453487
)
454488
run.add_argument(
455489
"--simulator",
456-
default="iPhone SE (3rd Generation)",
457-
help="The name of the simulator to use (default: 'iPhone SE (3rd Generation)')",
490+
help=(
491+
"The name of the simulator to use (eg: 'iPhone 16e'). Defaults to ",
492+
"the most recently released 'entry level' iPhone device."
493+
)
458494
)
459495
run.add_argument(
460496
"-v", "--verbose",

0 commit comments

Comments
 (0)