Modern QA2026Стратегии самовосстановления для агентно-управляемых тестов
Join

Course01 Agent Skills for Browser Automation

Cutting-edge · Chapter 01

Стратегии самовосстановления для агентно-управляемых тестов

Updated Jul 2026

Что означает «самовосстановление»

Традиционное самовосстановление (testRigor, Mabl и т.д.): Когда селектор ломается, инструмент автоматически находит альтернативу с помощью эвристик (визуальная позиция, текстовое содержимое, соседние элементы).

Агентно-управляемое самовосстановление: Когда селектор ломается, ИИ-агент рассуждает о сбое и решает, как восстановиться. Это принципиально более гибко, потому что агент может понимать контекст, а не просто применять правила.

Три уровня восстановления

Уровень 1: Автоматический повтор с альтернативными селекторами

Когда основной селектор не срабатывает, агент пробует альтернативы:

Agent: Bash("vibe-check click '#submit-btn'")
→ Error: timeout waiting for '#submit-btn'

Agent thinking: "The submit button selector failed. Let me find what buttons
exist on the page."

Agent: Bash("vibe-check find-all 'button' --json")
→ [
    {"tag": "button", "text": "Cancel", "selector": "button:nth-of-type(1)"},
    {"tag": "button", "text": "Submit Form", "selector": "button:nth-of-type(2)"},
    {"tag": "button", "text": "Save Draft", "selector": "button:nth-of-type(3)"}
  ]

Agent thinking: "I see a button with text 'Submit Form'. That's likely the
submit button with a changed ID. Let me try clicking it."

Agent: Bash("vibe-check click 'button:nth-of-type(2)'")
→ Success

Стоимость токенов: ~500 токенов на восстановление (find-all + рассуждение + повтор) Процент успеха: ~80% для простых изменений селекторов

Уровень 2: Анализ страницы с текстом и скриншотами

Когда Уровень 1 не срабатывает, агент проводит более глубокий анализ:

