Для начала тесты у меня в большей степени выполняют функцию заполнения логов, т.е. реально основная сложная диагностика делается по логам. Для этого они весьма насыщены аналитикой и машинно-читаемы, как база данных. Это сделано для ad-hoc скриптов агентов, которыми они обожают ковыряться в логах. Когда я говорю, что как Kun Chen могу отключить тесты и ничего не произойдёт, то это действительно так — и даже доказывать бенчмарком это не нужно. Просто для агента ничего не изменится: он найдёт новый способ, как запустить код для заполнения логов, обычно создаёт себе MCP или CLI. Фактически коллеги, которые панически топят за тесты, практически сразу же для меня показывают, что они дилетанты в организации логов — иначе причина, почему отключение тестов не влияет, была бы им довольно очевидна.
Однако тесты я нахожу полезными для «доказательного тестирования», как в подходах у авиаторов и медиков.
Когда агент в стадии Architect, он анализирует новые требования, классифицирует их, а потом делает запросы на формулирование «инвариантов» на код. Кодирующий агент по факту получает «бремя доказательства», что такой-то элемент спецификации работает. Это бремя доказательства с одной стороны сразу определяет форматы возврата разных данных, но с другой стороны требует сделать формальную проверку относительно пункта запроса. Важный момент: часто записать доказательство может только специальная «роль». Далее тест на деле делает вызов алгоритма для заполнения логов. Однако в ходе этого процесса сработали не только простые trace-проверки, но в лог попали «доказательства» — их как раз тест и проверяет.
Это выглядит в самих тестах очень лаконично, т.к. код верификации реально слился с самим кодом реализации в единое целое.
def test_set_params_changes_state_and_leaves_evidence(configured, trace):
# 1. Вызываем инструмент MCP
response = call("tools/call", {"name": "set_params", "arguments": {"a": 2.0}})
# 2. Проверяем бизнес-логику (стандартный ассерт)
assert response["result"]["isError"] is False
assert state.current()["a"] == 2.0
# 3. ГЛАВНОЕ: Проверяем доказательство в журнале
assert verdict(trace(), "spec.mcp.tools")["signal"] == "ok"
На мой взгляд, это эффективнее традиционных подходов, т.к. не даёт дрейфовать агентам от требований — все требования покрываются доказательствами. Также тестирование воспринимается агентами через призму «бремени доказательства».
Мы постепенно переходим к ситуации, когда основной проблемой будет совсем не фикс багов, а приёмка приложения от ИИ, где нужно убедиться, что не просто «прошло тесты», а что всё, что просил заказчик через RFC, change requests и т.п., определённо сделано — причём не просто сделано, а ИИ доказал, что это всё работает по каждому отдельному пункту. Причём все такие доказательства сразу видны в логе.
Отмечу, что такой подход требует очень зрелого пайплайна и точно такое вам сами агенты не соберут, ими нужно руководить.