خطوط اختبار ذاتية الإصلاح
ابنِ خطوط اختبار تتعلّم من الإخفاقات وتتكيف تلقائيًا باستخدام ذاكرة Synapse.
خطوط اختبار ذاتية الإصلاح
تنكسر مجموعات الاختبار التقليدية عند تغير الواجهة. تستخدم اختبارات الإصلاح الذاتي ذاكرة Synapse للتعلّم من الإخفاقات السابقة والتكيف — مما يقلل الاختبارات المتذبذبة والعبء الصياني.
المفهوم
┌─────────┐ fails ┌──────────┐ store ┌──────────┐
│ Test │ ───────▶ │ Synapse │ ───────▶ │ Memories │
│ Run │ │ Memory │ │ (failures)│
└─────────┘ └──────────┘ └──────────┘
▲ │
│ recall │
│ before next run │
└─────────────────────┘- يُشغّل الاختبار
- إذا فشل، خزّن الفشل (ما الخطأ، لماذا، كيف الإصلاح)
- التشغيل التالي: استدعِ الإخفاقات ذات الصلة قبل التنفيذ
- طبّق الإصلاحات المعروفة تلقائيًا
التنفيذ
الخطوة 1: غلاف الاختبار
غلّف كل اختبار باستدعاء ذاكرة/تخزين:
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. استدعِ الإخفاقات السابقة لهذا الاختبار
past_failures = requests.get(
f"{URL}/memory/search?q={test_name}+failure",
headers={"Authorization": f"Bearer {MIND_KEY}"}
).json()
# 2. شغّل الاختبار بسياق الإخفاق
try:
test_fn(known_failures=past_failures)
except Exception as e:
# 3. خزّن الفشل
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: منطق اختبار تكيّفي
داخل الاختبار، تحقق من الإخفاقات المعروفة وطبّق الإصلاحات:
@self_healing_test
def test_login_page(browser, known_failures=None):
browser.goto("https://app.com/login")
# تحقق إذا كنا رأينا تغير هذه الصفحة من قبل
if known_failures and known_failures.get("results"):
for failure in known_failures["results"]:
if "button moved" in failure["content"].lower():
# استخدم تسمية الوصول بدلًا من الإحداثيات
browser.click(by_label="Login button")
return
# افتراضي: استخدم الإحداثيات
browser.click(x=150, y=400)الخطوة 3: استراتيجيات التعافي
خزّن استراتيجيات التعافي كذكريات:
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_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
# .gitlab-ci.yml
test:self-healing:
script:
- export SYNAPSE_MIND_KEY=$SYNAPSE_TEST_MIND_KEY
- pytest tests/ --self-healing
after_script:
# لخّص الإخفاقات الجديدة
- python scripts/synapse_failure_summary.pyالخطوة 5: لوحة تحليل الإخفاقات
# احصل على جميع إخفاقات الاختبار من الأسبوع الماضي
r = requests.get(
f"{URL}/memory/search?q=test+failure",
headers={"Authorization": f"Bearer {MIND_KEY}"}
)
# جمّع حسب اسم الاختبار
failures = {}
for mem in r.json().get("results", []):
test_name = extract_test_name(mem["content"])
failures.setdefault(test_name, []).append(mem)
# التقرير
for test, fails in sorted(failures.items(), key=lambda x: -len(x[1])):
print(f"{test}: {len(fails)} failures")أفضل الممارسات
أنماط إخفاق شائعة للتخزين
| نوع الإخفاق | ما يجب تخزينه |
|---|---|
| عنصر غير موجود | المُحدِّد المُجرَّب، حالة الصفحة، لقطة شاشة |
| انتهاء المهلة | وقت الانتظار، ما كان يُنتظر |
| فشل التأكيد | القيمة المتوقعة مقابل الفعلية |
| خطأ شبكة | عنوان URL، رمز الحالة، نص الاستجابة |
| رفض الإذن | الإذن المطلوب، دور المستخدم الحالي |