Тестирование непредсказуемого: как проверять интерфейс когда поведение AI меняется каждый раз
Основной чат
Чат для вайбкодеров: новости, гайды, поиск исполнителей, маркетплейс и разбор реальных кейсов.
Открываешь интерфейс с AI-ассистентом, задаёшь один и тот же вопрос три раза подряд — получаешь три разных ответа. Где-то модель ответила в одно предложение, где-то развернула три абзаца с маркированным списком, где-то добавила картинку. Кнопка «Регенерировать» иногда возвращает почти то же самое, а иногда — совершенно другой результат, и пользователь не понимает, что произошло.
Это новая реальность тестирования. Раньше QA-инженер мог открыть Jira-таск, повторить шаги, увидеть один и тот же баг и закрыть его. Сейчас «шаги воспроизведения» работают через раз, скриншоты бесполезны через час, а «expected result» приходится формулировать как диапазон, а не как конкретный экран. Классические подходы к тестированию интерфейсов с AI ломаются — и команды либо это игнорируют, либо честно перестраивают процесс.
Почему старые методы тестирования не работают
Классический UI-тест строится на детерминизме. Кликнул сюда — получил то. Один и тот же сценарий даёт один и тот же результат, и любое отклонение — это баг.
С AI всё иначе. Поведение модели зависит от истории диалога, контекста, версии модели, температуры, иногда даже от времени суток (если провайдер балансирует нагрузку). Один и тот же промпт может вернуть JSON в одном случае и markdown — в другом. Кнопка «Применить» иногда видна, а иногда нет — потому что модель решила, что в этом контексте действие не нужно.
Это рушит три привычные опоры:
- Скриншоты как источник правды. Скриншот фиксирует один из возможных исходов, а не «как должно быть».
- Шаги воспроизведения. Баг может проявиться раз на десять, и переоткрыть его сложнее, чем починить.
- Автотесты по тексту. Снапшот-тесты на ответы модели падают на каждом релизе, даже если функционально всё работает.
Что меняется в роли тестировщика
Тестировщик AI-интерфейса всё меньше похож на инспектора и всё больше — на исследователя. Его задача не «убедиться, что экран такой, как в макете», а «понять, как ведёт себя система в диапазоне возможных состояний и где этот диапазон выходит за пределы допустимого».
На ревью это видно сразу: вместо «вот баг, вот скрин» — «вот десять прогонов, в трёх случаях модель проигнорировала системный промпт, вот закономерность».
Сценарий вместо точного исхода
Первое, что приходится перестроить, — формулировка ожидаемого результата. Если писать «ассистент возвращает фразу X», тест будет красным всегда. Если писать «ассистент признаёт, что не знает ответа, и предлагает уточнение» — тест становится осмысленным.
Как формулировать «expected» для AI-фичи
Хорошее ожидание описывает поведение, а не текст:
- Намерение модели — что она должна понять из запроса.
- Тип ответа — рассуждение, действие, отказ, уточняющий вопрос.
- Границы — чего модель не должна делать (раскрывать системный промпт, обещать действия, которые не выполнит, выдавать персональные данные).
- Форма — структурированный JSON, текст для пользователя, вызов инструмента.
Анти-паттерны постановки задачи
- «Должен ответить корректно» — слово «корректно» здесь ничего не значит, под него подходит любой текст.
- «Не должен галлюцинировать» — слишком общо, не проверяется.
- «Должен быть дружелюбным» — субъективно, разные ревьюеры дадут разные вердикты.
Вместо этого: «при запросе про несуществующий заказ модель не должна выдумывать номер, должна предложить проверить почту и переключить на оператора, если пользователь настаивает».
Тестирование диапазоном: прогоны вместо одного клика
Если поведение стохастическое, один прогон ничего не доказывает. Пять успешных прогонов подряд тоже не доказывают, что фича работает, — они показывают, что в пяти случаях из пяти модель попала в нужный диапазон.
Минимальный протокол прогонов
- Запускать один и тот же сценарий не меньше 5–10 раз.
- Фиксировать каждый ответ отдельно, не редактируя и не «приводя к среднему».
- Помечать каждый прогон тегами: «ок», «ок, но странно», «нарушение границ», «фактическая ошибка».
- Сохранять seed, версию модели и системный промпт — иначе через неделю результат невозможно повторить.
Вопросы для ревью прогонов
- В скольких прогонах из десяти модель попала в ожидаемое поведение?
- Какие два-три типа отклонений встречаются чаще всего?
- Есть ли среди отклонений «тихие» — те, что выглядят нормально, но содержат ошибку?
- Что общего у плохих прогонов: длина истории, формулировка пользователя, конкретное слово-триггер?
Короткий итог: тестирование AI-интерфейса — это не «поймать баг», а «описать поведение системы как распределение». Чем раньше команда перестаёт ждать от модели одинаковости и начинает работать с диапазоном, тем быстрее появляются понятные критерии релиза.
Рабочий процесс: от макета до релиза
Когда поведение меняется от прогона к прогону, привычный конвейер «макет → разработка → QA → релиз» перестаёт работать линейно. На каждом этапе нужна петля обратной связи, в которой дизайнер видит реальные ответы модели, а не плейсхолдеры.
Этап 1. Макет с диапазоном состояний
В Figma больше нельзя рисовать один «правильный» экран ассистента. На каждый AI-блок нужно как минимум четыре макета:
- Удачный исход. Модель поняла запрос, ответ помещается в карточку.
- Длинный ответ. Текст вдвое больше расчётного, кнопки внизу.
- Уточняющий вопрос. Модель не уверена и просит детали.
- Отказ или ошибка. Модель не может ответить, инструмент упал, превышен лимит.
Если макет не описывает все четыре — на проде интерфейс рассыплется на одном из них. Чаще всего ломаются именно отказы: их рисуют в последнюю очередь и без согласования копирайта.
Этап 2. Прототип на живой модели
Кликабельный прототип с заранее записанными ответами полезен для презентации, но опасен для проверки гипотез. Он скрывает главное — что модель в реальности отвечает иначе, чем в макете.
Минимум, который стоит делать до передачи в разработку: подключить ту же модель, что пойдёт в прод, и прогнать пять-десять реальных запросов через сырой интерфейс. Часто на этом этапе всплывает, что выбранная карточка слишком узкая, что markdown ломает вёрстку или что модель упорно отвечает не на том языке.
Этап 3. Тестовая среда с фиксированным seed
Разработчику нужно дать возможность воспроизводить хотя бы часть поведения. Для этого в дев-сборке полезно иметь:
- Переключатель «фиксированный seed» — чтобы повторно получить тот же ответ.
- Лог последнего системного промпта и параметров вызова.
- Кнопку «прогнать сценарий N раз» с экспортом результатов.
Без этого QA и дизайнер обсуждают разные баги под одним названием.
Диагностика: как разбирать жалобу «ассистент сломался»
Самая частая формулировка от пользователя и от менеджера — «он отвечает как-то не так». Это не баг-репорт, это симптом. Чтобы превратить его в задачу, нужно пройти по слоям.
Слой 1. Входные данные
- Какой именно запрос отправил пользователь, дословно?
- Какая была история диалога перед этим?
- Какие данные подтянулись из контекста (профиль, документ, RAG)?
Часто оказывается, что «модель тупит» — это «в контекст пришёл устаревший документ» или «история уже не помещается в окно и обрезалась посередине».
Слой 2. Промпт и параметры
- Менялся ли системный промпт за последние дни?
- Какая версия модели стоит сейчас и не было ли тихого апдейта у провайдера?
- Температура, top-p, лимит токенов — те же, что и в макете?
Тихий апдейт модели — отдельный класс багов. Интерфейс не менялся, код не менялся, а поведение поехало. Это нужно проверять первым, а не последним.
Слой 3. Интерфейс вокруг ответа
- Ответ модели на самом деле плохой — или интерфейс плохо его показывает?
- Не режется ли длинный ответ скроллом без индикатора?
- Видит ли пользователь, что ассистент вызвал инструмент, или ему кажется, что система зависла?
В половине случаев «модель отвечает плохо» — это «модель отвечает нормально, но человек не понимает, что произошло».
Типичные ошибки в продуктовой работе с AI
Опираться на демо-сценарий
Все демонстрации собираются на трёх-четырёх «золотых» запросах, на которых модель ведёт себя предсказуемо. Если фича уезжает в релиз только с такой проверкой, на проде она встречается с реальным распределением запросов и разваливается.
Считать промпт «настройкой», а не частью продукта
Системный промпт правят на ходу, без версионирования и без регрессии. Через месяц никто не помнит, почему там абзац про «не упоминай конкурентов» и что сломается, если его убрать. Промпт нужно держать в репозитории и менять через тот же ревью, что и код.
Прятать неуверенность модели
Когда модель не уверена, дизайнеры часто прячут это за бодрой формулировкой. Пользователь получает ровный, уверенный ответ — и принимает его за факт. Честный интерфейс показывает степень уверенности словами или формой: «возможно», «я не нашёл это в документах», вызов инструмента вместо догадки.
Игнорировать «тихие» ошибки
Громкие ошибки — когда модель явно выдала чушь — ловятся быстро. Тихие — когда ответ выглядит правдоподобно, но содержит выдуманный факт — пропускаются и QA, и дизайнером. Отдельная категория ревью должна быть именно про них: «проверь не как выглядит, а правда ли это».
Как дизайнеру встроить это в свой макет
Несколько привычек, которые меняют макет ассистента:
- Рядом с каждым AI-блоком отметить, какие источники данных в него приходят и что произойдёт, если их нет.
- На каждый текстовый ответ заложить состояние «слишком длинный» и «пустой» — не как опцию, а как обязательный фрейм.
- Для каждого действия модели нарисовать состояние ожидания длиннее, чем кажется нужным. Реальные ответы приходят волной, а не мгновенно.
- Описать в комментарии к фрейму границы поведения: о чём ассистент не говорит, что не делает без подтверждения, куда отправляет, если не справился.
Вопросы для ревью макета AI-фичи
- Что увидит пользователь, если модель ответит втрое длиннее ожидаемого?
- Что произойдёт, если ответ придёт через 15 секунд, а не через одну?
- Видно ли пользователю, что система сейчас думает, а не зависла?
- Где в интерфейсе показано, что ассистент чего-то не знает?
- Есть ли путь «позвать человека», когда модель не справляется?
Короткий итог: в продуктовой работе с AI макет перестаёт быть картинкой одного исхода и становится описанием поведения системы в диапазоне. Дизайнер, который держит в голове все ветки — длинный ответ, отказ, тихую ошибку, задержку, — экономит команде недели спора о том, «как должно быть на самом деле».
Продвинутые сценарии: где обычное QA уже не работает
Когда базовые состояния отрисованы, начинается интересное. Простой ассистент-чат прошёл проверку, но в продукте AI редко живёт в одиночку. Он встроен в воронку, у него есть память, инструменты, иногда — несколько моделей под капотом. И именно в этой обвязке прячутся самые дорогие баги.
Сценарий «модель меняет мнение в одной сессии»
Пользователь спрашивает: «можно ли мне взять этот тариф?». Ассистент отвечает «да». Через три сообщения уточняет данные и говорит «нет». Формально обе ответы корректны — просто во втором случае у него больше контекста. Для пользователя это выглядит как враньё.
Что закладывать в макет:
- Видимый якорь: «я изменил ответ, потому что увидел вот это».
- Возможность откатиться к предыдущему ответу и сравнить.
- Запрет на молчаливое противоречие — если ответ инвертируется, это событие, а не строка в потоке.
Сценарий «инструмент сработал, но не до конца»
Ассистент вызвал API, получил частичный результат, дорисовал недостающее текстом. Снаружи всё выглядит как успешный ответ. Внутри — половина данных реальная, половина выдумана.
На ревью полезно проверять:
- Помечен ли в UI источник каждого блока (модель / инструмент / документ)?
- Что показывает интерфейс, если инструмент вернул ошибку, а не пустоту?
- Есть ли разница между «инструмент не нашёл» и «инструмент не вызывался»?
Сценарий «несколько пользователей в одном контексте»
Командные ассистенты — отдельная боль. Один человек попросил «сделай покороче», второй заходит и видит обрезанный ответ, не понимая почему. Память о предпочтениях должна быть либо явной, либо персональной, но не «общей и невидимой».
Как проверять качество, когда нет правильного ответа
Классический QA работает на сравнении с эталоном. С AI эталона нет — есть диапазон допустимого. Это меняет сам способ проверки.
Оценка по рубрикам, а не по «правильно/неправильно»
Вместо «ответ верный» — несколько осей: фактическая точность, полнота, тон, длина, безопасность. Каждая ось оценивается отдельно. Это позволяет увидеть, что ответ «правильный по фактам, но грубый», и не считать его эталонным только потому, что цифры сошлись.
Регрессия на наборе кейсов, а не на одном промпте
В команде стоит держать живой набор из нескольких десятков реальных запросов: типичные, краевые, провокационные, многоязычные, с опечатками. После любого изменения промпта или модели — прогон по всему набору, а не «я проверил, у меня работает».
Слепое сравнение версий
Когда меняется промпт, легко убедить себя, что стало лучше. Способ против самообмана: показать два варианта ответа на один и тот же запрос человеку, который не знает, какой откуда. Если он не отличает или предпочитает старый — улучшения не было.
Чеклист регрессии AI-фичи
- Прогон тестового набора до и после изменения.
- Слепое сравнение хотя бы на 10–20 кейсах.
- Проверка краевых сценариев: пустой запрос, очень длинный, на другом языке, с провокацией.
- Поведение при отказе инструмента и при таймауте.
- Логи: видно ли постфактум, какая версия промпта и модели сгенерировала ответ.
Как объяснить решение команде
Самая частая ошибка дизайнера в AI-проекте — приносить макет и не приносить логику поведения. Разработчик додумывает, продакт додумывает, тестировщик додумывает по-своему. На выходе три разные фичи.
Документ поведения рядом с макетом
Не вместо макета, а параллельно. Короткий текст, который описывает:
- что ассистент делает и чего не делает;
- какие источники использует и в каком порядке;
- как ведёт себя при неуверенности, отказе, таймауте;
- какие действия требуют подтверждения, а какие — нет.
Этот документ живёт в том же месте, что и макет, и обновляется вместе с ним. Если поведение поменялось, а текст не обновлён, это такой же баг, как несовпадение шрифта со стайлгайдом.
Язык, на котором с командой стоит говорить
- «Это поведение по умолчанию» вместо «модель так отвечает».
- «Здесь продукт обязан показать неуверенность» вместо «давайте напишем что-то аккуратное».
- «Этот сценарий мы пока не поддерживаем, и интерфейс честно говорит об этом» вместо «потом доделаем».
Вопросы, которые имеет смысл задавать на ревью
- Если завтра провайдер обновит модель, какие наши экраны сломаются первыми?
- Где в интерфейсе пользователь узнаёт, что ассистент чего-то не знает?
- Какое поведение мы считаем нормой, а какое — инцидентом, и кто это решает?
- Что мы записываем в логи, чтобы через месяц разобрать жалобу?
Короткий итог: качество AI-фичи — это не качество одного ответа, а предсказуемость поведения в диапазоне. Дизайнер, который умеет описать этот диапазон словами и проверить его на наборе кейсов, превращается из «рисующего экраны» в человека, без которого фичу нельзя выпустить.
Финальный чеклист: готова ли AI-фича к выпуску
Это не «всё или ничего», а способ увидеть, где ещё дыры. Если по половине пунктов ответ «не знаю» — выпуск преждевременный.
Поведение
- Описан диапазон допустимых ответов, а не один эталон.
- Определено, что считается отказом, и как он выглядит на экране.
- Решено, какие действия требуют подтверждения, а какие — нет.
- Есть правило для долгих ответов: стриминг, прогресс или честный таймаут.
- Понятно, как ассистент ведёт себя без интернета, без инструмента, без контекста.
Интерфейс
- Сообщение о неуверенности существует как отдельное состояние, а не как обычный ответ серым цветом.
- Источники видны там, где это важно для решения пользователя.
- Есть способ откатить или поправить действие ассистента, если оно затронуло данные.
- Состояние «ассистент думает» отличается от «ассистент завис».
- Пустое состояние объясняет, что вообще можно спросить, а не показывает мигающий курсор.
Проверка
- Живой набор кейсов лежит в репозитории, а не в голове у одного человека.
- Прогон по набору делается до релиза и после смены модели или промпта.
- Есть слепое сравнение версий хотя бы на части кейсов.
- Логируется версия промпта, модели и инструментов, которые отработали.
- Жалоба пользователя восстанавливается по логам за разумное время.
Команда
- Документ поведения лежит рядом с макетом и обновляется вместе с ним.
- Продакт, разработчик и поддержка одинаково отвечают на вопрос «что фича делает, а что нет».
- Договорено, кто принимает решение, когда поведение модели плавает между релизами.
Анти-паттерны, которые встречаются чаще всего
«Мы доверились модели»
Промпт написан, экран нарисован, проверки нет. На демо всё красиво, в продакшене — лотерея. Доверие к модели без рамок — это не доверие, а отсутствие продукта.
«Один идеальный пример в Figma»
Макет показывает ответ длиной ровно в три строки. В жизни ответы бывают в одну строку, в тридцать, с таблицей внутри и с пустотой. Если макет не показывает диапазон, разработчик угадывает вёрстку.
«Загрузка вечная, потому что мы не знаем сколько»
Спиннер без таймаута и без признаков жизни. Пользователь сидит и не понимает, ответ идёт или процесс умер. Любое долгое действие должно иметь верхнюю границу и видимый прогресс.
«Уверенный тон на любую тему»
Ассистент отвечает одинаково бодро на «сколько будет 2+2» и «какой у меня остаток на счёте». Второе он не знает, но звучит так же. Это не дизайн-проблема промпта — это дизайн-проблема интерфейса, который не различает источники уверенности.
«Память, о которой никто не предупредил»
Ассистент помнит прошлый разговор, но пользователь об этом не знает. Через неделю он видит странный ответ и не понимает, откуда взялся контекст. Память должна быть видимой и управляемой, иначе она работает против доверия.
«Тестируем на себе»
Команда из пяти человек гоняет фичу две недели и считает, что проверила. Пять человек не покрывают ни язык, ни опечатки, ни странные домены, ни провокации. Без живого набора кейсов любое «у нас работает» — самообман.
«Эталон от лучшего ответа»
Сняли красивый скрин удачного диалога и используют его как образец. Через месяц модель обновилась, ответы стали другими, скрин уже не воспроизводится — и команда спорит, стало хуже или просто иначе. Эталон должен быть описанием поведения, а не картинкой удачного дня.
Вопросы для ревью дизайна AI-фичи
Эти вопросы стоит задавать не в конце, а на этапе, когда макет ещё можно поменять без боли.
- Где в интерфейсе пользователь видит, что ассистент чего-то не знает или не уверен?
- Что произойдёт, если ответ придёт через 20 секунд вместо двух?
- Какие действия ассистент может совершить без подтверждения, и согласны ли мы с этим списком?
- Если пользователь захочет проверить ассистента, откуда он возьмёт источник?
- Как выглядит экран, когда инструмент вернул ошибку, а не пустоту?
- Что в этом интерфейсе сломается первым, если завтра сменится модель?
- Какое поведение мы считаем нормой, а какое — инцидентом, и кто на него реагирует?
- Через месяц по жалобе пользователя мы поймём, что именно произошло, или будем гадать?
Короткий практический итог
AI-фича не проверяется как обычная кнопка. У неё нет одного правильного ответа — есть диапазон допустимого, и задача дизайна — описать этот диапазон так, чтобы команда и интерфейс одинаково понимали, где он заканчивается.
Три вещи, которые отличают зрелую работу с непредсказуемым поведением от наивной. Первое — поведение описано словами, а не угадывается по макету. Второе — есть живой набор кейсов, по которому фича проверяется до и после каждого изменения, а не «у меня работает». Третье — интерфейс честно показывает границы: неуверенность, источники, отказы, долгое ожидание. Всё остальное — нюансы поверх этих трёх опор.
Дизайнер, который умеет это собрать, перестаёт быть автором экранов и становится автором поведения. А поведение — это то, что пользователь на самом деле запоминает.