Modern QA2026Маппинг ReAct на команды Vibe-Check
Join

Course03 Agentic Testing Architectures

Cutting-edge · Chapter 03

Маппинг ReAct на команды Vibe-Check

Updated Jul 2026

Связь теории и практики

Паттерн ReAct абстрактен: наблюдение, размышление, действие, оценка. Чтобы сделать его конкретным, нужно отобразить каждую фазу на реальные команды, которые ИИ-агент может выполнять. CLI vibe-check предоставляет именно такие команды, что делает его практической реализацией цикла ReAct для браузерного тестирования.

Отображение фаз на команды

Фаза ReAct Активность тестирования Команды Vibe-Check
Observe Чтение текущего состояния страницы vibe-check text "body", vibe-check url, vibe-check screenshot, vibe-check find-all "selector"
Think Решение, что тестировать на основе наблюдения Агент рассуждает внутренне (нет команды -- вывод LLM)
Act Выполнение тестового действия vibe-check type "selector" "text", vibe-check click "selector", vibe-check navigate "url"
Evaluate Проверка результата относительно ожиданий vibe-check text ".error", vibe-check url, vibe-check find "selector"

Команды наблюдения подробно

Фаза наблюдения заключается в сборе состояния. Разные команды раскрывают разные аспекты:

# Get the full visible text of the page (for content analysis)
vibe-check text "body"

# Get text from a specific element (for targeted checks)
vibe-check text ".notification-banner"

# Get the current URL (for navigation verification)
vibe-check url

# Take a screenshot (for visual state capture)
vibe-check screenshot -o current-state.png

# Find all elements matching a selector (for structural analysis)
vibe-check find-all "button"

# Get HTML of a section (for deep structural analysis)
vibe-check html

# Evaluate JavaScript (for dynamic state)
vibe-check eval "document.querySelectorAll('.error').length"

Команды действия подробно

# Navigation
vibe-check navigate "https://app.example.com/login"

# Form interaction
vibe-check type "input[name=email]" "user@test.com"
vibe-check type "input[name=password]" "secret123"
vibe-check select "#country" "United States"

# Clicking
vibe-check click "button[type=submit]"
vibe-check click "#menu-toggle"

# Keyboard
vibe-check keys "Enter"
vibe-check keys "Ctrl+a"

# Scrolling
vibe-check scroll down
vibe-check scroll "footer"

# Hovering
vibe-check hover ".dropdown-trigger"

# Waiting
vibe-check wait "#loading-spinner" --state=hidden
vibe-check wait ".content" --state=visible

Полный тест ReAct с использованием Vibe-Check

Вот как агент проходит через тест входа, используя цикл ReAct и команды vibe-check:

TEST OBJECTIVE: Verify that submitting the login form with empty fields
shows appropriate validation errors.

STEP 1 — OBSERVE:
  $ vibe-check navigate "https://app.example.com/login"
  $ vibe-check text "body"
  → "Login to Your Account | Email | Password | Sign In | Forgot Password?"

STEP 2 — THINK:
  "I see a login form with email and password fields and a Sign In button.
   My objective is to test empty field submission. I should click Sign In
   without filling in any fields."

STEP 3 — ACT:
  $ vibe-check click "button:has-text('Sign In')"

STEP 4 — OBSERVE:
  $ vibe-check text ".error-message"
  → "Email is required"
  $ vibe-check find-all ".field-error"
  → [
       { "selector": "#email-error", "text": "Email is required" },
       { "selector": "#password-error", "text": "Password is required" }
     ]

STEP 5 — THINK:
  "Two validation errors appeared: one for email and one for password.
   Both say the field is required. This matches expected behavior.
   Let me also verify we stayed on the login page (no navigation)."

STEP 6 — OBSERVE:
  $ vibe-check url
  → "https://app.example.com/login"

STEP 7 — THINK:
  "URL has not changed. We are still on the login page. Both required
   field errors are shown. Test objective is met."

STEP 8 — EVALUATE:
  DONE pass "Empty form submission correctly shows validation errors
  for both email ('Email is required') and password ('Password is required').
  Page did not navigate away from /login."

Реализация агента на Python

import subprocess
import json

