{"title":"Testing automatizzato di app iOS","slug":"automated-testing-ios","category":"guides","summary":"Usi Synapse + Computer Control API per automatizzare il testing di app iOS tramite Simulator.","audience":["human","llm"],"tags":["guide","ios","testing","automation"],"difficulty":"advanced","updated":"2026-06-27","word_count":332,"read_minutes":2,"lang":"it","translated":true,"requested_lang":"it","content_markdown":"\n# Testing automatizzato di app iOS\n\nCombini il sistema di memoria di Synapse con la Computer Control API per\ncostruire test di app iOS guidati da LLM. L'LLM ricorda gli scenari di test,\nimpara dai fallimenti passati e si adatta ai cambiamenti della UI.\n\n## Architettura\n\n```\n┌──────────────┐    commands    ┌──────────────┐    screenshots    ┌──────────────┐\n│  LLM Agent   │ ─────────────▶│  Synapse     │ ────────────────▶ │  iOS Sim     │\n│  (Claude)    │               │  Computer    │ ◀──────────────── │  (via agent) │\n└──────────────┘               │  Control     │    results        └──────────────┘\n       │                       └──────────────┘\n       │ store/recall\n       ▼\n┌──────────────┐\n│  Memories    │ (test scenarios, past failures, UI patterns)\n└──────────────┘\n```\n\n## Prerequisiti\n\n- Account Synapse + Mind Key\n- Server MCP di Synapse configurato in Claude Desktop\n- iOS Simulator con `screen-remote-agent` installato\n- Computer registrato in Synapse (veda [Computer Control API](/docs/api/computers))\n\n## Passo 1: Registri il computer Simulator\n\nSul Mac che esegue l'iOS Simulator:\n\n```bash\n# Get install code from Synapse\ncurl -X POST https://synapse.schaefer.zone/computers/install-code \\\n  -H \"Authorization: Bearer YOUR_MIND_KEY\" \\\n  -d '{\"computer_name\":\"ios-sim\"}'\n# → { \"install_code\": \"ic_...\" }\n\n# Run screen-remote-agent on the Mac\n# (uses the install code to register)\n```\n\n## Passo 2: Memorizzi gli scenari di test in memoria\n\nMemorizzi gli scenari di test riutilizzabili come memorie:\n\n```python\nimport requests\n\ndef store_test_scenario(name, steps, app):\n    requests.post(f\"{URL}/memory\",\n        headers={\"Authorization\": f\"Bearer {MIND_KEY}\"},\n        json={\n            \"category\": \"skill\",\n            \"key\": f\"test_scenario_{name}\",\n            \"content\": f\"App: {app}\\nSteps:\\n\" + \"\\n\".join(steps),\n            \"tags\": [\"test\", \"ios\", app],\n            \"priority\": \"high\"\n        })\n\nstore_test_scenario(\"login_flow\", [\n    \"Launch app\",\n    \"Tap email field\",\n    \"Type test@example.com\",\n    \"Tap password field\",\n    \"Type password123\",\n    \"Tap Login button\",\n    \"Verify home screen appears\"\n], \"MyApp\")\n```\n\n## Passo 3: Esecuzione del test guidata da LLM\n\nIn Claude Desktop (con Synapse MCP configurato):\n\n```\nRun the login_flow test scenario on the iOS Simulator.\nTake a screenshot after each step and verify the expected UI.\nIf any step fails, store the failure as a memory so we can\navoid it next time.\n```\n\nClaude:\n\n1. Chiamerà `memory_search` per trovare la memoria `test_scenario_login_flow`\n2. Chiamerà `computer_screenshot` per vedere lo stato corrente\n3. Eseguirà ogni passo tramite `computer_command_queue` (click, type)\n4. Verificherà i risultati tramite schermate\n5. Memorizzerà eventuali fallimenti come memorie `mistake`\n\n## Passo 4: Test self-healing\n\nQuando un test fallisce, memorizzi il fallimento e il recupero:\n\n```python\ndef store_test_failure(scenario, step, error, recovery):\n    requests.post(f\"{URL}/memory\",\n        headers={\"Authorization\": f\"Bearer {MIND_KEY}\"},\n        json={\n            \"category\": \"mistake\",\n            \"key\": f\"failure_{scenario}_{step}\",\n            \"content\": f\"Scenario: {scenario}\\nStep: {step}\\nError: {error}\\nRecovery: {recovery}\",\n            \"tags\": [\"test\", \"failure\", \"ios\", scenario],\n            \"priority\": \"high\"\n        })\n\n# Example\nstore_test_failure(\"login_flow\", \"tap_login\",\n    \"Login button not found at expected coordinates\",\n    \"Button moved due to new logo. Search by accessibility label instead.\")\n```\n\nLa prossima volta che l'LLM esegue il test, richiama il fallimento e applica\nil recupero automaticamente.\n\n## Passo 5: Tracciamento dei risultati dei test\n\nTracci le esecuzioni dei test come attività:\n\n```python\ndef track_test_run(scenario, status, duration):\n    requests.post(f\"{URL}/mind/task\",\n        headers={\"Authorization\": f\"Bearer {MIND_KEY}\",\n                 \"Content-Type\": \"application/json\"},\n        json={\n            \"title\": f\"Test: {scenario}\",\n            \"description\": f\"Status: {status}, Duration: {duration}s\",\n            \"priority\": \"normal\"\n        })\n```\n\n## Comandi comuni\n\n| Azione | Comando |\n|--------|---------|\n| Avvia Simulator | `xcrun simctl launch booted com.example.app` |\n| Schermata | `computer_screenshot` (tramite Synapse MCP) |\n| Tap a (x,y) | `computer_command_queue {type:\"click\", payload:{x,y}}` |\n| Digita testo | `computer_command_queue {type:\"type\", payload:{text:\"...\"}}` |\n| Premi Home | `computer_command_queue {type:\"key\", payload:{keys:[\"Cmd\",\"Shift\",\"H\"]}}` |\n\n## Best practice\n\n> [!TIP]\n> - **Memorizzi le coordinate UI come memorie** — la UI cambia, ma l'LLM può reimparare\n> - **Usi le etichette di accessibilità** — più stabili delle coordinate\n> - **Memorizzi i dati di test separatamente** — usi variabili per username, password\n> - **Esegua i test in stato pulito** — reset del Simulator tra le esecuzioni\n> - **Logghi le schermate per i fallimenti** — utili per il debug\n\n## Prossimi passi\n\n- [Test self-healing](/docs/guides/self-healing-tests)\n- [Computer Control API](/docs/api/computers)\n- [Best practice per la memoria](/docs/guides/memory-best-practices)\n","content_html":"<h1>Testing automatizzato di app iOS</h1>\n<p>Combini il sistema di memoria di Synapse con la Computer Control API per\ncostruire test di app iOS guidati da LLM. L&#39;LLM ricorda gli scenari di test,\nimpara dai fallimenti passati e si adatta ai cambiamenti della UI.</p>\n<h2>Architettura</h2>\n<pre><code class=\"hljs language-plaintext\">┌──────────────┐    commands    ┌──────────────┐    screenshots    ┌──────────────┐\n│  LLM Agent   │ ─────────────▶│  Synapse     │ ────────────────▶ │  iOS Sim     │\n│  (Claude)    │               │  Computer    │ ◀──────────────── │  (via agent) │\n└──────────────┘               │  Control     │    results        └──────────────┘\n       │                       └──────────────┘\n       │ store/recall\n       ▼\n┌──────────────┐\n│  Memories    │ (test scenarios, past failures, UI patterns)\n└──────────────┘</code></pre><h2>Prerequisiti</h2>\n<ul>\n<li>Account Synapse + Mind Key</li>\n<li>Server MCP di Synapse configurato in Claude Desktop</li>\n<li>iOS Simulator con <code>screen-remote-agent</code> installato</li>\n<li>Computer registrato in Synapse (veda <a href=\"/docs/api/computers\">Computer Control API</a>)</li>\n</ul>\n<h2>Passo 1: Registri il computer Simulator</h2>\n<p>Sul Mac che esegue l&#39;iOS Simulator:</p>\n<pre><code class=\"hljs language-bash\"><span class=\"hljs-comment\"># Get install code from Synapse</span>\ncurl -X POST https://synapse.schaefer.zone/computers/install-code \\\n  -H <span class=\"hljs-string\">&quot;Authorization: Bearer YOUR_MIND_KEY&quot;</span> \\\n  -d <span class=\"hljs-string\">&#x27;{&quot;computer_name&quot;:&quot;ios-sim&quot;}&#x27;</span>\n<span class=\"hljs-comment\"># → { &quot;install_code&quot;: &quot;ic_...&quot; }</span>\n\n<span class=\"hljs-comment\"># Run screen-remote-agent on the Mac</span>\n<span class=\"hljs-comment\"># (uses the install code to register)</span></code></pre><h2>Passo 2: Memorizzi gli scenari di test in memoria</h2>\n<p>Memorizzi gli scenari di test riutilizzabili come memorie:</p>\n<pre><code class=\"hljs language-python\"><span class=\"hljs-keyword\">import</span> requests\n\n<span class=\"hljs-keyword\">def</span> <span class=\"hljs-title function_\">store_test_scenario</span>(<span class=\"hljs-params\">name, steps, app</span>):\n    requests.post(<span class=\"hljs-string\">f&quot;<span class=\"hljs-subst\">{URL}</span>/memory&quot;</span>,\n        headers={<span class=\"hljs-string\">&quot;Authorization&quot;</span>: <span class=\"hljs-string\">f&quot;Bearer <span class=\"hljs-subst\">{MIND_KEY}</span>&quot;</span>},\n        json={\n            <span class=\"hljs-string\">&quot;category&quot;</span>: <span class=\"hljs-string\">&quot;skill&quot;</span>,\n            <span class=\"hljs-string\">&quot;key&quot;</span>: <span class=\"hljs-string\">f&quot;test_scenario_<span class=\"hljs-subst\">{name}</span>&quot;</span>,\n            <span class=\"hljs-string\">&quot;content&quot;</span>: <span class=\"hljs-string\">f&quot;App: <span class=\"hljs-subst\">{app}</span>\\nSteps:\\n&quot;</span> + <span class=\"hljs-string\">&quot;\\n&quot;</span>.join(steps),\n            <span class=\"hljs-string\">&quot;tags&quot;</span>: [<span class=\"hljs-string\">&quot;test&quot;</span>, <span class=\"hljs-string\">&quot;ios&quot;</span>, app],\n            <span class=\"hljs-string\">&quot;priority&quot;</span>: <span class=\"hljs-string\">&quot;high&quot;</span>\n        })\n\nstore_test_scenario(<span class=\"hljs-string\">&quot;login_flow&quot;</span>, [\n    <span class=\"hljs-string\">&quot;Launch app&quot;</span>,\n    <span class=\"hljs-string\">&quot;Tap email field&quot;</span>,\n    <span class=\"hljs-string\">&quot;Type test@example.com&quot;</span>,\n    <span class=\"hljs-string\">&quot;Tap password field&quot;</span>,\n    <span class=\"hljs-string\">&quot;Type password123&quot;</span>,\n    <span class=\"hljs-string\">&quot;Tap Login button&quot;</span>,\n    <span class=\"hljs-string\">&quot;Verify home screen appears&quot;</span>\n], <span class=\"hljs-string\">&quot;MyApp&quot;</span>)</code></pre><h2>Passo 3: Esecuzione del test guidata da LLM</h2>\n<p>In Claude Desktop (con Synapse MCP configurato):</p>\n<pre><code class=\"hljs language-plaintext\">Run the login_flow test scenario on the iOS Simulator.\nTake a screenshot after each step and verify the expected UI.\nIf any step fails, store the failure as a memory so we can\navoid it next time.</code></pre><p>Claude:</p>\n<ol>\n<li>Chiamerà <code>memory_search</code> per trovare la memoria <code>test_scenario_login_flow</code></li>\n<li>Chiamerà <code>computer_screenshot</code> per vedere lo stato corrente</li>\n<li>Eseguirà ogni passo tramite <code>computer_command_queue</code> (click, type)</li>\n<li>Verificherà i risultati tramite schermate</li>\n<li>Memorizzerà eventuali fallimenti come memorie <code>mistake</code></li>\n</ol>\n<h2>Passo 4: Test self-healing</h2>\n<p>Quando un test fallisce, memorizzi il fallimento e il recupero:</p>\n<pre><code class=\"hljs language-python\"><span class=\"hljs-keyword\">def</span> <span class=\"hljs-title function_\">store_test_failure</span>(<span class=\"hljs-params\">scenario, step, error, recovery</span>):\n    requests.post(<span class=\"hljs-string\">f&quot;<span class=\"hljs-subst\">{URL}</span>/memory&quot;</span>,\n        headers={<span class=\"hljs-string\">&quot;Authorization&quot;</span>: <span class=\"hljs-string\">f&quot;Bearer <span class=\"hljs-subst\">{MIND_KEY}</span>&quot;</span>},\n        json={\n            <span class=\"hljs-string\">&quot;category&quot;</span>: <span class=\"hljs-string\">&quot;mistake&quot;</span>,\n            <span class=\"hljs-string\">&quot;key&quot;</span>: <span class=\"hljs-string\">f&quot;failure_<span class=\"hljs-subst\">{scenario}</span>_<span class=\"hljs-subst\">{step}</span>&quot;</span>,\n            <span class=\"hljs-string\">&quot;content&quot;</span>: <span class=\"hljs-string\">f&quot;Scenario: <span class=\"hljs-subst\">{scenario}</span>\\nStep: <span class=\"hljs-subst\">{step}</span>\\nError: <span class=\"hljs-subst\">{error}</span>\\nRecovery: <span class=\"hljs-subst\">{recovery}</span>&quot;</span>,\n            <span class=\"hljs-string\">&quot;tags&quot;</span>: [<span class=\"hljs-string\">&quot;test&quot;</span>, <span class=\"hljs-string\">&quot;failure&quot;</span>, <span class=\"hljs-string\">&quot;ios&quot;</span>, scenario],\n            <span class=\"hljs-string\">&quot;priority&quot;</span>: <span class=\"hljs-string\">&quot;high&quot;</span>\n        })\n\n<span class=\"hljs-comment\"># Example</span>\nstore_test_failure(<span class=\"hljs-string\">&quot;login_flow&quot;</span>, <span class=\"hljs-string\">&quot;tap_login&quot;</span>,\n    <span class=\"hljs-string\">&quot;Login button not found at expected coordinates&quot;</span>,\n    <span class=\"hljs-string\">&quot;Button moved due to new logo. Search by accessibility label instead.&quot;</span>)</code></pre><p>La prossima volta che l&#39;LLM esegue il test, richiama il fallimento e applica\nil recupero automaticamente.</p>\n<h2>Passo 5: Tracciamento dei risultati dei test</h2>\n<p>Tracci le esecuzioni dei test come attività:</p>\n<pre><code class=\"hljs language-python\"><span class=\"hljs-keyword\">def</span> <span class=\"hljs-title function_\">track_test_run</span>(<span class=\"hljs-params\">scenario, status, duration</span>):\n    requests.post(<span class=\"hljs-string\">f&quot;<span class=\"hljs-subst\">{URL}</span>/mind/task&quot;</span>,\n        headers={<span class=\"hljs-string\">&quot;Authorization&quot;</span>: <span class=\"hljs-string\">f&quot;Bearer <span class=\"hljs-subst\">{MIND_KEY}</span>&quot;</span>,\n                 <span class=\"hljs-string\">&quot;Content-Type&quot;</span>: <span class=\"hljs-string\">&quot;application/json&quot;</span>},\n        json={\n            <span class=\"hljs-string\">&quot;title&quot;</span>: <span class=\"hljs-string\">f&quot;Test: <span class=\"hljs-subst\">{scenario}</span>&quot;</span>,\n            <span class=\"hljs-string\">&quot;description&quot;</span>: <span class=\"hljs-string\">f&quot;Status: <span class=\"hljs-subst\">{status}</span>, Duration: <span class=\"hljs-subst\">{duration}</span>s&quot;</span>,\n            <span class=\"hljs-string\">&quot;priority&quot;</span>: <span class=\"hljs-string\">&quot;normal&quot;</span>\n        })</code></pre><h2>Comandi comuni</h2>\n<table>\n<thead>\n<tr>\n<th>Azione</th>\n<th>Comando</th>\n</tr>\n</thead>\n<tbody><tr>\n<td>Avvia Simulator</td>\n<td><code>xcrun simctl launch booted com.example.app</code></td>\n</tr>\n<tr>\n<td>Schermata</td>\n<td><code>computer_screenshot</code> (tramite Synapse MCP)</td>\n</tr>\n<tr>\n<td>Tap a (x,y)</td>\n<td><code>computer_command_queue {type:&quot;click&quot;, payload:{x,y}}</code></td>\n</tr>\n<tr>\n<td>Digita testo</td>\n<td><code>computer_command_queue {type:&quot;type&quot;, payload:{text:&quot;...&quot;}}</code></td>\n</tr>\n<tr>\n<td>Premi Home</td>\n<td><code>computer_command_queue {type:&quot;key&quot;, payload:{keys:[&quot;Cmd&quot;,&quot;Shift&quot;,&quot;H&quot;]}}</code></td>\n</tr>\n</tbody></table>\n<h2>Best practice</h2>\n<div class=\"callout callout-ok\"></div><h2>Prossimi passi</h2>\n<ul>\n<li><a href=\"/docs/guides/self-healing-tests\">Test self-healing</a></li>\n<li><a href=\"/docs/api/computers\">Computer Control API</a></li>\n<li><a href=\"/docs/guides/memory-best-practices\">Best practice per la memoria</a></li>\n</ul>\n","urls":{"html":"/docs/guides/automated-testing-ios","text":"/docs/guides/automated-testing-ios?format=text","json":"/docs/guides/automated-testing-ios?format=json","llm":"/docs/guides/automated-testing-ios?format=llm"},"translations_available":["en","zh","hi","es","fr","ar","pt","ru","ja","de","it","ko","nl","pl","tr","sv","vi","th","id","uk"]}