Automated iOS App Testing
Use Synapse + Computer Control API to automate iOS app testing via Simulator.
Automated iOS App Testing
Combine Synapse's memory system with the Computer Control API to build LLM-driven iOS app tests. The LLM remembers test scenarios, learns from past failures, and adapts to UI changes.
Architecture
┌──────────────┐ commands ┌──────────────┐ screenshots ┌──────────────┐
│ LLM Agent │ ─────────────▶│ Synapse │ ────────────────▶ │ iOS Sim │
│ (Claude) │ │ Computer │ ◀──────────────── │ (via agent) │
└──────────────┘ │ Control │ results └──────────────┘
│ └──────────────┘
│ store/recall
▼
┌──────────────┐
│ Memories │ (test scenarios, past failures, UI patterns)
└──────────────┘Prerequisites
- Synapse account + Mind Key
- Synapse MCP server configured in Claude Desktop
- iOS Simulator with
screen-remote-agentinstalled - Computer registered in Synapse (see Computer Control API)
Step 1: Register the Simulator Computer
On the Mac running iOS Simulator:
# Get install code from Synapse
curl -X POST https://synapse.schaefer.zone/computers/install-code \
-H "Authorization: Bearer YOUR_MIND_KEY" \
-d '{"computer_name":"ios-sim"}'
# → { "install_code": "ic_..." }
# Run screen-remote-agent on the Mac
# (uses the install code to register)Step 2: Store Test Scenarios in Memory
Store reusable test scenarios as memories:
import requests
def store_test_scenario(name, steps, app):
requests.post(f"{URL}/memory",
headers={"Authorization": f"Bearer {MIND_KEY}"},
json={
"category": "skill",
"key": f"test_scenario_{name}",
"content": f"App: {app}\nSteps:\n" + "\n".join(steps),
"tags": ["test", "ios", app],
"priority": "high"
})
store_test_scenario("login_flow", [
"Launch app",
"Tap email field",
"Type test@example.com",
"Tap password field",
"Type password123",
"Tap Login button",
"Verify home screen appears"
], "MyApp")Step 3: LLM-Driven Test Execution
In Claude Desktop (with Synapse MCP configured):
Run the login_flow test scenario on the iOS Simulator.
Take a screenshot after each step and verify the expected UI.
If any step fails, store the failure as a memory so we can
avoid it next time.Claude will:
- Call
memory_searchto find thetest_scenario_login_flowmemory - Call
computer_screenshotto see the current state - Execute each step via
computer_command_queue(click, type) - Verify results via screenshots
- Store any failures as
mistakememories
Step 4: Self-Healing Tests
When a test fails, store the failure and the recovery:
def store_test_failure(scenario, step, error, recovery):
requests.post(f"{URL}/memory",
headers={"Authorization": f"Bearer {MIND_KEY}"},
json={
"category": "mistake",
"key": f"failure_{scenario}_{step}",
"content": f"Scenario: {scenario}\nStep: {step}\nError: {error}\nRecovery: {recovery}",
"tags": ["test", "failure", "ios", scenario],
"priority": "high"
})
# Example
store_test_failure("login_flow", "tap_login",
"Login button not found at expected coordinates",
"Button moved due to new logo. Search by accessibility label instead.")Next time the LLM runs the test, it recalls the failure and applies the recovery automatically.
Step 5: Test Result Tracking
Track test runs as tasks:
def track_test_run(scenario, status, duration):
requests.post(f"{URL}/mind/task",
headers={"Authorization": f"Bearer {MIND_KEY}",
"Content-Type": "application/json"},
json={
"title": f"Test: {scenario}",
"description": f"Status: {status}, Duration: {duration}s",
"priority": "normal"
})Common Commands
| Action | Command |
|---|---|
| Launch Simulator | xcrun simctl launch booted com.example.app |
| Screenshot | computer_screenshot (via Synapse MCP) |
| Tap at (x,y) | computer_command_queue {type:"click", payload:{x,y}} |
| Type text | computer_command_queue {type:"type", payload:{text:"..."}} |
| Press Home | computer_command_queue {type:"key", payload:{keys:["Cmd","Shift","H"]}} |