zeno-mobile-runner 0.1.8 → 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +72 -0
- package/FEATURES.md +1 -1
- package/README.md +175 -238
- package/clients/kotlin/README.md +1 -1
- package/clients/kotlin/build.gradle.kts +1 -1
- package/clients/python/pyproject.toml +1 -1
- package/clients/rust/Cargo.lock +1 -1
- package/clients/rust/Cargo.toml +1 -1
- package/clients/typescript/package.json +1 -1
- package/docs/agent-discovery.md +10 -0
- package/docs/ai-agents.md +18 -0
- package/docs/benchmarking.md +39 -0
- package/docs/benchmarks/2026-06-09-android-workflow.md +73 -0
- package/docs/benchmarks/2026-06-09-android-workflow.results.jsonl +20 -0
- package/docs/benchmarks/2026-06-09-framework-baseline-status.md +32 -0
- package/docs/benchmarks/2026-06-09-ios-appium-comparison.md +115 -0
- package/docs/benchmarks/2026-06-09-ios-appium-comparison.results.jsonl +40 -0
- package/docs/benchmarks/2026-06-09-ios-demo.md +90 -0
- package/docs/benchmarks/2026-06-09-ios-demo.results.jsonl +20 -0
- package/docs/benchmarks/2026-06-09-ios-maestro-comparison.md +128 -0
- package/docs/benchmarks/2026-06-09-ios-maestro-comparison.results.jsonl +40 -0
- package/docs/benchmarks/2026-06-09-ios-workflow-comparison.md +143 -0
- package/docs/benchmarks/2026-06-09-ios-workflow-comparison.results.jsonl +40 -0
- package/docs/benchmarks/2026-06-09-ios-xctest-floor.md +106 -0
- package/docs/benchmarks/2026-06-09-ios-xctest-floor.results.jsonl +40 -0
- package/docs/benchmarks/README.md +36 -0
- package/docs/benchmarks/benchmark-lab-v1.json +155 -0
- package/docs/benchmarks/benchmark-lab-v1.md +95 -0
- package/docs/clients.md +16 -0
- package/docs/demo.md +36 -1
- package/docs/frameworks.md +10 -0
- package/docs/npm.md +44 -2
- package/docs/protocol-fixtures/core-session.responses.jsonl +1 -1
- package/docs/protocol.md +10 -10
- package/docs/scenario-authoring.md +15 -0
- package/docs/trace-privacy.md +9 -0
- package/docs/troubleshooting.md +6 -0
- package/examples/android-workflow.json +79 -0
- package/examples/ios-dev-client-open-link.json +24 -13
- package/examples/ios-dev-client-route-snapshot.json +33 -8
- package/examples/ios-shim-workflow.json +79 -0
- package/examples/react-native-expo-workflow.json +75 -0
- package/npm/scenarios.mjs +15 -8
- package/npm/wizard.mjs +1 -1
- package/package.json +6 -1
- package/prebuilds/darwin-arm64/zmr +0 -0
- package/prebuilds/darwin-x64/zmr +0 -0
- package/prebuilds/linux-arm64/zmr +0 -0
- package/prebuilds/linux-x64/zmr +0 -0
- package/scripts/benchmark-lab.py +253 -0
- package/scripts/create-android-demo-app.sh +324 -29
- package/scripts/create-ios-demo-app.sh +174 -7
- package/scripts/create-react-native-expo-demo-app.sh +727 -0
- package/scripts/demo.sh +3 -0
- package/scripts/install-ios-shim.sh +2 -2
- package/shims/ios/ZMRShim.swift +10 -0
- package/shims/ios/ZMRShimUITestCase.swift +49 -1
- package/shims/ios/protocol.md +1 -0
- package/src/cli_import.zig +31 -15
- package/src/cli_trace.zig +38 -16
- package/src/cli_validate.zig +12 -6
- package/src/ios.zig +44 -11
- package/src/ios_shim.zig +36 -2
- package/src/main.zig +6 -0
- package/src/version.zig +1 -1
- package/viewer/app.js +23 -3
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
# 2026-06-09 iOS Simulator ZMR vs Maestro Comparison
|
|
2
|
+
|
|
3
|
+
This evidence pack compares ZMR with Maestro on the generated public iOS demo
|
|
4
|
+
app. It is a command-level benchmark: each row starts the runner command,
|
|
5
|
+
executes one smoke flow on the same booted simulator, and records the command
|
|
6
|
+
duration.
|
|
7
|
+
|
|
8
|
+
This is not a universal claim about either project. Treat it as reproducible
|
|
9
|
+
evidence for this app, host, simulator, and flow shape.
|
|
10
|
+
|
|
11
|
+
## Result
|
|
12
|
+
|
|
13
|
+
| Tool | Runs | Pass rate | Failures | Mean duration | p95 duration |
|
|
14
|
+
| --- | ---: | ---: | ---: | ---: | ---: |
|
|
15
|
+
| ZMR | 20 | 100.00% | 0 | 2236 ms | 2282 ms |
|
|
16
|
+
| Maestro | 20 | 95.00% | 1 | 7578 ms | 7918 ms |
|
|
17
|
+
|
|
18
|
+
For this run, ZMR was 3.39x faster on mean duration and 3.47x faster on p95
|
|
19
|
+
duration. Maestro run 8 failed while launching the app with a driver connection
|
|
20
|
+
error: `Failed to connect to /127.0.0.1:7001`.
|
|
21
|
+
|
|
22
|
+
## Environment
|
|
23
|
+
|
|
24
|
+
| Field | Value |
|
|
25
|
+
| --- | --- |
|
|
26
|
+
| ZMR runner | `0.1.8` |
|
|
27
|
+
| ZMR protocol | `2026-04-28` |
|
|
28
|
+
| Maestro | `1.40.3` |
|
|
29
|
+
| Java | OpenJDK 21.0.6 |
|
|
30
|
+
| Host OS | macOS 26.6, arm64 |
|
|
31
|
+
| Xcode | 26.5, build 17F42 |
|
|
32
|
+
| Simulator | Booted iOS 26.5 simulator, `zmr-iPhone` |
|
|
33
|
+
| App id | `com.example.mobiletest` |
|
|
34
|
+
| App build label | `generated-ios-demo-20260609` |
|
|
35
|
+
| Demo app source | Generated by `scripts/create-ios-demo-app.sh` |
|
|
36
|
+
|
|
37
|
+
## ZMR Command
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
ZMR_BIN="$PWD/zig-out/bin/zmr" scripts/benchmark.sh \
|
|
41
|
+
--zmr examples/ios-smoke.json \
|
|
42
|
+
--platform ios \
|
|
43
|
+
--ios-device-type simulator \
|
|
44
|
+
--device booted \
|
|
45
|
+
--app-id com.example.mobiletest \
|
|
46
|
+
--xcrun xcrun \
|
|
47
|
+
--app-build generated-ios-demo-20260609 \
|
|
48
|
+
--runs 20 \
|
|
49
|
+
--trace-root traces/public-benchmarks/20260609-ios-maestro-comparison/zmr \
|
|
50
|
+
--results traces/public-benchmarks/20260609-ios-maestro-comparison/results.jsonl \
|
|
51
|
+
--replace \
|
|
52
|
+
--min-pass-rate 100 \
|
|
53
|
+
--max-failures 0
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
The ZMR scenario launches the app, opens `exampleapp:///e2e-auth?probe=1`, and
|
|
57
|
+
captures a snapshot:
|
|
58
|
+
|
|
59
|
+
```json
|
|
60
|
+
{
|
|
61
|
+
"name": "ZMR iOS simulator smoke demo",
|
|
62
|
+
"appId": "com.example.mobiletest",
|
|
63
|
+
"steps": [
|
|
64
|
+
{ "action": "launch" },
|
|
65
|
+
{ "action": "openLink", "url": "exampleapp:///e2e-auth?probe=1" },
|
|
66
|
+
{ "action": "snapshot" }
|
|
67
|
+
]
|
|
68
|
+
}
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
## Maestro Command
|
|
72
|
+
|
|
73
|
+
```bash
|
|
74
|
+
scripts/benchmark-command.sh \
|
|
75
|
+
--tool maestro \
|
|
76
|
+
--platform ios \
|
|
77
|
+
--device booted \
|
|
78
|
+
--app-id com.example.mobiletest \
|
|
79
|
+
--scenario examples/ios-smoke.json \
|
|
80
|
+
--app-build generated-ios-demo-20260609 \
|
|
81
|
+
--runs 20 \
|
|
82
|
+
--trace-root traces/public-benchmarks/20260609-ios-maestro-comparison/maestro \
|
|
83
|
+
--results traces/public-benchmarks/20260609-ios-maestro-comparison/results.jsonl \
|
|
84
|
+
--min-pass-rate 100 \
|
|
85
|
+
--max-failures 0 \
|
|
86
|
+
-- maestro --platform ios --device F839B002-5388-4814-B64F-DBE5A113EBED test --no-ansi /tmp/zmr-maestro-benchmark-20260609/ios-smoke.yaml
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
The Maestro flow launches the same app, opens the same deep link, and asserts
|
|
90
|
+
the resulting status text:
|
|
91
|
+
|
|
92
|
+
```yaml
|
|
93
|
+
appId: com.example.mobiletest
|
|
94
|
+
---
|
|
95
|
+
- launchApp
|
|
96
|
+
- openLink: exampleapp:///e2e-auth?probe=1
|
|
97
|
+
- assertVisible: Deep link opened
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
## Comparison Report
|
|
101
|
+
|
|
102
|
+
```text
|
|
103
|
+
# Benchmark Comparison
|
|
104
|
+
|
|
105
|
+
| Tool | Runs | Pass rate | Failures | Mean ms | P95 ms |
|
|
106
|
+
| --- | ---: | ---: | ---: | ---: | ---: |
|
|
107
|
+
| zmr | 20 | 100.00% | 0 | 2236 | 2282 |
|
|
108
|
+
| maestro | 20 | 95.00% | 1 | 7578 | 7918 |
|
|
109
|
+
|
|
110
|
+
- Mean speedup: 3.39x (-70.5% candidate vs baseline)
|
|
111
|
+
- P95 speedup: 3.47x (-71.2% candidate vs baseline)
|
|
112
|
+
- Same benchmark context: yes
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
The sanitized result rows are committed in
|
|
116
|
+
[2026-06-09-ios-maestro-comparison.results.jsonl](2026-06-09-ios-maestro-comparison.results.jsonl).
|
|
117
|
+
|
|
118
|
+
Raw local trace and runner logs are not committed because they can include local
|
|
119
|
+
absolute paths. The failure detail above was taken from the failed Maestro
|
|
120
|
+
run's local stdout log.
|
|
121
|
+
|
|
122
|
+
## Scope
|
|
123
|
+
|
|
124
|
+
This benchmark compares the local command surfaces under repeated execution. It
|
|
125
|
+
does not compare cloud execution, long multi-screen flows, Detox, XCTest-only
|
|
126
|
+
flows, or app-specific selectors. Detox requires a project-specific native test
|
|
127
|
+
harness, so it should get its own evidence pack rather than being forced into
|
|
128
|
+
this demo comparison.
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
{"tool":"zmr","run":1,"status":"ok","durationMs":2347,"traceDir":"traces/public-benchmarks/20260609-ios-maestro-comparison/zmr/zmr-1","platform":"ios","device":"booted","appId":"com.example.mobiletest","scenario":"examples/ios-smoke.json","appBuild":"generated-ios-demo-20260609","traceStatus":"passed"}
|
|
2
|
+
{"tool":"zmr","run":2,"status":"ok","durationMs":2233,"traceDir":"traces/public-benchmarks/20260609-ios-maestro-comparison/zmr/zmr-2","platform":"ios","device":"booted","appId":"com.example.mobiletest","scenario":"examples/ios-smoke.json","appBuild":"generated-ios-demo-20260609","traceStatus":"passed"}
|
|
3
|
+
{"tool":"zmr","run":3,"status":"ok","durationMs":2282,"traceDir":"traces/public-benchmarks/20260609-ios-maestro-comparison/zmr/zmr-3","platform":"ios","device":"booted","appId":"com.example.mobiletest","scenario":"examples/ios-smoke.json","appBuild":"generated-ios-demo-20260609","traceStatus":"passed"}
|
|
4
|
+
{"tool":"zmr","run":4,"status":"ok","durationMs":2204,"traceDir":"traces/public-benchmarks/20260609-ios-maestro-comparison/zmr/zmr-4","platform":"ios","device":"booted","appId":"com.example.mobiletest","scenario":"examples/ios-smoke.json","appBuild":"generated-ios-demo-20260609","traceStatus":"passed"}
|
|
5
|
+
{"tool":"zmr","run":5,"status":"ok","durationMs":2231,"traceDir":"traces/public-benchmarks/20260609-ios-maestro-comparison/zmr/zmr-5","platform":"ios","device":"booted","appId":"com.example.mobiletest","scenario":"examples/ios-smoke.json","appBuild":"generated-ios-demo-20260609","traceStatus":"passed"}
|
|
6
|
+
{"tool":"zmr","run":6,"status":"ok","durationMs":2185,"traceDir":"traces/public-benchmarks/20260609-ios-maestro-comparison/zmr/zmr-6","platform":"ios","device":"booted","appId":"com.example.mobiletest","scenario":"examples/ios-smoke.json","appBuild":"generated-ios-demo-20260609","traceStatus":"passed"}
|
|
7
|
+
{"tool":"zmr","run":7,"status":"ok","durationMs":2208,"traceDir":"traces/public-benchmarks/20260609-ios-maestro-comparison/zmr/zmr-7","platform":"ios","device":"booted","appId":"com.example.mobiletest","scenario":"examples/ios-smoke.json","appBuild":"generated-ios-demo-20260609","traceStatus":"passed"}
|
|
8
|
+
{"tool":"zmr","run":8,"status":"ok","durationMs":2196,"traceDir":"traces/public-benchmarks/20260609-ios-maestro-comparison/zmr/zmr-8","platform":"ios","device":"booted","appId":"com.example.mobiletest","scenario":"examples/ios-smoke.json","appBuild":"generated-ios-demo-20260609","traceStatus":"passed"}
|
|
9
|
+
{"tool":"zmr","run":9,"status":"ok","durationMs":2189,"traceDir":"traces/public-benchmarks/20260609-ios-maestro-comparison/zmr/zmr-9","platform":"ios","device":"booted","appId":"com.example.mobiletest","scenario":"examples/ios-smoke.json","appBuild":"generated-ios-demo-20260609","traceStatus":"passed"}
|
|
10
|
+
{"tool":"zmr","run":10,"status":"ok","durationMs":2211,"traceDir":"traces/public-benchmarks/20260609-ios-maestro-comparison/zmr/zmr-10","platform":"ios","device":"booted","appId":"com.example.mobiletest","scenario":"examples/ios-smoke.json","appBuild":"generated-ios-demo-20260609","traceStatus":"passed"}
|
|
11
|
+
{"tool":"zmr","run":11,"status":"ok","durationMs":2268,"traceDir":"traces/public-benchmarks/20260609-ios-maestro-comparison/zmr/zmr-11","platform":"ios","device":"booted","appId":"com.example.mobiletest","scenario":"examples/ios-smoke.json","appBuild":"generated-ios-demo-20260609","traceStatus":"passed"}
|
|
12
|
+
{"tool":"zmr","run":12,"status":"ok","durationMs":2245,"traceDir":"traces/public-benchmarks/20260609-ios-maestro-comparison/zmr/zmr-12","platform":"ios","device":"booted","appId":"com.example.mobiletest","scenario":"examples/ios-smoke.json","appBuild":"generated-ios-demo-20260609","traceStatus":"passed"}
|
|
13
|
+
{"tool":"zmr","run":13,"status":"ok","durationMs":2244,"traceDir":"traces/public-benchmarks/20260609-ios-maestro-comparison/zmr/zmr-13","platform":"ios","device":"booted","appId":"com.example.mobiletest","scenario":"examples/ios-smoke.json","appBuild":"generated-ios-demo-20260609","traceStatus":"passed"}
|
|
14
|
+
{"tool":"zmr","run":14,"status":"ok","durationMs":2249,"traceDir":"traces/public-benchmarks/20260609-ios-maestro-comparison/zmr/zmr-14","platform":"ios","device":"booted","appId":"com.example.mobiletest","scenario":"examples/ios-smoke.json","appBuild":"generated-ios-demo-20260609","traceStatus":"passed"}
|
|
15
|
+
{"tool":"zmr","run":15,"status":"ok","durationMs":2224,"traceDir":"traces/public-benchmarks/20260609-ios-maestro-comparison/zmr/zmr-15","platform":"ios","device":"booted","appId":"com.example.mobiletest","scenario":"examples/ios-smoke.json","appBuild":"generated-ios-demo-20260609","traceStatus":"passed"}
|
|
16
|
+
{"tool":"zmr","run":16,"status":"ok","durationMs":2236,"traceDir":"traces/public-benchmarks/20260609-ios-maestro-comparison/zmr/zmr-16","platform":"ios","device":"booted","appId":"com.example.mobiletest","scenario":"examples/ios-smoke.json","appBuild":"generated-ios-demo-20260609","traceStatus":"passed"}
|
|
17
|
+
{"tool":"zmr","run":17,"status":"ok","durationMs":2236,"traceDir":"traces/public-benchmarks/20260609-ios-maestro-comparison/zmr/zmr-17","platform":"ios","device":"booted","appId":"com.example.mobiletest","scenario":"examples/ios-smoke.json","appBuild":"generated-ios-demo-20260609","traceStatus":"passed"}
|
|
18
|
+
{"tool":"zmr","run":18,"status":"ok","durationMs":2226,"traceDir":"traces/public-benchmarks/20260609-ios-maestro-comparison/zmr/zmr-18","platform":"ios","device":"booted","appId":"com.example.mobiletest","scenario":"examples/ios-smoke.json","appBuild":"generated-ios-demo-20260609","traceStatus":"passed"}
|
|
19
|
+
{"tool":"zmr","run":19,"status":"ok","durationMs":2262,"traceDir":"traces/public-benchmarks/20260609-ios-maestro-comparison/zmr/zmr-19","platform":"ios","device":"booted","appId":"com.example.mobiletest","scenario":"examples/ios-smoke.json","appBuild":"generated-ios-demo-20260609","traceStatus":"passed"}
|
|
20
|
+
{"tool":"zmr","run":20,"status":"ok","durationMs":2248,"traceDir":"traces/public-benchmarks/20260609-ios-maestro-comparison/zmr/zmr-20","platform":"ios","device":"booted","appId":"com.example.mobiletest","scenario":"examples/ios-smoke.json","appBuild":"generated-ios-demo-20260609","traceStatus":"passed"}
|
|
21
|
+
{"tool":"maestro","run":1,"status":"ok","durationMs":7762,"traceDir":"traces/public-benchmarks/20260609-ios-maestro-comparison/maestro/maestro-1","platform":"ios","device":"booted","appId":"com.example.mobiletest","scenario":"examples/ios-smoke.json","appBuild":"generated-ios-demo-20260609"}
|
|
22
|
+
{"tool":"maestro","run":2,"status":"ok","durationMs":7793,"traceDir":"traces/public-benchmarks/20260609-ios-maestro-comparison/maestro/maestro-2","platform":"ios","device":"booted","appId":"com.example.mobiletest","scenario":"examples/ios-smoke.json","appBuild":"generated-ios-demo-20260609"}
|
|
23
|
+
{"tool":"maestro","run":3,"status":"ok","durationMs":7771,"traceDir":"traces/public-benchmarks/20260609-ios-maestro-comparison/maestro/maestro-3","platform":"ios","device":"booted","appId":"com.example.mobiletest","scenario":"examples/ios-smoke.json","appBuild":"generated-ios-demo-20260609"}
|
|
24
|
+
{"tool":"maestro","run":4,"status":"ok","durationMs":7762,"traceDir":"traces/public-benchmarks/20260609-ios-maestro-comparison/maestro/maestro-4","platform":"ios","device":"booted","appId":"com.example.mobiletest","scenario":"examples/ios-smoke.json","appBuild":"generated-ios-demo-20260609"}
|
|
25
|
+
{"tool":"maestro","run":5,"status":"ok","durationMs":7838,"traceDir":"traces/public-benchmarks/20260609-ios-maestro-comparison/maestro/maestro-5","platform":"ios","device":"booted","appId":"com.example.mobiletest","scenario":"examples/ios-smoke.json","appBuild":"generated-ios-demo-20260609"}
|
|
26
|
+
{"tool":"maestro","run":6,"status":"ok","durationMs":7918,"traceDir":"traces/public-benchmarks/20260609-ios-maestro-comparison/maestro/maestro-6","platform":"ios","device":"booted","appId":"com.example.mobiletest","scenario":"examples/ios-smoke.json","appBuild":"generated-ios-demo-20260609"}
|
|
27
|
+
{"tool":"maestro","run":7,"status":"ok","durationMs":7975,"traceDir":"traces/public-benchmarks/20260609-ios-maestro-comparison/maestro/maestro-7","platform":"ios","device":"booted","appId":"com.example.mobiletest","scenario":"examples/ios-smoke.json","appBuild":"generated-ios-demo-20260609"}
|
|
28
|
+
{"tool":"maestro","run":8,"status":"failed","durationMs":5091,"traceDir":"traces/public-benchmarks/20260609-ios-maestro-comparison/maestro/maestro-8","platform":"ios","device":"booted","appId":"com.example.mobiletest","scenario":"examples/ios-smoke.json","appBuild":"generated-ios-demo-20260609"}
|
|
29
|
+
{"tool":"maestro","run":9,"status":"ok","durationMs":6764,"traceDir":"traces/public-benchmarks/20260609-ios-maestro-comparison/maestro/maestro-9","platform":"ios","device":"booted","appId":"com.example.mobiletest","scenario":"examples/ios-smoke.json","appBuild":"generated-ios-demo-20260609"}
|
|
30
|
+
{"tool":"maestro","run":10,"status":"ok","durationMs":7716,"traceDir":"traces/public-benchmarks/20260609-ios-maestro-comparison/maestro/maestro-10","platform":"ios","device":"booted","appId":"com.example.mobiletest","scenario":"examples/ios-smoke.json","appBuild":"generated-ios-demo-20260609"}
|
|
31
|
+
{"tool":"maestro","run":11,"status":"ok","durationMs":7738,"traceDir":"traces/public-benchmarks/20260609-ios-maestro-comparison/maestro/maestro-11","platform":"ios","device":"booted","appId":"com.example.mobiletest","scenario":"examples/ios-smoke.json","appBuild":"generated-ios-demo-20260609"}
|
|
32
|
+
{"tool":"maestro","run":12,"status":"ok","durationMs":7738,"traceDir":"traces/public-benchmarks/20260609-ios-maestro-comparison/maestro/maestro-12","platform":"ios","device":"booted","appId":"com.example.mobiletest","scenario":"examples/ios-smoke.json","appBuild":"generated-ios-demo-20260609"}
|
|
33
|
+
{"tool":"maestro","run":13,"status":"ok","durationMs":7808,"traceDir":"traces/public-benchmarks/20260609-ios-maestro-comparison/maestro/maestro-13","platform":"ios","device":"booted","appId":"com.example.mobiletest","scenario":"examples/ios-smoke.json","appBuild":"generated-ios-demo-20260609"}
|
|
34
|
+
{"tool":"maestro","run":14,"status":"ok","durationMs":7772,"traceDir":"traces/public-benchmarks/20260609-ios-maestro-comparison/maestro/maestro-14","platform":"ios","device":"booted","appId":"com.example.mobiletest","scenario":"examples/ios-smoke.json","appBuild":"generated-ios-demo-20260609"}
|
|
35
|
+
{"tool":"maestro","run":15,"status":"ok","durationMs":7681,"traceDir":"traces/public-benchmarks/20260609-ios-maestro-comparison/maestro/maestro-15","platform":"ios","device":"booted","appId":"com.example.mobiletest","scenario":"examples/ios-smoke.json","appBuild":"generated-ios-demo-20260609"}
|
|
36
|
+
{"tool":"maestro","run":16,"status":"ok","durationMs":7629,"traceDir":"traces/public-benchmarks/20260609-ios-maestro-comparison/maestro/maestro-16","platform":"ios","device":"booted","appId":"com.example.mobiletest","scenario":"examples/ios-smoke.json","appBuild":"generated-ios-demo-20260609"}
|
|
37
|
+
{"tool":"maestro","run":17,"status":"ok","durationMs":7702,"traceDir":"traces/public-benchmarks/20260609-ios-maestro-comparison/maestro/maestro-17","platform":"ios","device":"booted","appId":"com.example.mobiletest","scenario":"examples/ios-smoke.json","appBuild":"generated-ios-demo-20260609"}
|
|
38
|
+
{"tool":"maestro","run":18,"status":"ok","durationMs":7661,"traceDir":"traces/public-benchmarks/20260609-ios-maestro-comparison/maestro/maestro-18","platform":"ios","device":"booted","appId":"com.example.mobiletest","scenario":"examples/ios-smoke.json","appBuild":"generated-ios-demo-20260609"}
|
|
39
|
+
{"tool":"maestro","run":19,"status":"ok","durationMs":7787,"traceDir":"traces/public-benchmarks/20260609-ios-maestro-comparison/maestro/maestro-19","platform":"ios","device":"booted","appId":"com.example.mobiletest","scenario":"examples/ios-smoke.json","appBuild":"generated-ios-demo-20260609"}
|
|
40
|
+
{"tool":"maestro","run":20,"status":"ok","durationMs":7658,"traceDir":"traces/public-benchmarks/20260609-ios-maestro-comparison/maestro/maestro-20","platform":"ios","device":"booted","appId":"com.example.mobiletest","scenario":"examples/ios-smoke.json","appBuild":"generated-ios-demo-20260609"}
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
# 2026-06-09 iOS Simulator Workflow Comparison
|
|
2
|
+
|
|
3
|
+
This evidence pack compares ZMR with Maestro on the generated public iOS demo
|
|
4
|
+
app using a longer workflow than the smoke benchmark. The flow launches the
|
|
5
|
+
app, fills a profile form, opens a catalog item, saves it, reviews the order,
|
|
6
|
+
and asserts the final state.
|
|
7
|
+
|
|
8
|
+
This is not a universal claim about either project. Treat it as reproducible
|
|
9
|
+
evidence for this app, host, simulator, app build, and workflow shape.
|
|
10
|
+
|
|
11
|
+
## Result
|
|
12
|
+
|
|
13
|
+
| Tool | Runs | Pass rate | Failures | Mean duration | p95 duration |
|
|
14
|
+
| --- | ---: | ---: | ---: | ---: | ---: |
|
|
15
|
+
| ZMR | 20 | 100.00% | 0 | 19539 ms | 22970 ms |
|
|
16
|
+
| Maestro | 20 | 100.00% | 0 | 36240 ms | 47502 ms |
|
|
17
|
+
|
|
18
|
+
For this run, ZMR was 1.85x faster on mean duration and 2.07x faster on p95
|
|
19
|
+
duration.
|
|
20
|
+
|
|
21
|
+
## Environment
|
|
22
|
+
|
|
23
|
+
| Field | Value |
|
|
24
|
+
| --- | --- |
|
|
25
|
+
| ZMR runner | `0.1.8` |
|
|
26
|
+
| ZMR protocol | `2026-04-28` |
|
|
27
|
+
| Maestro | `1.40.3` |
|
|
28
|
+
| Java | OpenJDK 21.0.6 |
|
|
29
|
+
| Host OS | macOS 26.6, arm64 |
|
|
30
|
+
| Xcode | 26.5, build 17F42 |
|
|
31
|
+
| Simulator | Booted iOS 26.5 simulator, `zmr-iPhone` |
|
|
32
|
+
| App id | `com.example.mobiletest` |
|
|
33
|
+
| App build label | `generated-ios-workflow-demo-20260609` |
|
|
34
|
+
| Demo app source | Generated by `scripts/create-ios-demo-app.sh` |
|
|
35
|
+
|
|
36
|
+
## ZMR Command
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
ZMR_BIN="$PWD/zig-out/bin/zmr" scripts/benchmark.sh \
|
|
40
|
+
--zmr examples/ios-shim-workflow.json \
|
|
41
|
+
--platform ios \
|
|
42
|
+
--ios-device-type simulator \
|
|
43
|
+
--device booted \
|
|
44
|
+
--app-id com.example.mobiletest \
|
|
45
|
+
--xcrun xcrun \
|
|
46
|
+
--ios-shim /tmp/zmr-ios-workflow-demo-20260609/.zmr/ios-shim \
|
|
47
|
+
--app-build generated-ios-workflow-demo-20260609 \
|
|
48
|
+
--runs 20 \
|
|
49
|
+
--trace-root traces/public-benchmarks/20260609-ios-workflow-comparison/zmr \
|
|
50
|
+
--results traces/public-benchmarks/20260609-ios-workflow-comparison/results.jsonl \
|
|
51
|
+
--replace \
|
|
52
|
+
--min-pass-rate 100 \
|
|
53
|
+
--max-failures 0
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
The ZMR scenario is committed as
|
|
57
|
+
[`examples/ios-shim-workflow.json`](../../examples/ios-shim-workflow.json).
|
|
58
|
+
|
|
59
|
+
## Maestro Command
|
|
60
|
+
|
|
61
|
+
```bash
|
|
62
|
+
MAESTRO_BIN="$HOME/.maestro/bin/maestro"
|
|
63
|
+
scripts/benchmark-command.sh \
|
|
64
|
+
--tool maestro \
|
|
65
|
+
--platform ios \
|
|
66
|
+
--device booted \
|
|
67
|
+
--app-id com.example.mobiletest \
|
|
68
|
+
--scenario examples/ios-shim-workflow.json \
|
|
69
|
+
--app-build generated-ios-workflow-demo-20260609 \
|
|
70
|
+
--runs 20 \
|
|
71
|
+
--trace-root traces/public-benchmarks/20260609-ios-workflow-comparison/maestro \
|
|
72
|
+
--results traces/public-benchmarks/20260609-ios-workflow-comparison/results.jsonl \
|
|
73
|
+
--min-pass-rate 90 \
|
|
74
|
+
--max-failures 2 \
|
|
75
|
+
-- "$MAESTRO_BIN" \
|
|
76
|
+
--platform ios \
|
|
77
|
+
--device F839B002-5388-4814-B64F-DBE5A113EBED \
|
|
78
|
+
test \
|
|
79
|
+
--no-ansi \
|
|
80
|
+
/tmp/zmr-maestro-workflow-20260609/ios-workflow.yaml
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
The measured Maestro flow used the same visible labels and app state:
|
|
84
|
+
|
|
85
|
+
```yaml
|
|
86
|
+
appId: com.example.mobiletest
|
|
87
|
+
---
|
|
88
|
+
- launchApp
|
|
89
|
+
- assertVisible: ZMR iOS Demo
|
|
90
|
+
- tapOn: Continue
|
|
91
|
+
- assertVisible: Profile
|
|
92
|
+
- tapOn: Name
|
|
93
|
+
- inputText: Riley
|
|
94
|
+
- tapOn: Email
|
|
95
|
+
- inputText: riley@example.test
|
|
96
|
+
- hideKeyboard
|
|
97
|
+
- tapOn: Save profile
|
|
98
|
+
- assertVisible: Catalog
|
|
99
|
+
- tapOn: North Ridge Pack
|
|
100
|
+
- assertVisible: North Ridge Pack
|
|
101
|
+
- tapOn: Save item
|
|
102
|
+
- assertVisible: Saved North Ridge Pack
|
|
103
|
+
- tapOn: Review order
|
|
104
|
+
- assertVisible: Workflow complete
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
## Comparison Report
|
|
108
|
+
|
|
109
|
+
```text
|
|
110
|
+
# Benchmark Comparison
|
|
111
|
+
|
|
112
|
+
| Tool | Runs | Pass rate | Failures | Mean ms | P95 ms |
|
|
113
|
+
| --- | ---: | ---: | ---: | ---: | ---: |
|
|
114
|
+
| zmr | 20 | 100.00% | 0 | 19539 | 22970 |
|
|
115
|
+
| maestro | 20 | 100.00% | 0 | 36240 | 47502 |
|
|
116
|
+
|
|
117
|
+
- Mean speedup: 1.85x (-46.1% candidate vs baseline)
|
|
118
|
+
- P95 speedup: 2.07x (-51.6% candidate vs baseline)
|
|
119
|
+
- Same benchmark context: yes
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
The sanitized result rows are committed in
|
|
123
|
+
[2026-06-09-ios-workflow-comparison.results.jsonl](2026-06-09-ios-workflow-comparison.results.jsonl).
|
|
124
|
+
|
|
125
|
+
Raw local trace and runner logs are not committed because they can include local
|
|
126
|
+
absolute paths.
|
|
127
|
+
|
|
128
|
+
## Other Baselines
|
|
129
|
+
|
|
130
|
+
Appium 3.5.0 with XCUITest driver 11.10.0 was attempted against the same app
|
|
131
|
+
and simulator. The smoke run failed twice while starting WebDriverAgent with
|
|
132
|
+
`connect ECONNREFUSED 127.0.0.1:8100`, so no Appium timing rows are included in
|
|
133
|
+
this evidence pack.
|
|
134
|
+
|
|
135
|
+
Detox needs a project-specific native test harness and app build wiring, so it
|
|
136
|
+
should get its own fixture rather than being forced into this generated SwiftUI
|
|
137
|
+
demo.
|
|
138
|
+
|
|
139
|
+
## Scope
|
|
140
|
+
|
|
141
|
+
This benchmark compares local command surfaces under repeated execution. It
|
|
142
|
+
does not compare cloud execution, Android, Flutter widget-tree automation, or
|
|
143
|
+
framework-specific project harnesses.
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
{"tool":"zmr","run":1,"status":"ok","durationMs":21874,"traceDir":"traces/public-benchmarks/20260609-ios-workflow-comparison/zmr-final/zmr-1","platform":"ios","device":"booted","appId":"com.example.mobiletest","scenario":"examples/ios-shim-workflow.json","appBuild":"generated-ios-workflow-demo-20260609","traceStatus":"passed"}
|
|
2
|
+
{"tool":"zmr","run":2,"status":"ok","durationMs":17173,"traceDir":"traces/public-benchmarks/20260609-ios-workflow-comparison/zmr-final/zmr-2","platform":"ios","device":"booted","appId":"com.example.mobiletest","scenario":"examples/ios-shim-workflow.json","appBuild":"generated-ios-workflow-demo-20260609","traceStatus":"passed"}
|
|
3
|
+
{"tool":"zmr","run":3,"status":"ok","durationMs":16724,"traceDir":"traces/public-benchmarks/20260609-ios-workflow-comparison/zmr-final/zmr-3","platform":"ios","device":"booted","appId":"com.example.mobiletest","scenario":"examples/ios-shim-workflow.json","appBuild":"generated-ios-workflow-demo-20260609","traceStatus":"passed"}
|
|
4
|
+
{"tool":"zmr","run":4,"status":"ok","durationMs":16453,"traceDir":"traces/public-benchmarks/20260609-ios-workflow-comparison/zmr-final/zmr-4","platform":"ios","device":"booted","appId":"com.example.mobiletest","scenario":"examples/ios-shim-workflow.json","appBuild":"generated-ios-workflow-demo-20260609","traceStatus":"passed"}
|
|
5
|
+
{"tool":"zmr","run":5,"status":"ok","durationMs":17385,"traceDir":"traces/public-benchmarks/20260609-ios-workflow-comparison/zmr-final/zmr-5","platform":"ios","device":"booted","appId":"com.example.mobiletest","scenario":"examples/ios-shim-workflow.json","appBuild":"generated-ios-workflow-demo-20260609","traceStatus":"passed"}
|
|
6
|
+
{"tool":"zmr","run":6,"status":"ok","durationMs":23807,"traceDir":"traces/public-benchmarks/20260609-ios-workflow-comparison/zmr-final/zmr-6","platform":"ios","device":"booted","appId":"com.example.mobiletest","scenario":"examples/ios-shim-workflow.json","appBuild":"generated-ios-workflow-demo-20260609","traceStatus":"passed"}
|
|
7
|
+
{"tool":"zmr","run":7,"status":"ok","durationMs":18335,"traceDir":"traces/public-benchmarks/20260609-ios-workflow-comparison/zmr-final/zmr-7","platform":"ios","device":"booted","appId":"com.example.mobiletest","scenario":"examples/ios-shim-workflow.json","appBuild":"generated-ios-workflow-demo-20260609","traceStatus":"passed"}
|
|
8
|
+
{"tool":"zmr","run":8,"status":"ok","durationMs":18195,"traceDir":"traces/public-benchmarks/20260609-ios-workflow-comparison/zmr-final/zmr-8","platform":"ios","device":"booted","appId":"com.example.mobiletest","scenario":"examples/ios-shim-workflow.json","appBuild":"generated-ios-workflow-demo-20260609","traceStatus":"passed"}
|
|
9
|
+
{"tool":"zmr","run":9,"status":"ok","durationMs":17859,"traceDir":"traces/public-benchmarks/20260609-ios-workflow-comparison/zmr-final/zmr-9","platform":"ios","device":"booted","appId":"com.example.mobiletest","scenario":"examples/ios-shim-workflow.json","appBuild":"generated-ios-workflow-demo-20260609","traceStatus":"passed"}
|
|
10
|
+
{"tool":"zmr","run":10,"status":"ok","durationMs":21344,"traceDir":"traces/public-benchmarks/20260609-ios-workflow-comparison/zmr-final/zmr-10","platform":"ios","device":"booted","appId":"com.example.mobiletest","scenario":"examples/ios-shim-workflow.json","appBuild":"generated-ios-workflow-demo-20260609","traceStatus":"passed"}
|
|
11
|
+
{"tool":"zmr","run":11,"status":"ok","durationMs":21375,"traceDir":"traces/public-benchmarks/20260609-ios-workflow-comparison/zmr-final/zmr-11","platform":"ios","device":"booted","appId":"com.example.mobiletest","scenario":"examples/ios-shim-workflow.json","appBuild":"generated-ios-workflow-demo-20260609","traceStatus":"passed"}
|
|
12
|
+
{"tool":"zmr","run":12,"status":"ok","durationMs":20713,"traceDir":"traces/public-benchmarks/20260609-ios-workflow-comparison/zmr-final/zmr-12","platform":"ios","device":"booted","appId":"com.example.mobiletest","scenario":"examples/ios-shim-workflow.json","appBuild":"generated-ios-workflow-demo-20260609","traceStatus":"passed"}
|
|
13
|
+
{"tool":"zmr","run":13,"status":"ok","durationMs":18959,"traceDir":"traces/public-benchmarks/20260609-ios-workflow-comparison/zmr-final/zmr-13","platform":"ios","device":"booted","appId":"com.example.mobiletest","scenario":"examples/ios-shim-workflow.json","appBuild":"generated-ios-workflow-demo-20260609","traceStatus":"passed"}
|
|
14
|
+
{"tool":"zmr","run":14,"status":"ok","durationMs":20610,"traceDir":"traces/public-benchmarks/20260609-ios-workflow-comparison/zmr-final/zmr-14","platform":"ios","device":"booted","appId":"com.example.mobiletest","scenario":"examples/ios-shim-workflow.json","appBuild":"generated-ios-workflow-demo-20260609","traceStatus":"passed"}
|
|
15
|
+
{"tool":"zmr","run":15,"status":"ok","durationMs":22176,"traceDir":"traces/public-benchmarks/20260609-ios-workflow-comparison/zmr-final/zmr-15","platform":"ios","device":"booted","appId":"com.example.mobiletest","scenario":"examples/ios-shim-workflow.json","appBuild":"generated-ios-workflow-demo-20260609","traceStatus":"passed"}
|
|
16
|
+
{"tool":"zmr","run":16,"status":"ok","durationMs":18852,"traceDir":"traces/public-benchmarks/20260609-ios-workflow-comparison/zmr-final/zmr-16","platform":"ios","device":"booted","appId":"com.example.mobiletest","scenario":"examples/ios-shim-workflow.json","appBuild":"generated-ios-workflow-demo-20260609","traceStatus":"passed"}
|
|
17
|
+
{"tool":"zmr","run":17,"status":"ok","durationMs":22970,"traceDir":"traces/public-benchmarks/20260609-ios-workflow-comparison/zmr-final/zmr-17","platform":"ios","device":"booted","appId":"com.example.mobiletest","scenario":"examples/ios-shim-workflow.json","appBuild":"generated-ios-workflow-demo-20260609","traceStatus":"passed"}
|
|
18
|
+
{"tool":"zmr","run":18,"status":"ok","durationMs":18682,"traceDir":"traces/public-benchmarks/20260609-ios-workflow-comparison/zmr-final/zmr-18","platform":"ios","device":"booted","appId":"com.example.mobiletest","scenario":"examples/ios-shim-workflow.json","appBuild":"generated-ios-workflow-demo-20260609","traceStatus":"passed"}
|
|
19
|
+
{"tool":"zmr","run":19,"status":"ok","durationMs":18347,"traceDir":"traces/public-benchmarks/20260609-ios-workflow-comparison/zmr-final/zmr-19","platform":"ios","device":"booted","appId":"com.example.mobiletest","scenario":"examples/ios-shim-workflow.json","appBuild":"generated-ios-workflow-demo-20260609","traceStatus":"passed"}
|
|
20
|
+
{"tool":"zmr","run":20,"status":"ok","durationMs":18951,"traceDir":"traces/public-benchmarks/20260609-ios-workflow-comparison/zmr-final/zmr-20","platform":"ios","device":"booted","appId":"com.example.mobiletest","scenario":"examples/ios-shim-workflow.json","appBuild":"generated-ios-workflow-demo-20260609","traceStatus":"passed"}
|
|
21
|
+
{"tool":"maestro","run":1,"status":"ok","durationMs":47502,"traceDir":"traces/public-benchmarks/20260609-ios-workflow-comparison/maestro/maestro-1","platform":"ios","device":"booted","appId":"com.example.mobiletest","scenario":"examples/ios-shim-workflow.json","appBuild":"generated-ios-workflow-demo-20260609"}
|
|
22
|
+
{"tool":"maestro","run":2,"status":"ok","durationMs":29793,"traceDir":"traces/public-benchmarks/20260609-ios-workflow-comparison/maestro/maestro-2","platform":"ios","device":"booted","appId":"com.example.mobiletest","scenario":"examples/ios-shim-workflow.json","appBuild":"generated-ios-workflow-demo-20260609"}
|
|
23
|
+
{"tool":"maestro","run":3,"status":"ok","durationMs":31898,"traceDir":"traces/public-benchmarks/20260609-ios-workflow-comparison/maestro/maestro-3","platform":"ios","device":"booted","appId":"com.example.mobiletest","scenario":"examples/ios-shim-workflow.json","appBuild":"generated-ios-workflow-demo-20260609"}
|
|
24
|
+
{"tool":"maestro","run":4,"status":"ok","durationMs":27151,"traceDir":"traces/public-benchmarks/20260609-ios-workflow-comparison/maestro/maestro-4","platform":"ios","device":"booted","appId":"com.example.mobiletest","scenario":"examples/ios-shim-workflow.json","appBuild":"generated-ios-workflow-demo-20260609"}
|
|
25
|
+
{"tool":"maestro","run":5,"status":"ok","durationMs":31825,"traceDir":"traces/public-benchmarks/20260609-ios-workflow-comparison/maestro/maestro-5","platform":"ios","device":"booted","appId":"com.example.mobiletest","scenario":"examples/ios-shim-workflow.json","appBuild":"generated-ios-workflow-demo-20260609"}
|
|
26
|
+
{"tool":"maestro","run":6,"status":"ok","durationMs":32080,"traceDir":"traces/public-benchmarks/20260609-ios-workflow-comparison/maestro/maestro-6","platform":"ios","device":"booted","appId":"com.example.mobiletest","scenario":"examples/ios-shim-workflow.json","appBuild":"generated-ios-workflow-demo-20260609"}
|
|
27
|
+
{"tool":"maestro","run":7,"status":"ok","durationMs":27544,"traceDir":"traces/public-benchmarks/20260609-ios-workflow-comparison/maestro/maestro-7","platform":"ios","device":"booted","appId":"com.example.mobiletest","scenario":"examples/ios-shim-workflow.json","appBuild":"generated-ios-workflow-demo-20260609"}
|
|
28
|
+
{"tool":"maestro","run":8,"status":"ok","durationMs":30177,"traceDir":"traces/public-benchmarks/20260609-ios-workflow-comparison/maestro/maestro-8","platform":"ios","device":"booted","appId":"com.example.mobiletest","scenario":"examples/ios-shim-workflow.json","appBuild":"generated-ios-workflow-demo-20260609"}
|
|
29
|
+
{"tool":"maestro","run":9,"status":"ok","durationMs":31528,"traceDir":"traces/public-benchmarks/20260609-ios-workflow-comparison/maestro/maestro-9","platform":"ios","device":"booted","appId":"com.example.mobiletest","scenario":"examples/ios-shim-workflow.json","appBuild":"generated-ios-workflow-demo-20260609"}
|
|
30
|
+
{"tool":"maestro","run":10,"status":"ok","durationMs":30227,"traceDir":"traces/public-benchmarks/20260609-ios-workflow-comparison/maestro/maestro-10","platform":"ios","device":"booted","appId":"com.example.mobiletest","scenario":"examples/ios-shim-workflow.json","appBuild":"generated-ios-workflow-demo-20260609"}
|
|
31
|
+
{"tool":"maestro","run":11,"status":"ok","durationMs":29175,"traceDir":"traces/public-benchmarks/20260609-ios-workflow-comparison/maestro/maestro-11","platform":"ios","device":"booted","appId":"com.example.mobiletest","scenario":"examples/ios-shim-workflow.json","appBuild":"generated-ios-workflow-demo-20260609"}
|
|
32
|
+
{"tool":"maestro","run":12,"status":"ok","durationMs":30119,"traceDir":"traces/public-benchmarks/20260609-ios-workflow-comparison/maestro/maestro-12","platform":"ios","device":"booted","appId":"com.example.mobiletest","scenario":"examples/ios-shim-workflow.json","appBuild":"generated-ios-workflow-demo-20260609"}
|
|
33
|
+
{"tool":"maestro","run":13,"status":"ok","durationMs":38762,"traceDir":"traces/public-benchmarks/20260609-ios-workflow-comparison/maestro/maestro-13","platform":"ios","device":"booted","appId":"com.example.mobiletest","scenario":"examples/ios-shim-workflow.json","appBuild":"generated-ios-workflow-demo-20260609"}
|
|
34
|
+
{"tool":"maestro","run":14,"status":"ok","durationMs":36592,"traceDir":"traces/public-benchmarks/20260609-ios-workflow-comparison/maestro/maestro-14","platform":"ios","device":"booted","appId":"com.example.mobiletest","scenario":"examples/ios-shim-workflow.json","appBuild":"generated-ios-workflow-demo-20260609"}
|
|
35
|
+
{"tool":"maestro","run":15,"status":"ok","durationMs":29813,"traceDir":"traces/public-benchmarks/20260609-ios-workflow-comparison/maestro/maestro-15","platform":"ios","device":"booted","appId":"com.example.mobiletest","scenario":"examples/ios-shim-workflow.json","appBuild":"generated-ios-workflow-demo-20260609"}
|
|
36
|
+
{"tool":"maestro","run":16,"status":"ok","durationMs":34198,"traceDir":"traces/public-benchmarks/20260609-ios-workflow-comparison/maestro/maestro-16","platform":"ios","device":"booted","appId":"com.example.mobiletest","scenario":"examples/ios-shim-workflow.json","appBuild":"generated-ios-workflow-demo-20260609"}
|
|
37
|
+
{"tool":"maestro","run":17,"status":"ok","durationMs":42114,"traceDir":"traces/public-benchmarks/20260609-ios-workflow-comparison/maestro/maestro-17","platform":"ios","device":"booted","appId":"com.example.mobiletest","scenario":"examples/ios-shim-workflow.json","appBuild":"generated-ios-workflow-demo-20260609"}
|
|
38
|
+
{"tool":"maestro","run":18,"status":"ok","durationMs":46397,"traceDir":"traces/public-benchmarks/20260609-ios-workflow-comparison/maestro/maestro-18","platform":"ios","device":"booted","appId":"com.example.mobiletest","scenario":"examples/ios-shim-workflow.json","appBuild":"generated-ios-workflow-demo-20260609"}
|
|
39
|
+
{"tool":"maestro","run":19,"status":"ok","durationMs":44429,"traceDir":"traces/public-benchmarks/20260609-ios-workflow-comparison/maestro/maestro-19","platform":"ios","device":"booted","appId":"com.example.mobiletest","scenario":"examples/ios-shim-workflow.json","appBuild":"generated-ios-workflow-demo-20260609"}
|
|
40
|
+
{"tool":"maestro","run":20,"status":"ok","durationMs":73476,"traceDir":"traces/public-benchmarks/20260609-ios-workflow-comparison/maestro/maestro-20","platform":"ios","device":"booted","appId":"com.example.mobiletest","scenario":"examples/ios-shim-workflow.json","appBuild":"generated-ios-workflow-demo-20260609"}
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
# 2026-06-09 iOS Simulator XCTest Shim Floor
|
|
2
|
+
|
|
3
|
+
This evidence pack compares the optimized ZMR iOS shim-backed smoke flow with a
|
|
4
|
+
direct XCTest-shim floor on the generated public iOS demo app.
|
|
5
|
+
|
|
6
|
+
The floor is not a competing product. It bypasses ZMR scenario parsing, trace
|
|
7
|
+
events, screenshots, result normalization, and reporting. It is useful because
|
|
8
|
+
it shows how much room remains between ZMR and the warmed native shim path.
|
|
9
|
+
|
|
10
|
+
## Result
|
|
11
|
+
|
|
12
|
+
| Tool | Runs | Pass rate | Failures | Mean duration | p95 duration |
|
|
13
|
+
| --- | ---: | ---: | ---: | ---: | ---: |
|
|
14
|
+
| ZMR with XCTest shim | 20 | 100.00% | 0 | 2007 ms | 2969 ms |
|
|
15
|
+
| Direct XCTest shim floor | 20 | 100.00% | 0 | 1004 ms | 962 ms |
|
|
16
|
+
|
|
17
|
+
Before this run, ZMR was changed to skip the slow best-effort iOS "Open"
|
|
18
|
+
confirmation probe for custom URL schemes. Universal `http://` and `https://`
|
|
19
|
+
links still keep that safety check.
|
|
20
|
+
|
|
21
|
+
The result: ZMR is now roughly 2.0x the direct warmed shim mean for this flow,
|
|
22
|
+
while still producing scenario semantics and trace artifacts.
|
|
23
|
+
|
|
24
|
+
## Environment
|
|
25
|
+
|
|
26
|
+
| Field | Value |
|
|
27
|
+
| --- | --- |
|
|
28
|
+
| ZMR runner | `0.1.8` |
|
|
29
|
+
| ZMR protocol | `2026-04-28` |
|
|
30
|
+
| Host OS | macOS 26.6, arm64 |
|
|
31
|
+
| Xcode | 26.5, build 17F42 |
|
|
32
|
+
| Simulator | Booted iOS 26.5 simulator, `zmr-iPhone` |
|
|
33
|
+
| App id | `com.example.mobiletest` |
|
|
34
|
+
| App build label | `generated-ios-demo-20260609` |
|
|
35
|
+
| Demo app source | Generated by `scripts/create-ios-demo-app.sh` |
|
|
36
|
+
|
|
37
|
+
## ZMR Command
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
ZMR_BIN="$PWD/zig-out/bin/zmr" scripts/benchmark.sh \
|
|
41
|
+
--zmr examples/ios-smoke.json \
|
|
42
|
+
--platform ios \
|
|
43
|
+
--ios-device-type simulator \
|
|
44
|
+
--device booted \
|
|
45
|
+
--app-id com.example.mobiletest \
|
|
46
|
+
--xcrun xcrun \
|
|
47
|
+
--ios-shim /tmp/zmr-public-benchmark-ios-demo-20260609-plain/.zmr/ios-shim \
|
|
48
|
+
--app-build generated-ios-demo-20260609 \
|
|
49
|
+
--runs 20 \
|
|
50
|
+
--trace-root traces/public-benchmarks/20260609-ios-xctest-floor-optimized/zmr \
|
|
51
|
+
--results traces/public-benchmarks/20260609-ios-xctest-floor-optimized/results.jsonl \
|
|
52
|
+
--replace \
|
|
53
|
+
--min-pass-rate 100 \
|
|
54
|
+
--max-failures 0
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
## Direct XCTest Shim Floor Command
|
|
58
|
+
|
|
59
|
+
The direct floor launches the already-installed app, opens the same custom
|
|
60
|
+
scheme URL, sends one `snapshot` command to the warmed XCTest shim server, and
|
|
61
|
+
asserts that the snapshot contains `Deep link opened`.
|
|
62
|
+
|
|
63
|
+
It intentionally does not terminate the app before each run. Terminating the app
|
|
64
|
+
under a persistent XCTest runner can invalidate XCTest's connection to the app
|
|
65
|
+
and create failures unrelated to ZMR.
|
|
66
|
+
|
|
67
|
+
```bash
|
|
68
|
+
scripts/benchmark-command.sh \
|
|
69
|
+
--tool xctest-shim \
|
|
70
|
+
--platform ios \
|
|
71
|
+
--device booted \
|
|
72
|
+
--app-id com.example.mobiletest \
|
|
73
|
+
--scenario examples/ios-smoke.json \
|
|
74
|
+
--app-build generated-ios-demo-20260609 \
|
|
75
|
+
--runs 20 \
|
|
76
|
+
--trace-root traces/public-benchmarks/20260609-ios-xctest-floor-optimized/xctest-shim \
|
|
77
|
+
--results traces/public-benchmarks/20260609-ios-xctest-floor-optimized/results.jsonl \
|
|
78
|
+
--min-pass-rate 100 \
|
|
79
|
+
--max-failures 0 \
|
|
80
|
+
-- bash -lc '<simctl launch, simctl openurl, direct shim snapshot, grep status text>'
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
## Comparison Report
|
|
84
|
+
|
|
85
|
+
```text
|
|
86
|
+
# Benchmark Comparison
|
|
87
|
+
|
|
88
|
+
| Tool | Runs | Pass rate | Failures | Mean ms | P95 ms |
|
|
89
|
+
| --- | ---: | ---: | ---: | ---: | ---: |
|
|
90
|
+
| zmr | 20 | 100.00% | 0 | 2007 | 2969 |
|
|
91
|
+
| xctest-shim | 20 | 100.00% | 0 | 1004 | 962 |
|
|
92
|
+
|
|
93
|
+
- Mean speedup: 0.50x (+99.9% candidate vs baseline)
|
|
94
|
+
- P95 speedup: 0.32x (+208.6% candidate vs baseline)
|
|
95
|
+
- Same benchmark context: yes
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
The sanitized result rows are committed in
|
|
99
|
+
[2026-06-09-ios-xctest-floor.results.jsonl](2026-06-09-ios-xctest-floor.results.jsonl).
|
|
100
|
+
|
|
101
|
+
## Scope
|
|
102
|
+
|
|
103
|
+
This floor is a native-path reference point, not a replacement for product
|
|
104
|
+
benchmarks. It does not include trace writing, scenario validation, artifact
|
|
105
|
+
capture, report generation, JSONL result normalization, or multi-step selector
|
|
106
|
+
logic.
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
{"tool":"zmr","run":1,"status":"ok","durationMs":4500,"traceDir":"traces/public-benchmarks/20260609-ios-xctest-floor-optimized/zmr/zmr-1","platform":"ios","device":"booted","appId":"com.example.mobiletest","scenario":"examples/ios-smoke.json","appBuild":"generated-ios-demo-20260609","traceStatus":"passed"}
|
|
2
|
+
{"tool":"zmr","run":2,"status":"ok","durationMs":1810,"traceDir":"traces/public-benchmarks/20260609-ios-xctest-floor-optimized/zmr/zmr-2","platform":"ios","device":"booted","appId":"com.example.mobiletest","scenario":"examples/ios-smoke.json","appBuild":"generated-ios-demo-20260609","traceStatus":"passed"}
|
|
3
|
+
{"tool":"zmr","run":3,"status":"ok","durationMs":2969,"traceDir":"traces/public-benchmarks/20260609-ios-xctest-floor-optimized/zmr/zmr-3","platform":"ios","device":"booted","appId":"com.example.mobiletest","scenario":"examples/ios-smoke.json","appBuild":"generated-ios-demo-20260609","traceStatus":"passed"}
|
|
4
|
+
{"tool":"zmr","run":4,"status":"ok","durationMs":1816,"traceDir":"traces/public-benchmarks/20260609-ios-xctest-floor-optimized/zmr/zmr-4","platform":"ios","device":"booted","appId":"com.example.mobiletest","scenario":"examples/ios-smoke.json","appBuild":"generated-ios-demo-20260609","traceStatus":"passed"}
|
|
5
|
+
{"tool":"zmr","run":5,"status":"ok","durationMs":1778,"traceDir":"traces/public-benchmarks/20260609-ios-xctest-floor-optimized/zmr/zmr-5","platform":"ios","device":"booted","appId":"com.example.mobiletest","scenario":"examples/ios-smoke.json","appBuild":"generated-ios-demo-20260609","traceStatus":"passed"}
|
|
6
|
+
{"tool":"zmr","run":6,"status":"ok","durationMs":1782,"traceDir":"traces/public-benchmarks/20260609-ios-xctest-floor-optimized/zmr/zmr-6","platform":"ios","device":"booted","appId":"com.example.mobiletest","scenario":"examples/ios-smoke.json","appBuild":"generated-ios-demo-20260609","traceStatus":"passed"}
|
|
7
|
+
{"tool":"zmr","run":7,"status":"ok","durationMs":1936,"traceDir":"traces/public-benchmarks/20260609-ios-xctest-floor-optimized/zmr/zmr-7","platform":"ios","device":"booted","appId":"com.example.mobiletest","scenario":"examples/ios-smoke.json","appBuild":"generated-ios-demo-20260609","traceStatus":"passed"}
|
|
8
|
+
{"tool":"zmr","run":8,"status":"ok","durationMs":1820,"traceDir":"traces/public-benchmarks/20260609-ios-xctest-floor-optimized/zmr/zmr-8","platform":"ios","device":"booted","appId":"com.example.mobiletest","scenario":"examples/ios-smoke.json","appBuild":"generated-ios-demo-20260609","traceStatus":"passed"}
|
|
9
|
+
{"tool":"zmr","run":9,"status":"ok","durationMs":1797,"traceDir":"traces/public-benchmarks/20260609-ios-xctest-floor-optimized/zmr/zmr-9","platform":"ios","device":"booted","appId":"com.example.mobiletest","scenario":"examples/ios-smoke.json","appBuild":"generated-ios-demo-20260609","traceStatus":"passed"}
|
|
10
|
+
{"tool":"zmr","run":10,"status":"ok","durationMs":1794,"traceDir":"traces/public-benchmarks/20260609-ios-xctest-floor-optimized/zmr/zmr-10","platform":"ios","device":"booted","appId":"com.example.mobiletest","scenario":"examples/ios-smoke.json","appBuild":"generated-ios-demo-20260609","traceStatus":"passed"}
|
|
11
|
+
{"tool":"zmr","run":11,"status":"ok","durationMs":1791,"traceDir":"traces/public-benchmarks/20260609-ios-xctest-floor-optimized/zmr/zmr-11","platform":"ios","device":"booted","appId":"com.example.mobiletest","scenario":"examples/ios-smoke.json","appBuild":"generated-ios-demo-20260609","traceStatus":"passed"}
|
|
12
|
+
{"tool":"zmr","run":12,"status":"ok","durationMs":1801,"traceDir":"traces/public-benchmarks/20260609-ios-xctest-floor-optimized/zmr/zmr-12","platform":"ios","device":"booted","appId":"com.example.mobiletest","scenario":"examples/ios-smoke.json","appBuild":"generated-ios-demo-20260609","traceStatus":"passed"}
|
|
13
|
+
{"tool":"zmr","run":13,"status":"ok","durationMs":1901,"traceDir":"traces/public-benchmarks/20260609-ios-xctest-floor-optimized/zmr/zmr-13","platform":"ios","device":"booted","appId":"com.example.mobiletest","scenario":"examples/ios-smoke.json","appBuild":"generated-ios-demo-20260609","traceStatus":"passed"}
|
|
14
|
+
{"tool":"zmr","run":14,"status":"ok","durationMs":1709,"traceDir":"traces/public-benchmarks/20260609-ios-xctest-floor-optimized/zmr/zmr-14","platform":"ios","device":"booted","appId":"com.example.mobiletest","scenario":"examples/ios-smoke.json","appBuild":"generated-ios-demo-20260609","traceStatus":"passed"}
|
|
15
|
+
{"tool":"zmr","run":15,"status":"ok","durationMs":1847,"traceDir":"traces/public-benchmarks/20260609-ios-xctest-floor-optimized/zmr/zmr-15","platform":"ios","device":"booted","appId":"com.example.mobiletest","scenario":"examples/ios-smoke.json","appBuild":"generated-ios-demo-20260609","traceStatus":"passed"}
|
|
16
|
+
{"tool":"zmr","run":16,"status":"ok","durationMs":1805,"traceDir":"traces/public-benchmarks/20260609-ios-xctest-floor-optimized/zmr/zmr-16","platform":"ios","device":"booted","appId":"com.example.mobiletest","scenario":"examples/ios-smoke.json","appBuild":"generated-ios-demo-20260609","traceStatus":"passed"}
|
|
17
|
+
{"tool":"zmr","run":17,"status":"ok","durationMs":1810,"traceDir":"traces/public-benchmarks/20260609-ios-xctest-floor-optimized/zmr/zmr-17","platform":"ios","device":"booted","appId":"com.example.mobiletest","scenario":"examples/ios-smoke.json","appBuild":"generated-ios-demo-20260609","traceStatus":"passed"}
|
|
18
|
+
{"tool":"zmr","run":18,"status":"ok","durationMs":1800,"traceDir":"traces/public-benchmarks/20260609-ios-xctest-floor-optimized/zmr/zmr-18","platform":"ios","device":"booted","appId":"com.example.mobiletest","scenario":"examples/ios-smoke.json","appBuild":"generated-ios-demo-20260609","traceStatus":"passed"}
|
|
19
|
+
{"tool":"zmr","run":19,"status":"ok","durationMs":1843,"traceDir":"traces/public-benchmarks/20260609-ios-xctest-floor-optimized/zmr/zmr-19","platform":"ios","device":"booted","appId":"com.example.mobiletest","scenario":"examples/ios-smoke.json","appBuild":"generated-ios-demo-20260609","traceStatus":"passed"}
|
|
20
|
+
{"tool":"zmr","run":20,"status":"ok","durationMs":1833,"traceDir":"traces/public-benchmarks/20260609-ios-xctest-floor-optimized/zmr/zmr-20","platform":"ios","device":"booted","appId":"com.example.mobiletest","scenario":"examples/ios-smoke.json","appBuild":"generated-ios-demo-20260609","traceStatus":"passed"}
|
|
21
|
+
{"tool":"xctest-shim","run":1,"status":"ok","durationMs":3403,"traceDir":"traces/public-benchmarks/20260609-ios-xctest-floor-optimized/xctest-shim/xctest-shim-1","platform":"ios","device":"booted","appId":"com.example.mobiletest","scenario":"examples/ios-smoke.json","appBuild":"generated-ios-demo-20260609"}
|
|
22
|
+
{"tool":"xctest-shim","run":2,"status":"ok","durationMs":879,"traceDir":"traces/public-benchmarks/20260609-ios-xctest-floor-optimized/xctest-shim/xctest-shim-2","platform":"ios","device":"booted","appId":"com.example.mobiletest","scenario":"examples/ios-smoke.json","appBuild":"generated-ios-demo-20260609"}
|
|
23
|
+
{"tool":"xctest-shim","run":3,"status":"ok","durationMs":808,"traceDir":"traces/public-benchmarks/20260609-ios-xctest-floor-optimized/xctest-shim/xctest-shim-3","platform":"ios","device":"booted","appId":"com.example.mobiletest","scenario":"examples/ios-smoke.json","appBuild":"generated-ios-demo-20260609"}
|
|
24
|
+
{"tool":"xctest-shim","run":4,"status":"ok","durationMs":912,"traceDir":"traces/public-benchmarks/20260609-ios-xctest-floor-optimized/xctest-shim/xctest-shim-4","platform":"ios","device":"booted","appId":"com.example.mobiletest","scenario":"examples/ios-smoke.json","appBuild":"generated-ios-demo-20260609"}
|
|
25
|
+
{"tool":"xctest-shim","run":5,"status":"ok","durationMs":904,"traceDir":"traces/public-benchmarks/20260609-ios-xctest-floor-optimized/xctest-shim/xctest-shim-5","platform":"ios","device":"booted","appId":"com.example.mobiletest","scenario":"examples/ios-smoke.json","appBuild":"generated-ios-demo-20260609"}
|
|
26
|
+
{"tool":"xctest-shim","run":6,"status":"ok","durationMs":874,"traceDir":"traces/public-benchmarks/20260609-ios-xctest-floor-optimized/xctest-shim/xctest-shim-6","platform":"ios","device":"booted","appId":"com.example.mobiletest","scenario":"examples/ios-smoke.json","appBuild":"generated-ios-demo-20260609"}
|
|
27
|
+
{"tool":"xctest-shim","run":7,"status":"ok","durationMs":959,"traceDir":"traces/public-benchmarks/20260609-ios-xctest-floor-optimized/xctest-shim/xctest-shim-7","platform":"ios","device":"booted","appId":"com.example.mobiletest","scenario":"examples/ios-smoke.json","appBuild":"generated-ios-demo-20260609"}
|
|
28
|
+
{"tool":"xctest-shim","run":8,"status":"ok","durationMs":871,"traceDir":"traces/public-benchmarks/20260609-ios-xctest-floor-optimized/xctest-shim/xctest-shim-8","platform":"ios","device":"booted","appId":"com.example.mobiletest","scenario":"examples/ios-smoke.json","appBuild":"generated-ios-demo-20260609"}
|
|
29
|
+
{"tool":"xctest-shim","run":9,"status":"ok","durationMs":870,"traceDir":"traces/public-benchmarks/20260609-ios-xctest-floor-optimized/xctest-shim/xctest-shim-9","platform":"ios","device":"booted","appId":"com.example.mobiletest","scenario":"examples/ios-smoke.json","appBuild":"generated-ios-demo-20260609"}
|
|
30
|
+
{"tool":"xctest-shim","run":10,"status":"ok","durationMs":870,"traceDir":"traces/public-benchmarks/20260609-ios-xctest-floor-optimized/xctest-shim/xctest-shim-10","platform":"ios","device":"booted","appId":"com.example.mobiletest","scenario":"examples/ios-smoke.json","appBuild":"generated-ios-demo-20260609"}
|
|
31
|
+
{"tool":"xctest-shim","run":11,"status":"ok","durationMs":865,"traceDir":"traces/public-benchmarks/20260609-ios-xctest-floor-optimized/xctest-shim/xctest-shim-11","platform":"ios","device":"booted","appId":"com.example.mobiletest","scenario":"examples/ios-smoke.json","appBuild":"generated-ios-demo-20260609"}
|
|
32
|
+
{"tool":"xctest-shim","run":12,"status":"ok","durationMs":876,"traceDir":"traces/public-benchmarks/20260609-ios-xctest-floor-optimized/xctest-shim/xctest-shim-12","platform":"ios","device":"booted","appId":"com.example.mobiletest","scenario":"examples/ios-smoke.json","appBuild":"generated-ios-demo-20260609"}
|
|
33
|
+
{"tool":"xctest-shim","run":13,"status":"ok","durationMs":962,"traceDir":"traces/public-benchmarks/20260609-ios-xctest-floor-optimized/xctest-shim/xctest-shim-13","platform":"ios","device":"booted","appId":"com.example.mobiletest","scenario":"examples/ios-smoke.json","appBuild":"generated-ios-demo-20260609"}
|
|
34
|
+
{"tool":"xctest-shim","run":14,"status":"ok","durationMs":864,"traceDir":"traces/public-benchmarks/20260609-ios-xctest-floor-optimized/xctest-shim/xctest-shim-14","platform":"ios","device":"booted","appId":"com.example.mobiletest","scenario":"examples/ios-smoke.json","appBuild":"generated-ios-demo-20260609"}
|
|
35
|
+
{"tool":"xctest-shim","run":15,"status":"ok","durationMs":823,"traceDir":"traces/public-benchmarks/20260609-ios-xctest-floor-optimized/xctest-shim/xctest-shim-15","platform":"ios","device":"booted","appId":"com.example.mobiletest","scenario":"examples/ios-smoke.json","appBuild":"generated-ios-demo-20260609"}
|
|
36
|
+
{"tool":"xctest-shim","run":16,"status":"ok","durationMs":861,"traceDir":"traces/public-benchmarks/20260609-ios-xctest-floor-optimized/xctest-shim/xctest-shim-16","platform":"ios","device":"booted","appId":"com.example.mobiletest","scenario":"examples/ios-smoke.json","appBuild":"generated-ios-demo-20260609"}
|
|
37
|
+
{"tool":"xctest-shim","run":17,"status":"ok","durationMs":862,"traceDir":"traces/public-benchmarks/20260609-ios-xctest-floor-optimized/xctest-shim/xctest-shim-17","platform":"ios","device":"booted","appId":"com.example.mobiletest","scenario":"examples/ios-smoke.json","appBuild":"generated-ios-demo-20260609"}
|
|
38
|
+
{"tool":"xctest-shim","run":18,"status":"ok","durationMs":878,"traceDir":"traces/public-benchmarks/20260609-ios-xctest-floor-optimized/xctest-shim/xctest-shim-18","platform":"ios","device":"booted","appId":"com.example.mobiletest","scenario":"examples/ios-smoke.json","appBuild":"generated-ios-demo-20260609"}
|
|
39
|
+
{"tool":"xctest-shim","run":19,"status":"ok","durationMs":865,"traceDir":"traces/public-benchmarks/20260609-ios-xctest-floor-optimized/xctest-shim/xctest-shim-19","platform":"ios","device":"booted","appId":"com.example.mobiletest","scenario":"examples/ios-smoke.json","appBuild":"generated-ios-demo-20260609"}
|
|
40
|
+
{"tool":"xctest-shim","run":20,"status":"ok","durationMs":865,"traceDir":"traces/public-benchmarks/20260609-ios-xctest-floor-optimized/xctest-shim/xctest-shim-20","platform":"ios","device":"booted","appId":"com.example.mobiletest","scenario":"examples/ios-smoke.json","appBuild":"generated-ios-demo-20260609"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# Benchmark Evidence
|
|
2
|
+
|
|
3
|
+
This directory contains public-safe benchmark evidence collected from
|
|
4
|
+
reproducible ZMR demo apps.
|
|
5
|
+
|
|
6
|
+
Evidence here is intentionally narrow:
|
|
7
|
+
|
|
8
|
+
- It records the command, platform, runner version, run count, pass rate, and
|
|
9
|
+
duration summary.
|
|
10
|
+
- It does not claim ZMR is faster than another tool unless an equivalent
|
|
11
|
+
baseline was collected on the same app build, device state, and scenario.
|
|
12
|
+
- Raw local traces are not committed because generated reports and JUnit files
|
|
13
|
+
can include absolute local paths. Public rows are sanitized before commit.
|
|
14
|
+
|
|
15
|
+
## Evidence Packs
|
|
16
|
+
|
|
17
|
+
- [Benchmark Lab v1](benchmark-lab-v1.md): public fixture, timing-mode,
|
|
18
|
+
runner-adapter, and claim-rule plan for framework-level evidence.
|
|
19
|
+
- [2026-06-09 iOS simulator demo](2026-06-09-ios-demo.md): 20 repeated runs of
|
|
20
|
+
the public iOS smoke scenario on a booted simulator.
|
|
21
|
+
- [2026-06-09 iOS simulator ZMR vs Maestro comparison](2026-06-09-ios-maestro-comparison.md):
|
|
22
|
+
command-level comparison against Maestro on the same generated iOS demo app.
|
|
23
|
+
- [2026-06-09 iOS simulator ZMR vs Appium comparison](2026-06-09-ios-appium-comparison.md):
|
|
24
|
+
command-level comparison against Appium on the same generated iOS demo app.
|
|
25
|
+
- [2026-06-09 iOS simulator workflow comparison](2026-06-09-ios-workflow-comparison.md):
|
|
26
|
+
longer profile, catalog, save, and review workflow on the generated iOS demo
|
|
27
|
+
app.
|
|
28
|
+
- [2026-06-09 Android emulator workflow](2026-06-09-android-workflow.md):
|
|
29
|
+
20 repeated ZMR runs of the generated Android workflow demo app.
|
|
30
|
+
- React Native/Expo fixture: generated app and ZMR workflow scenarios are
|
|
31
|
+
available through `zmr-create-react-native-expo-demo-app`; public timing rows
|
|
32
|
+
are still pending.
|
|
33
|
+
- [2026-06-09 iOS simulator XCTest shim floor](2026-06-09-ios-xctest-floor.md):
|
|
34
|
+
native-path floor for the optimized iOS shim-backed smoke flow.
|
|
35
|
+
- [2026-06-09 framework baseline status](2026-06-09-framework-baseline-status.md):
|
|
36
|
+
status for Detox, Flutter, Espresso, and other framework-specific baselines.
|