class VibeCheckReActAgent:
    """A ReAct test agent using vibe-check CLI commands."""

    def __init__(self, llm, max_steps=15):
        self.llm = llm
        self.max_steps = max_steps
        self.history = []

    def vibe(self, command: str) -> str:
        """Execute a vibe-check command and return output."""
        result = subprocess.run(
            f"vibe-check {command}",
            shell=True, capture_output=True, text=True, timeout=30
        )
        if result.returncode != 0:
            return f"ERROR: {result.stderr.strip()}"
        return result.stdout.strip()

    def observe(self) -> dict:
        """Gather current page state using vibe-check commands."""
        return {
            "url": self.vibe("url"),
            "text": self.vibe('text "body"')[:2000],
            "title": self.vibe("title"),
            "errors": self.vibe('eval "document.querySelectorAll(\'.error\').length"'),
        }

    def run(self, objective: str) -> dict:
        """Execute a test using the ReAct loop."""
        for step in range(self.max_steps):
            # OBSERVE
            state = self.observe()

            # THINK + decide
            prompt = f"""
            You are a QA test agent. Your objective: {objective}

            Current state:
            - URL: {state['url']}
            - Page text (first 2000 chars): {state['text']}
            - Error count: {state['errors']}

            History (last 5 actions):
            {json.dumps(self.history[-5:], indent=2)}

            Respond with exactly ONE action:
            VIBE <command>  — execute a vibe-check command
            PASS <reason>   — test passed, explain why
            FAIL <reason>   — test failed, explain why
            """

            response = self.llm.generate(prompt).strip()
            self.history.append({"step": step, "state_url": state["url"], "action": response})

            # ACT or EVALUATE
            if response.startswith("VIBE "):
                command = response[5:]
                output = self.vibe(command)
                self.history[-1]["output"] = output
            elif response.startswith("PASS "):
                return {"status": "pass", "reason": response[5:], "steps": step + 1}
            elif response.startswith("FAIL "):
                return {"status": "fail", "reason": response[5:], "steps": step + 1}

        return {"status": "timeout", "reason": f"Exceeded {self.max_steps} steps", "steps": self.max_steps}

Паттерны восстановления после ошибок

Один из самых мощных аспектов маппинга ReAct на vibe-check -- способность агента восстанавливаться после ошибок:

Восстановление при отсутствии селектора

Agent tries: vibe-check click "#submit-btn"
Output: ERROR: No element found for selector '#submit-btn'

Agent observes: vibe-check find-all "button"
Output: [
  {"selector": "button.primary-action", "text": "Submit"},
  {"selector": "button.cancel", "text": "Cancel"}
]

Agent reasons: "The submit button exists but has a different selector.
              I should use 'button.primary-action' instead."

Agent acts: vibe-check click "button.primary-action"
Output: success

Восстановление при неожиданном состоянии

Agent tries: vibe-check click "#checkout-btn"
Output: success

Agent observes: vibe-check text "body"
Output: "Your session has expired. Please log in again."

Agent reasons: "Session expired during checkout. This is an environment
              issue. I need to log in again before continuing the test."

Agent acts:
  vibe-check type "#email" "test@example.com"
  vibe-check type "#password" "password123"
  vibe-check click "#login-btn"
  // Then retries the checkout

Соображения производительности

Метрика Агент Vibe-Check Прямой скрипт Playwright
Шагов на тест 8-20 Фиксировано (известно при написании)
Время на шаг (LLM) 200-500 мс 0 мс (нет рассуждений)
Время на шаг (браузер) 100-300 мс 100-300 мс
Общее время теста 5-15 секунд 1-3 секунды
Адаптивность Высокая Нулевая
Сложность отладки Средняя (трассировка истории) Низкая (линейный скрипт)

Ключевой вывод

CLI vibe-check обеспечивает естественное отображение абстрактного паттерна ReAct на конкретные команды браузерной автоматизации. Каждая фаза ReAct имеет соответствующие команды vibe-check: наблюдение через text/url/find-all/screenshot, действие через click/type/navigate и оценка через проверки с помощью text и url, подобные утверждениям. Это отображение превращает теоретический цикл ReAct в практичного, реализуемого тестового агента.