Skip to main content

Självläkande testpipelines

Bygg testpipelines som lär sig av fel och anpassar sig automatiskt med Synapse-minne.


Självläkande testpipelines

Traditionella testsviter går sönder när UI ändras. Självläkande tester använder Synapse-minne för att lära sig av tidigare fel och anpassa sig — vilket minskar ostabila tester och underhållsbörda.

Koncept

┌─────────┐  fails   ┌──────────┐  store   ┌──────────┐
│  Test   │ ───────▶ │  Synapse │ ───────▶ │ Memories │
│  Run    │          │  Memory  │          │ (failures)│
└─────────┘          └──────────┘          └──────────┘
                           ▲                     │
                           │   recall            │
                           │  before next run    │
                           └─────────────────────┘
  1. Test körs
  2. Om det misslyckas, lagra felet (vad som gick fel, varför, hur man fixar)
  3. Nästa körning: återkalla relevanta fel innan körning
  4. Tillämpa kända fixar automatiskt

Implementering

Steg 1: Test-omslag

Omslut varje test med minnesåterkallning/lagring:

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"
        })

Steg 2: Adaptiv testlogik

Inuti testet, kontrollera kända fel och tillämpa fixar:

@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)

Steg 3: Återställningsstrategier

Lagra återställningsstrategier som minnen:

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.")

Steg 4: CI-integration

# .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

Steg 5: Instrumentpanel för felanalys

# 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")

Bästa praxis

Vanliga felmönster att lagra

Feltyp Vad som ska lagras
Element hittades inte Selector som provades, sidtillstånd, skärmdump
Timeout Väntetid, vad som väntades på
Assertion misslyckades Förväntat vs faktiskt värde
Nätverksfel URL, statuskod, svarskropp
Nekad behörighet Nödvändig behörighet, aktuell användarroll

Nästa steg