内容
<div align="center">
# 测试工具
**像人类一样驱动 iOS 模拟器 — 通过 AI 代理。**
真正的 HID 触摸(每个手势),通过辅助功能树读取屏幕
**或设备上的 OCR**,令牌高效,快速,**且无第三方依赖**。
测试 React Native / Expo 和原生 SwiftUI 应用端到端 — **无需添加单个 `testID`**。
[](https://github.com/seizeddev/testa/actions/workflows/ci.yml)
[](LICENSE)




<img src="assets/demo.gif" alt="Testa 驱动 iOS 模拟器 — 点击,缩放,旋转,拖放,输入" width="280">
<sub>代理点击,缩放,旋转,拖放,输入 — 所有操作都通过辅助功能树验证,无需截图。</sub>
</div>
---
## 为什么选择 Testa
代理非常适合编写 iOS 应用,但在使用模拟器时显得笨拙。
**Testa 正是为此而设计** — 它有两大特点使其与众不同:它可以驱动 **零辅助功能** 的屏幕(通过设备上的 OCR),并且它是一个 **单一、完全开放、 无依赖的二进制文件**。
- 🧠 **无需应用设置。** 读取辅助功能树,并 fallback 到 **Apple Vision OCR** 以点击任何 **可见文本** — 因此它可以驱动画布、游戏、WebViews 和使用 vibe 编码的应用,而这些应用从未添加 `testID`。
- 🪙 **令牌高效。** 每个元素一行紧凑的代码 (`e5 Button "Save" #save @120,300`),并带有 `find` / `assert` / `ui diff` — 而不是截图。
- ⚡ **快速。** 一个温暖的守护进程保持连接,辅助功能翻译器和 HID 客户端热启动:**~60 ms** 每次快照。
- 👆 **每个手势都是真实的。** 点击,长按,滑动,**拖放**,**缩放/缩放**,**旋转**,多点触控,Unicode/表情符号文本 — 真正的 HID 事件。
- 🔌 **代理原生。** 提供 **MCP 服务器** (`testa mcp`) 和 Claude Code 技能。
- 🔒 **本地且私密。** 一个 `0600` 的 per-user Unix 套接字。无网络,无遥测。
- 📦 **零第三方运行时依赖。** 直接与 Apple 的 `CoreSimulator`,`SimulatorKit`,`AccessibilityPlatformTranslation`,Vision 和 `simctl` 通信。
| | **Testa** | Argent | idb | Appium | Maestro |
|---|:--:|:--:|:--:|:--:|:--:|
| 代理原生(MCP + 令牌高效快照) | ✅ | ✅ | ❌ | ❌ | ⚠️ |
| 驱动 **零辅助功能** 的屏幕(设备 OCR) | ✅ | ❌ | ❌ | ❌ | ❌ |
| 缩放 · 旋转 · 拖放 · 多点触控 | ✅ | ⚠️ | ✅ | ✅ | ⚠️ |
| 自包含:一个原生二进制文件,无 Node/SDK 运行时 | ✅ | ❌ | ❌ | ❌ | ❌ |
| 完全开源,无专有部分 | ✅ MIT | ⚠️ | ✅ | ✅ | ✅ |
| 平台 | iOS | iOS · Android | iOS | iOS · Android · web | iOS · Android |
| 即时调试和性能分析(日志 · 网络 · RN 树 · 仪器) | ❌ | ✅ | ⚠️ | ❌ | ❌ |
<sub>高级总结,根据 2026 年的文档对每个项目进行验证。这些都是很好的工具。最近的是 <a href="https://github.com/software-mansion/argent">Argent</a>(Software Mansion):比 Testa 更广泛(跨平台,深度调试和性能分析),但仅限于辅助功能(无 OCR),基于 Node,Apache-2.0 源代码 <em>加上专有二进制文件</em>。Testa 的定位:完全开放,无依赖,OCR 驱动,专注于 iOS。</sub>
## 快速开始
```bash
# 安装(一行)- 构建,安装技能,注册 MCP 服务器
brew install https://raw.githubusercontent.com/seizeddev/testa/main/Formula/testa.rb
testa setup
# … 或从源代码
git clone https://github.com/seizeddev/testa && cd testa && ./install.sh
```
```bash
testa boot "iPhone 17 Pro"
testa install ./MyApp.app && testa launch com.example.myapp
testa ui # 屏幕上的内容(令牌高效)
testa tap "继续" # 通过可见文本 - fallback 到 OCR
testa typein "#email" "a@b.co"
testa assert "#welcome" exists # → PASS / FAIL (退出 0/1)
```
> 第一次调用会启动一个后台守护进程并预热辅助功能(几秒钟,一次)。之后的每次调用大约为 ~60 ms。需要 macOS + Xcode 26(iOS 26 模拟器),Swift 6。
## 循环
1. **观察** — `testa ui`(屏幕元素)· `testa see`(OCR 每个可见文本)· `testa find <q>` · `testa scrollto <sel>`。
2. **操作** — `tap · typein · setvalue · clear · swipe · drag · dragdrop · pinch · rotate`。通过 `eN` 引用,`#identifier`,“label”或 `x y` 来定位元素。
3. **验证** — `testa assert <sel> [exists|gone|value=…|label=…]` (退出 0/1)。
```text
$ testa ui
25 个元素(在屏幕上)
e1 Application "Testa Native" @201,437
e5 Button "点击我" #tapButton @102,171
e16 TextField #textInput =type here @201,673
…
$ testa pinch "#map" 2.0 → 缩放
$ testa dragdrop "#card" "#trash" → 拖放
$ testa assert "#status" label=done → PASS exists e2 …
```
<details>
<summary><b>完整的命令参考</b></summary>
```
观察
ui [diff|full] 屏幕快照(diff = 更改,full = 包括屏幕外)
see 每个可见文本的 OCR + 点击坐标(任何应用)
find <query> 匹配标签/ID/值/角色的元素
scrollto <sel> 滚动直到元素可见
assert <sel> [exists|gone|value=..|label=..]
wait <sel> [timeoutMs]
screenshot [path]
操作(sel = eN 引用 · #identifier · "label")
tap <sel> | tap <x> <y> | tapocr <text>
typein <sel> <text> | type <text> | setvalue <sel> <text> | clear <sel>
key <hidUsage>
swipe <x1 y1 x2 y2>
drag <x1 y1 x2 y2 | fromSel toSel>
dragdrop <x1 y1 x2 y2 | fromSel toSel>
longpress <sel | x y> | pinch <sel | x y> <scale> | rotate <sel | x y> <radians>
应用 / 设备
devices | boot <udid|name> | shutdown <udid|all>
install <app> | launch <bundle> | terminate <bundle> | apps | open <url>
logs [bundle] [seconds] | crashes [bundle]
permission <grant|revoke|reset> <service> <bundle>
record <start [path] | stop>
设置 / 守护进程
setup | start | stop | status | info | mcp (目标模拟器:--udid <udid>)
```
</details>
## 无需应用设置
您 **不需要** 应用添加 `testID`。可见文本就足够:
- 原生 SwiftUI 和 RN `Text` / `Pressable` / `TextInput` 已经将其文本作为标签公开 — `testa tap "继续"`。
- 对于其他情况,`testa see` + `testa tapocr "<text>"` 通过 **设备上的 Apple Vision** 读取像素(无密钥,无网络)。这甚至可以驱动 HealthKit 权限表或由画布渲染的屏幕,这些屏幕暴露 *零* 辅助功能。
添加 `testID` / `accessibilityIdentifier` 只会使定位更加精确。
<div align="center"><img src="assets/ocr-demo.gif" alt="Testa 驱动一个 Canvas-rendered 屏幕,该屏幕具有零辅助功能,通过 OCR" width="240"></div>
上行的底部是使用 `Canvas` 绘制的 — 它暴露 **零** 辅助功能。
大多数工具(和仅限辅助功能的代理)都看不到它。Testa 不是这样:
```console
$ testa ui # 辅助功能树
… 没有 "开始" / "设置" / "个人资料" — 它们不是辅助功能元素
$ testa see # 设备 OCR
"开始" @79,702 "设置" @200,703 "个人资料" @322,702
$ testa tapocr "设置"
点击(ocr)"设置" @200,703 → #status = canvas:设置
```
## 用于 AI 代理
- **Claude Code** — `testa setup` 安装技能 (`skills/testa/SKILL.md`)。
- **任何 MCP 客户端** (Codex,Cursor,…)— `claude mcp add testa -- testa mcp`。
工具:`ui, see, find, scrollTo, tap, tapText, type, setValue, clear, key, swipe, drag, dragdrop, longpress, pinch, rotate, screenshot, assert, wait, install, launch, terminate, apps, logs, crashes, open, info`。
## 工作原理
```
代理 ──► testa(CLI) ──┐
代理 ──► testa mcp(MCP 服务器) ──┤ Unix 套接字(~/.testa/daemon-<udid>.sock, 0600)
▼
testad(温暖的守护进程)
│ Obj-C 引擎,dlopen 私有框架
┌──────────────┼───────────────┐
▼ ▼ ▼
SimulatorKit CoreSimulator AccessibilityPlatformTranslation
(Indigo HID) (SimDevice) (AXPTranslator → 辅助功能树) + Vision(OCR)
└──────────────┴────────────────┘
启动的 iOS 模拟器
```
- **HID 注入** 重新实现了 Indigo 触摸线格式
(`SimDeviceLegacyHIDClient`) — 点击/拖动/多点触控逐字节与模拟器的访客 HID 服务期望相同。
- **辅助功能** 通过令牌委托驱动 `AXPTranslator`,该委托将每个属性读取桥接到异步 `SimDevice` XPC 请求,生成 **与点击空间匹配的点坐标** 中的元素树。
- **OCR** 在进程内帧缓冲区捕获(IOSurface)上运行 Apple Vision。
## 示范 / 测试
两个示例应用具有复杂手势,并作为回归套件。每个应用都镜像上一个识别的手势到 `#status` 元素,因此手势仅通过辅助功能树验证:
- `examples/native` — SwiftUI · `examples/native/build.sh`,然后 `examples/native/e2e.sh`。
- `examples/rnshowcase` — Expo / React Native · 查看 `TESTA_README.md`。
```bash
make build # 调试构建
make test # 单元测试
make e2e # 手势回归与原生示范(需要启动模拟器)
```
## 限制(诚实)
- **仅图标控件,无文本和无辅助功能标签** 对任何自动化都模糊不清 — 使用坐标,或添加 `accessibilityLabel`。
- 设计上仅限 iOS 模拟器。真正的设备和 Android 超出范围。
- 预构建的二进制文件如果使用自己的 Apple Developer ID 构建,则不会被标记(`release.sh`);`clone` 和 Homebrew 路径从源代码构建。
- `testa record` 生成 H.264 MP4;不支持实时 FPS 流媒体。
## 项目
- [CONTRIBUTING](CONTRIBUTING.md) · [CHANGELOG](CHANGELOG.md) · [Onboarding](ONBOARDING.md)
- License: [MIT](LICENSE)
<div align="center"><sub>在 Xcode 26.4 / iOS 26.4(iPhone 17 Pro)上验证,针对 SwiftUI + Expo/React Native 示范应用和真实生产应用。</sub></div>