BookaMac Engineering-Notizen

Reproduzierbare iOS-Standorttests auf einem Cloud-Mac aufbauen

Reproduzierbare iOS-Standorttests auf einem Cloud-Mac aufbauen

Funktionen wie die Auswahl einer Lieferadresse, die Prüfung des Einzugsgebiets einer Filiale oder Geofencing-Benachrichtigungen lassen sich auf einem Entwicklungsrechner oft mit wenigen Klicks erfolgreich testen, schlagen in unbeaufsichtigten Pipelines jedoch sporadisch fehl. Die Ursache liegt meist nicht im Ortungsalgorithmus. Vielmehr hat der Simulator Koordinaten oder Berechtigungen aus einem vorherigen Durchlauf übernommen, oder eine Route läuft noch. Damit Standorttests auf einem Cloud-Mac reproduzierbar sind, muss der Standort als Testeingabe behandelt werden, die explizit erzeugt und wieder entfernt wird – nicht als bloße Umgebungsbedingung des Simulators.

Drei Validierungsebenen voneinander trennen

Ein einzelner UI-Test sollte nicht gleichzeitig Koordinatenberechnungen, die Anbindung an die Systemortung und UI-Assertions abdecken. Stabiler ist eine Aufteilung in drei Ebenen:

  1. Entfernungen, Regionen und Zustandsübergänge mit normalen Unit-Tests prüfen und dafür konstruierte Koordinaten direkt übergeben.
  2. Mit wenigen Simulatortests sicherstellen, dass die Standortdaten des Systems tatsächlich in die App gelangen und die erwartete Ansicht auslösen.
  3. Auf realen Geräten das Aufwecken im Hintergrund, Signalschwankungen, den Energieverbrauch und sensorabhängiges Verhalten abnehmen.

Für die Geschäftslogik empfiehlt sich zunächst eine möglichst schmale Eingabeschnittstelle. Der Standortdienst kann beispielsweise ausschließlich Koordinaten, Zeit und Autorisierungsstatus liefern. Die Geofencing-Logik sollte nicht direkt über View-Controller verteilt sein. So lassen sich die meisten Grenzfälle ohne gestarteten Simulator prüfen; nur die Systemintegration hängt von simctl location ab.

Simulierte Koordinaten zeigen, wie die App einen bestimmten Standort verarbeitet. Sie belegen nicht, dass eine reale Funkumgebung Standortereignisse im gleichen Rhythmus liefert.

Für jeden Job einen eigenen Simulator bereitstellen

Zuerst wird der Xcode-Pfad festgelegt. Anschließend sollten die auf dem aktuellen Rechner tatsächlich installierten Gerätetypen und Runtimes aufgelistet werden. Die Runtime-Kennung aus einem Beispiel darf nicht dauerhaft fest codiert werden, da sie sich nach einem Xcode-Upgrade ändern kann.

sudo xcode-select -s /Applications/Xcode.app
xcrun simctl list devicetypes
xcrun simctl list runtimes

Die Pipeline sollte einen eigenen CoreSimulator-Gerätesatz erstellen und die erzeugte UDID für den aktuellen Job speichern. Gerätetyp und Runtime-Kennung im folgenden Beispiel müssen durch die tatsächlich vom vorherigen Befehl ausgegebenen Werte ersetzt werden.

set -euo pipefail

DEVICE_SET="$PWD/.simulator-location-tests"
DEVICE_TYPE="com.apple.CoreSimulator.SimDeviceType.iPhone-16"
RUNTIME="com.apple.CoreSimulator.SimRuntime.iOS-18-0"

rm -rf "$DEVICE_SET"
UDID="$(xcrun simctl --set "$DEVICE_SET" create GeoTest "$DEVICE_TYPE" "$RUNTIME")"
xcrun simctl --set "$DEVICE_SET" boot "$UDID"
xcrun simctl --set "$DEVICE_SET" bootstatus "$UDID" -b

Ein eigener Gerätesatz erleichtert die Fehlersuche gegenüber dem wiederholten Löschen eines gemeinsam genutzten Simulators. Das Geräteverzeichnis eines fehlgeschlagenen Jobs kann vorübergehend erhalten bleiben, während es nach einem erfolgreichen Job direkt gelöscht wird. Parallele Jobs konkurrieren außerdem nicht um dasselbe bereits gestartete Gerät.

Feste Koordinaten und Berechtigungen injizieren

Feste Koordinaten eignen sich für deterministische Bedingungen wie „innerhalb der Region“, „Grenze überschritten“ oder „weit vom Zielpunkt entfernt“. Zuerst sollte die App installiert, dann die Berechtigung vorbereitet und der Standort gesetzt werden. Erst danach wird das Testziel gestartet. Wird die Berechtigung erst nach dem App-Start geändert, kann die erste Ansicht bereits den nicht autorisierten Zustand gespeichert haben.

BUNDLE_ID="com.example.LocationDemo"

xcrun simctl --set "$DEVICE_SET" privacy "$UDID" grant location "$BUNDLE_ID"
xcrun simctl --set "$DEVICE_SET" location "$UDID" set 1.290270,103.851959

xcodebuild test \
  -workspace LocationDemo.xcworkspace \
  -scheme LocationDemo \
  -destination "platform=iOS Simulator,id=$UDID" \
  -resultBundlePath "$PWD/TestResults/LocationTests.xcresult"

Für Grenztests reicht ein einzelner Punkt nicht aus. Es sollten mindestens drei Koordinatengruppen für Standorte innerhalb der Region, nahe der Grenze und außerhalb der Region vorhanden sein. Die Testdaten sollten das erwartete Ergebnis benennen, statt die Bedeutung hinter Namen wie case1 oder case2 zu verbergen.

