# 자가 치유 테스트 파이프라인 전통적인 테스트 스위트는 UI가 변경되면 깨집니다. 자가 치유 테스트는 Synapse 메모리를 사용하여 과거 실패로부터 학습하고 적응합니다 — 불안정한 테스트와 유지 관리 부담을 줄입니다. ## 개념 ``` ┌─────────┐ fails ┌──────────┐ store ┌──────────┐ │ Test │ ───────▶ │ Synapse │ ───────▶ │ Memories │ │ Run │ │ Memory │ │ (failures)│ └─────────┘ └──────────┘ └──────────┘ ▲ │ │ recall │ │ before next run │ └─────────────────────┘ ``` 1. 테스트 실행 2. 실패하면, 실패 저장 (무엇이 잘못되었는지, 왜, 어떻게 수정하는지) 3. 다음 실행: 실행 전 관련 실패 회상 4. 알려진 수정 자동 적용 ## 구현 ### 1단계: 테스트 래퍼 각 테스트를 메모리 회상/저장으로 래핑: ```python import requests from datetime import datetime URL = "https://synapse.schaefer.zone" MIND_KEY = "mk_..." def self_healing_test(test_name, test_fn): """Decorator: wrap a test with self-healing memory.""" def wrapper(): # 1. Recall past failures for this test past_failures = requests.get( f"{URL}/memory/search?q={test_name}+failure", headers={"Authorization": f"Bearer {MIND_KEY}"} ).json() # 2. Run test with failure context try: test_fn(known_failures=past_failures) except Exception as e: # 3. Store the failure store_failure(test_name, e, traceback.format_exc()) raise return wrapper def store_failure(test_name, error, traceback_str): requests.post(f"{URL}/memory", headers={"Authorization": f"Bearer {MIND_KEY}", "Content-Type": "application/json"}, json={ "category": "mistake", "key": f"test_failure_{test_name}_{datetime.now().isoformat()}", "content": f"Test: {test_name}\nError: {error}\nTrace:\n{traceback_str}", "tags": ["test", "failure", test_name], "priority": "high" }) ``` ### 2단계: 적응형 테스트 로직 테스트 내에서 알려진 실패를 확인하고 수정 적용: ```python @self_healing_test def test_login_page(browser, known_failures=None): browser.goto("https://app.com/login") # Check if we've seen this page change before if known_failures and known_failures.get("results"): for failure in known_failures["results"]: if "button moved" in failure["content"].lower(): # Use accessibility label instead of coordinates browser.click(by_label="Login button") return # Default: use coordinates browser.click(x=150, y=400) ``` ### 3단계: 복구 전략 복구 전략을 메모리로 저장: ```python def store_recovery(failure_type, strategy): requests.post(f"{URL}/memory", headers={"Authorization": f"Bearer {MIND_KEY}", "Content-Type": "application/json"}, json={ "category": "skill", "key": f"recovery_{failure_type}", "content": strategy, "tags": ["test", "recovery", failure_type], "priority": "high" }) # Store recoveries for common failures store_recovery("element_not_found", "When element not found by ID, try by CSS class, then by XPath, " "then by accessibility label. Take screenshot for debugging.") store_recovery("timeout", "Increase timeout to 30s. If still fails, check if page is loading " "dynamically — wait for specific element instead of fixed time.") store_recovery("stale_element", "Re-find element before each interaction. Don't cache element references " "across page transitions.") ``` ### 4단계: CI 통합 ```yaml # .gitlab-ci.yml test:self-healing: script: - export SYNAPSE_MIND_KEY=$SYNAPSE_TEST_MIND_KEY - pytest tests/ --self-healing after_script: # Summarize new failures - python scripts/synapse_failure_summary.py ``` ### 5단계: 실패 분석 대시보드 ```python # Get all test failures from the last week r = requests.get( f"{URL}/memory/search?q=test+failure", headers={"Authorization": f"Bearer {MIND_KEY}"} ) # Group by test name failures = {} for mem in r.json().get("results", []): test_name = extract_test_name(mem["content"]) failures.setdefault(test_name, []).append(mem) # Report for test, fails in sorted(failures.items(), key=lambda x: -len(x[1])): print(f"{test}: {len(fails)} failures") ``` ## 모범 사례 > [!TIP] > - **트레이스백 저장** — 실패한 정확한 줄을 포함 > - **테스트 이름으로 태그** — 빠른 필터링 가능 > - **`mistake` 카테고리 사용** — 일반 메모리와 분리 > - **`high` 우선순위 설정** — 실패는 절대 잊지 않아야 함 > - **주기적 정리** — 해결된 문제의 메모리 삭제 > - **민감한 데이터 저장 금지** — 자격 증명, PII ## 저장할 일반적인 실패 패턴 | 실패 유형 | 저장할 내용 | |--------------|---------------| | 요소를 찾을 수 없음 | 시도한 셀렉터, 페이지 상태, 스크린샷 | | 시간 초과 | 대기 시간, 무엇을 기다리고 있었는지 | | 어설션 실패 | 예상 값 vs 실제 값 | | 네트워크 오류 | URL, 상태 코드, 응답 본문 | | 권한 거부 | 필요한 권한, 현재 사용자 역할 | ## 다음 단계 - [자동화된 iOS 테스트](/docs/guides/automated-testing-ios) - [메모리 모범 사례](/docs/guides/memory-best-practices) - [오류 복구 Cookbook](/docs/llm-cookbook/error-recovery)