Спектр детерминизма
Updated Jul 2026
Центральное противоречие
Главная сила агентного тестирования (адаптивность) одновременно является его главной слабостью (недетерминированность). Тест, который идёт разным путём при каждом запуске, мощен для исследования, но бесполезен как шлюз CI. Понимание того, где ваши тесты находятся на спектре детерминизма, критически важно для выбора правильного подхода.
Спектр
FULLY DETERMINISTIC <---------------------------------------> FULLY AUTONOMOUS
(pytest scripts) (free-roaming agent)
|-- Recorded tests |-- Parameterized |-- Constrained |-- Exploratory
| (fixed steps, | agents | agents | agents
| fixed data) | (fixed objective, | (fixed objective, | (no objective,
| | agent picks path) | bounded steps) | find anything)
| | | |
| REGRESSION | TARGETED | SMOKE/SANITY | DISCOVERY
| Best for CI | Best for staging | Best for deploy | Best for sprint
| gates | environments | verification | exploration
Уровень 1: Полностью детерминированные (записанные тесты)
# Traditional test: every step is predetermined
def test_login():
driver.navigate("https://app.example.com/login")
driver.type("#email", "test@test.com")
driver.type("#password", "password123")
driver.click("#submit")
assert driver.url == "https://app.example.com/dashboard"
Свойства: Одинаковый ввод, одинаковый путь, одинаковый результат каждый раз. Используйте для: Шлюзов CI, регрессионного тестирования, проверки возможности деплоя. Ограничение: Ломается при изменении UI. Нет адаптивности.
Уровень 2: Параметризованные агенты
# Agent has a fixed objective but chooses its own path
def test_login_agent():
agent = TestAgent(objective="Log in with test@test.com / password123")
result = agent.run(max_steps=15)
assert result.final_url == "https://app.example.com/dashboard"
Свойства: Одинаковая цель, потенциально разный путь, одинаковый ожидаемый результат. Используйте для: Тестов staging, самовосстанавливающихся регрессионных тестов. Ограничение: Может выбирать разные пути с разными характеристиками производительности.
Уровень 3: Ограниченные агенты
# Agent has a bounded scope but explores within it
def test_checkout_smoke():
agent = TestAgent(
objective="Complete a checkout with any valid product",
config=HarnessConfig(max_steps=20, timeout_seconds=120)
)
result = agent.run()
assert result.status == "pass"
assert "order confirmation" in result.final_observation.lower()
Свойства: Ограниченное исследование с целью. Разные пути, разные продукты. Используйте для: Верификации деплоя, smoke-тестов, проверок работоспособности. Ограничение: Недетерминированные результаты усложняют отладку.
Уровень 4: Полностью автономные (исследовательские агенты)
# Agent explores freely, looking for anything interesting
def test_explore_app():
agent = ExploratoryAgent(
starting_url="https://app.example.com",
config=HarnessConfig(max_steps=100, timeout_seconds=600)
)
findings = agent.explore()
assert len(findings.critical_issues) == 0
Свойства: Нет предопределённого пути. Агент обнаруживает проблемы автономно. Используйте для: Исследования в спринте, аудитов безопасности, обнаружения непротестированных состояний. Ограничение: Полностью недетерминированные. Не могут быть шлюзом CI.
Матрица ценности
| Сценарий | Ценность автономного агента | Риск недетерминированности | Рекомендация |
|---|---|---|---|
| Исследовательское тестирование нового UI | Высокая | Средний | Использовать как дополнение, не как шлюз |
| Регрессионное тестирование известных потоков | Низкая | Высокий | Используйте детерминированные скрипты |
| API-фаззинг | Высокая | Низкий (фаззинг стохастичен) | Агентный фаззинг идеален |
| Обнаружение нестабильных тестов | Высокая | Низкий (обнаружение детерминировано) | Сильный сценарий использования |
| Визуальная регрессия | Средняя | Средний (модель зрения варьируется) | Пиксельный diff + наложение агента |
| Кроссбраузерное тестирование | Средняя | Низкий | Хорошо с ограниченной обвязкой |
Как сделать агентов достаточно детерминированными для CI
Если вы хотите использовать агентов в CI-пайплайнах, где недетерминированность ломает сборки, применяйте эти техники:
Техника 1: Фиксация seed
# Deterministic model output via temperature=0 and fixed seed
response = client.chat.completions.create(
model="gpt-4o",
messages=messages,
temperature=0,
seed=42 # Fixed seed for reproducibility
)
Ограничение: Даже с temperature=0 и фиксированным seed, выводы LLM не гарантированно идентичны между версиями API или обновлениями модели.
Техника 2: Кэширование решений агента
class DeterministicAgent:
"""Replays cached decisions for reproducibility."""
def __init__(self, cache_path: str):
self.cache = self.load_cache(cache_path)
self.step = 0
def next_action(self):
if self.step in self.cache:
action = self.cache[self.step] # Replay cached decision
else:
action = self.llm.decide() # Generate new decision
self.cache[self.step] = action # Record for next run
self.step += 1
return action
def save_cache(self):
"""Save decisions for future deterministic replays."""
with open(self.cache_path, "w") as f:
json.dump(self.cache, f)
Как это работает: При первом запуске агент генерирует решения и кэширует их. При последующих запусках он воспроизводит кэшированные решения точно. Если страница изменилась и кэшированное решение стало невалидным, кэш инвалидируется и генерируется новое решение.
Техника 3: Утверждения о результатах, а не о путях
# BAD: asserts the exact sequence of agent actions
assert agent.history == [
"navigate /login",
"type email test@test.com",
"type password secret",
"click submit"
]
# GOOD: asserts the final state regardless of how the agent got there
assert agent.browser.url == "https://app.example.com/dashboard"
assert "Welcome" in agent.browser.text("h1")
Это наиболее практичная техника. Агент может выбрать разный путь при каждом запуске, но тест проходит, пока конечное состояние правильное.
Выбор позиции на спектре
| Ваша потребность | Позиция на спектре | Реализация |
|---|---|---|
| Шлюз CI (должен проходить каждый раз) | Левая (детерминированная) | Записанные скрипты или кэшированные агенты |
| Валидация staging (в основном проходит) | Лево-центральная (параметризованная) | Агенты с фиксированными целями, утверждения о результатах |
| Верификация деплоя (быстрая проверка) | Центральная (ограниченная) | Агенты с ограниченными шагами, широкие цели |
| Исследовательское тестирование (поиск проблем) | Правая (автономная) | Неограниченные агенты, отчёты на основе находок |
Ключевой вывод
Не существует единственной «правильной» позиции на спектре детерминизма. Шлюзам CI нужны детерминированные тесты. Исследовательскому тестированию нужны автономные агенты. Искусство заключается в выборе правильной позиции для каждой категории тестов и применении соответствующих техник (фиксация seed, кэширование решений, утверждения о результатах) для достижения нужного уровня воспроизводимости.