Szenario Gestaltung der Eingabe Empfohlene Assertion
Innerhalb der Region Entfernung zum Mittelpunkt deutlich kleiner als der Schwellenwert Zustand bleibt stabil auf „innerhalb der Region“
Nahe der Grenze Je einen Punkt auf beiden Seiten des Schwellenwerts platzieren Vergleichs- und Rundungsregeln sind konsistent
Außerhalb der Region Entfernung zum Mittelpunkt deutlich größer als der Schwellenwert Keine Aktion für „innerhalb der Region“ auslösen
Berechtigung deaktiviert Standortberechtigung widerrufen Einen behebbaren Hinweiszustand anzeigen

Falls die App den zuletzt bekannten Standort zwischenspeichert, müssen vor jedem Testfall die App-Daten gelöscht oder persistente Caches über Test-Startparameter deaktiviert werden. Andernfalls kann der alte Wert die neuen Koordinaten überschreiben.

Bewegungsabläufe mit GPX prüfen

Für kontinuierliche Bewegungen sollten kurze, gut lesbare GPX-Dateien verwendet werden. Eine Route sollte nur die Wegpunkte enthalten, die entscheidende Zustandsänderungen auslösen, statt einen vollständigen realen Streckenverlauf zu kopieren. Die folgende Datei bewegt sich von außerhalb der Region in die Region hinein:

<?xml version="1.0" encoding="UTF-8"?>
<gpx version="1.1" creator="location-ci">
  <wpt lat="1.320000" lon="103.820000">
    <name>outside</name>
  </wpt>
  <wpt lat="1.290270" lon="103.851959">
    <name>inside</name>
  </wpt>
</gpx>

Beim Ausführen der Route sollten sich Assertions auf die Ereignisreihenfolge beziehen und nicht von sekundengenauen Wartezeiten abhängen.

xcrun simctl --set "$DEVICE_SET" location "$UDID" start "$PWD/Fixtures/enter-region.gpx"
xcodebuild test \
  -workspace LocationDemo.xcworkspace \
  -scheme LocationRouteTests \
  -destination "platform=iOS Simulator,id=$UDID"
xcrun simctl --set "$DEVICE_SET" location "$UDID" stop

Die App kann eine datenschutzgerecht reduzierte Zustandsfolge wie outside → approaching → inside protokollieren und jede Änderung mit einer monoton steigenden Zeitangabe versehen. Vollständige Koordinaten gehören nicht in dauerhaft gespeicherte Protokolle. Als Fehlernachweis genügen der Name des Testfalls, die erwartete Region, der tatsächliche Zustand und eine begrenzte Anzahl von Dezimalstellen.

Zustand bereinigen und Fehlernachweise sichern

Die Bereinigung darf nicht nur im Erfolgsfall ausgeführt werden. Direkt nach dem Start des Skripts sollte ein Exit-Handler registriert werden, der die Route stoppt, den gesetzten Standort löscht und das Gerät herunterfährt. Ob der Gerätesatz gelöscht wird, hängt vom Testergebnis ab.

cleanup() {
  xcrun simctl --set "$DEVICE_SET" location "$UDID" stop 2>/dev/null || true
  xcrun simctl --set "$DEVICE_SET" location "$UDID" clear 2>/dev/null || true
  xcrun simctl --set "$DEVICE_SET" shutdown "$UDID" 2>/dev/null || true
}
trap cleanup EXIT

Bei einem Fehler sollten xcresult, App-Protokolle, die verwendete GPX-Datei, Geräte- und Runtime-Kennungen sowie der Berechtigungsstatus vor Testbeginn archiviert werden. Screenshots können die Analyse unterstützen, ersetzen aber keine strukturierten Assertions. Wenn dieselben Koordinaten wiederholt zu einem Fehler führen, sollte zunächst geprüft werden, ob der Gerätesatz tatsächlich isoliert ist, die Bundle-ID stimmt und die Berechtigung vor dem App-Start erteilt wurde. Erst danach ist die Geschäftslogik zu untersuchen.

Eine stabile Standort-Pipeline sollte letztlich folgende Eigenschaften bieten: lesbare Testeingaben, einmalig verwendete Simulatorzustände, zuverlässig gestoppte Routen und Geschäftslogik, die sich unabhängig von der Systemortung mit Unit-Tests prüfen lässt. Bei einem Fehler sieht das Team dann eine klar beschriebene Zustandsabweichung statt der nicht reproduzierbaren Aussage, die Ortung sei „manchmal ungenau“.

Häufig gestellte Fragen

Ersetzt eine simctl-Standortsimulation Tests auf echten Geräten?

Nein. Sie eignet sich für Zustandswechsel, Benutzeroberfläche und Geschäftsregeln. Hintergrundaktivierung, reale Signalschwankungen, Energieverbrauch und Sensorverhalten müssen auf Geräten geprüft werden.

Warum scheitert ein Standorttest nur innerhalb der vollständigen CI-Pipeline?

Meist bleiben Koordinaten, Berechtigungen oder eine GPX-Route in einem gemeinsam genutzten Simulator zurück. Ein eigener Gerätesatz pro Auftrag und eine explizite Bereinigung verhindern das.

Wann sind feste Koordinaten und wann GPX-Routen sinnvoll?

Feste Koordinaten prüfen Regionen und Grenzfälle deterministisch. GPX-Routen prüfen Bewegungsfolgen und Zustandsübergänge, sollten aber keine sekundengenaue Ankunft voraussetzen.

Dedizierter physischer Mac mini

Bewährte Workflows auf einen dauerhaft verfügbaren Cloud-Mac verlagern

Wählen Sie je nach Einsatz BookaMac M4 oder BookaMac M4 Pro und prüfen Sie bei der Bestellung Region, Laufzeit und optionale Speichererweiterungen.

Mietoption auswählen