Agent: Bash("vibe-check find-all 'button'")
→ No buttons found (the page didn't load correctly)

Agent: Bash("vibe-check screenshot -o debug.png")
Agent: Bash("vibe-check text")
→ "Loading... Please wait"

Agent thinking: "The page is still loading. There's a loading state I need
to wait for."

Agent: Bash("vibe-check wait '.loading' --state hidden --timeout 60000")
Agent: Bash("vibe-check click '#submit-btn'")
→ Success

Стоимость токенов: ~800 токенов Процент успеха: ~90% (ловит проблемы с таймингом, состояния загрузки, перенаправления)

Уровень 3: Резерв MCP для семантического анализа

Когда структура страницы принципиально изменилась:

Agent: "CLI-based recovery hasn't worked. Let me use MCP for semantic analysis."

Agent: browser_snapshot()  # MCP tool - returns accessibility tree
→ [role="form" name="Contact Form"]
    [role="textbox" name="Your email"]
    [role="textbox" name="Your message"]
    [role="button" name="Send message"]

Agent thinking: "The form has been completely redesigned. The submit button
is now called 'Send message' and uses different HTML structure. Let me
update my approach."

Agent: Bash("vibe-check click '[aria-label=\"Send message\"]'")
→ Success

Стоимость токенов: ~5 500 токенов (дорого, но необходимо) Процент успеха: ~95% (справляется с крупными редизайнами)

Матрица стратегий восстановления

Тип сбоя Обнаружение Восстановление Стоимость
Изменён ID/класс Тайм-аут селектора Поиск по текстовому содержимому Низкая
Элемент перемещён Селектор нашёл неправильный элемент Поиск по контексту/позиции Низкая
Страница реструктурирована Несколько селекторов не работают Анализ скриншота + текста Средняя
Проблема загрузки Элемент ещё не появился Ожидание завершения загрузки Низкая
Модальное окно/оверлей блокирует Ошибка «Obscured by» Сначала закрыть оверлей Низкая
Полный редизайн Все подходы не работают Семантический анализ MCP Высокая
Истекла аутентификация Перенаправление на страницу входа Повторная аутентификация Средняя

Реализация самовосстановления в вашем фреймворке

Функция-обёртка

# smart_click: Click with self-healing
smart_click() {
  local primary_selector="$1"
  local expected_text="${2:-}"  # Optional: what the element should say

  # Attempt 1: Primary selector
  if vibe-check click "$primary_selector" 2>/dev/null; then
    return 0
  fi

  echo "[heal] Primary selector failed: $primary_selector"

  # Attempt 2: Find by text content
  if [ -n "$expected_text" ]; then
    local alt_selector=$(vibe-check find-all "button, a, [role=button]" --json 2>/dev/null | \
      python3 -c "
import json, sys
for el in json.load(sys.stdin):
    if '$expected_text'.lower() in el.get('text', '').lower():
        print(el['selector'])
        break
")
    if [ -n "$alt_selector" ] && vibe-check click "$alt_selector" 2>/dev/null; then
      echo "[heal] Recovered using text match: $alt_selector"
      return 0
    fi
  fi

  # Attempt 3: Screenshot for debugging
  vibe-check screenshot -o "heal_debug_$(date +%s).png" 2>/dev/null

  echo "[heal] All recovery attempts failed for: $primary_selector"
  return 1
}

# Usage:
smart_click "#submit-btn" "Submit"
smart_click ".login-button" "Log in"

Нативный подход через агента

Вместо скриптования логики восстановления позвольте агенту справляться с этим естественным образом:

# Test definition with recovery hints
test: Submit contact form
steps:
  - Fill in the contact form
  - Click the submit button
recovery_hints:
  submit_button:
    primary: "#submit-btn"
    fallbacks:
      - "button[type=submit]"
      - "button:has-text('Submit')"
      - "button:has-text('Send')"
    semantic: "The button that submits the form"

Агент читает подсказки восстановления и использует их, если основной селектор не срабатывает.

Самовосстановление vs нестабильные тесты

В чём разница?

Нестабильный тест: Сам тест ненадёжен (состояния гонки, проблемы с таймингом, внешние зависимости). Самовосстановление не исправляет это — оно маскирует проблему.

Сломанный селектор: Приложение изменилось, селектор теста устарел. Самовосстановление действительно исправляет это.

Как отличить

Признак Нестабильный тест Сломанный селектор
Сбоит периодически Да Нет (стабильный сбой)
Тот же селектор иногда работает Да Нет
UI визуально не изменился Да Нет (UI обновлён)
Сообщение об ошибке Тайм-аут (элемент есть, но время варьируется) Не найден (элемент действительно отсутствует)

Правило

Самовосстановление должно исправлять сломанные селекторы, а не маскировать нестабильные тесты. Если тест нуждается в восстановлении при каждом запуске, это нестабильный тест, который нужно исправить в корне.

Отслеживание событий самовосстановления

Логируйте каждое событие восстановления для анализа:

{
  "timestamp": "2026-02-09T14:23:05Z",
  "test": "login_valid",
  "step": 4,
  "primary_selector": "#submit-btn",
  "healed_selector": "button:has-text('Sign in')",
  "healing_level": 1,
  "healing_cost_tokens": 450,
  "reason": "ID changed from 'submit-btn' to 'sign-in-btn'"
}

Еженедельный анализ логов восстановления:

  • Высокая частота восстановлений в одном тесте — Обновите селекторы теста
  • Высокая частота восстановлений по всем тестам — Произошёл крупный рефакторинг UI, обновите набор тестов
  • Восстановление всегда на Уровне 3 — Ваши селекторы слишком хрупкие, используйте более устойчивые стратегии

Иерархия устойчивости селекторов

От наиболее к наименее устойчивым:

Стратегия Пример Устойчивость Читаемость
data-testid [data-testid="submit"] Наивысшая Высокая
ARIA-метка [aria-label="Submit form"] Высокая Высокая
Роль + текст button:has-text("Submit") Высокая Высокая
Семантический HTML form button[type=submit] Средняя Средняя
Имя класса .btn-submit Средняя Средняя
ID #submit-btn Средняя Высокая
CSS-путь div > form > div:nth-child(3) > button Наименьшая Наименьшая

Рекомендация для ИИ-управляемых тестов: Используйте атрибуты data-testid где возможно (требует сотрудничества с разработчиками). При отсутствии — используйте ARIA-метки или селекторы роль+текст.

Тезис для собеседования

«Наш подход к самовосстановлению имеет три уровня. Первый: когда селектор не срабатывает, агент ищет альтернативные элементы по текстовому содержимому — это решает 80% случаев при стоимости ~500 токенов. Второй: агент делает скриншот и читает текст страницы для понимания текущего состояния — ловит проблемы с загрузкой и перенаправления. Третий: как резерв мы используем дерево доступности MCP для семантического анализа при кардинальном изменении дизайна страницы. Ключевой вывод в том, что самовосстановление ИИ-агента качественно отличается от традиционного восстановления на основе правил: агент может рассуждать о контексте, понимать сообщения об ошибках и принимать взвешенные решения. Но мы тщательно отслеживаем события восстановления — если тест нуждается в восстановлении при каждом запуске, это нестабильный тест, который нужно исправить, а не допустимый сценарий восстановления.»