Ответ 200, а денег нет. Что не покажут ни Postman, ни нейросеть

Скриншоты дальше из программы, в которой я делаю сверку ответов с документацией и логами. Говорю сразу, чтобы никто не искал подвох. Дальше по делу.
Двести это не значит хорошо
Заказ A-17, две позиции по 450 рублей. Сервис ответил успехом.

Тут три ошибки, и ни одну из них не видно глазами.
Итог посчитан как 800, хотя две позиции по 450 дают 900. Цифра правдоподобная, поэтому она проходит любой просмотр. Статус стоит NEW, хотя оплата прошла и он обязан быть PAID, и клиент покажет человеку «ожидает оплаты» по оплаченному заказу. И в ответе лежит поле debug со значением true, которого нет ни в какой документации. Сегодня это безобидный флаг из отладочной ветки, завтра на его месте окажется внутренний идентификатор пользователя или кусок стектрейса, и это уже разговор с безопасностью.
Такой ответ уходит в приёмку зелёным. Через день приходит менеджер и спрашивает, почему нет денег.
Postman показывает ответ, а не правду
Postman отвечает ровно на один вопрос, что вернул сервер. Он честно показывает эти самые 800 и этот самый debug, и на этом его работа заканчивается. Дальше человек своей головой должен вспомнить, что 800 не сходится с двумя по 450, и своей головой сверить каждое поле с документацией, открытой в соседнем окне.
Сверка головой ломается на третьем эндпоинте. Не потому что человек плохой, а потому что пятнадцать полей на ответ и восемь эндпоинтов это сто двадцать сравнений, и внимание кончается раньше.
И главное, чего Postman не сделает никогда. Он не заглянет в логи сервиса, а значит не скажет, почему сервер ответил именно так.
Про автотесты, которые написала нейросеть
Сценарий, который сейчас происходит в каждой второй команде. Человек, который не пишет код, просит модель сгенерировать автотесты. Модель выдаёт красивый файл, человек вставляет его в проект и подключает к сборке. Всё зелёное, все довольны.
Через месяц пятница, релиз, шаг в сборке краснеет. Человек открывает этот файл и смотрит на код, который он не писал и не читал. И теперь ему надо ответить на вопрос, который решает, поедет релиз или нет. Врёт тест или сломался сервис.
Ответить на него он не может. Не потому что глупый, а потому что это не его инструмент, он в нём не разбирается по определению. Дальше он идёт к разработчику, разработчик смотрит в код теста и говорит, что тест придумал поле, которого в этом сервисе никогда не было. Пятничный вечер потрачен, доверие к сборке потрачено, а модель, которая всё это написала, вообще не в курсе, что происходит.
Проблема не в том, что модель плохо генерирует код. Проблема в том, что человека сажают отвечать за инструмент, которым он не владеет. И потом за каждое падение он платит временем, которого у него и так нет.
Проверка правилами тем и отличается, что человек читает её на своём языке. Итог равен количеству, умноженному на цену. Статус равен PAID. Лишних полей нет. Тут нечего не понимать, и когда такая проверка краснеет, сразу видно, какое именно ожидание не сошлось.
Три прохода, которые делает проверка
Первый проход по структуре, все ли обязательные поля на месте. Второй по типам, потому что было число, стало строкой, и в JSON это одна кавычка, которую не видит никто. Третий по значениям, которые считает бэкенд, и это самое интересное место.

Посмотрите на строчку про итог. В правиле записан не результат, а расчёт, qty price = 2 450. Правило, куда ожидаемое число вписали руками, живёт до следующего тестового набора. Правило с расчётом внутри работает на любых данных и ловит именно то, ради чего всё затевалось, ошибку в бизнес-логике, а не опечатку в тесте.
Заголовки идут тем же способом. Тип содержимого обязан быть тем, который обещан, и ответ с телом JSON под заголовком text/html находится за секунду.
Проверять надо и то, чего быть не должно
Обычная проверка отвечает на вопрос, всё ли обещанное на месте. Поле debug она не найдёт никогда, потому что его никто не ждал.
Поэтому нужен список разрешённых полей, где всё остальное считается ошибкой. Именно так всплывают отладочные флаги, внутренние идентификаторы, чужие поля, случайно протёкшие из соседнего микросервиса, и заголовки, раскрывающие версию фреймворка. Это единственный способ поймать то, о чём вы даже не знали, что оно там появится.
Проверка «нет ли лишнего» находит больше проблем, чем проверка «есть ли нужное». Из всей статьи это главное.
Ответ это половина. Вторая половина в логах
Возвращаемся к A-17. Ответ пришёл со статусом 200. Смотрим, что в ту же секунду записал у себя сервис оплаты по тому же идентификатору запроса.

Сервис оплаты сам записал в свой лог итог 800 и статус NEW. Ошибка родилась на бэкенде, и это доказано его собственной строкой.
Вот что это меняет на практике. Разговор с разработчиком перестаёт быть спором. Не «у меня что-то не работает», а идентификатор запроса, время и строка из его лога. После такого сообщения задача уходит в работу сразу, а не возвращается с ответом «у меня всё воспроизводится нормально».
Ни один инструмент, который смотрит только на ответ, этого разговора вам не даст.
Правила пишутся не руками
Пятнадцать правил на ответ никто заводить вручную не станет, и это честно. Поэтому они делаются из самого ответа. Вставляете JSON и получаете готовый список проверок на все поля с типами и значениями, дальше отмечаете нужные и правите те, где вместо константы должен стоять расчёт.

Если у сервиса есть OpenAPI или Swagger, разворачивается сразу всё. Коллекция, запросы, заготовки проверок на статус, тип содержимого, поля тела и разрешённые заголовки. Руками останется описать только бизнес-правила расчётов, которых схема не знает.
Я специально не пишу тут красивых цифр про экономию времени, потому что у каждого свой проект и свои эндпоинты.
Скажу иначе.
Схема разворачивается в дерево запросов и готовых проверок за один клик, правила по ответу собираются автоматически, а прогон и отчёт умещаются в то время, пока закипает чайник.
Ручная сверка ответа с документацией на одном эндпоинте у меня занимает столько же, сколько тут занимает вся схема целиком.
Если не верите, схема Petstore публичная, повторите на ней сами и напишите в комментариях, сколько получилось у вас.
Как выглядит прогон

Отчёт отвечает на вопрос, что именно не так, без чтения кода. Его можно переслать разработчику или аналитику, и им не нужно разбираться в тестовом фреймворке, чтобы увидеть, что сумма посчитана неверно. Это же снимает и вечную проблему приёмки, когда результат теста понимает только тот, кто его писал.
Чем это отличается от остальных способов
Postman | Автотесты от нейросети | Проверка правилами | |
|---|---|---|---|
Кто разбирает падение | человек, вручную сверяя с документацией | тот, кто умеет читать код, а его обычно нет | любой, правило написано словами |
Одинаковый результат на одних данных | да | да, но код меняется при каждой перегенерации | да |
Видит записи в логах | нет | только если кто-то допишет доступ к хранилищу | да, по идентификатору запроса |
Ловит поля, которых нет в документации | нет | нет, модель проверяет то, что придумала сама | да, списком разрешённых полей |
Смена документации | переписывать проверки руками | генерировать заново и снова не читать | перегенерировать правила из нового ответа |
Куда уходит тело ответа | в облако при включённой синхронизации | в чужую модель целиком | никуда, всё локально |
Последняя строка стоит отдельного слова. Отправить ответ продового сервиса в чат с моделью означает вынести его наружу. В закрытом контуре это не абстракция, а разговор с безопасностью, и обычно короткий.
Повторяемость
Проверка имеет смысл, только если на одних и тех же данных она даёт один и тот же результат. Иначе её нельзя приложить к задаче и нельзя поставить в сборку.
В сборке
Набор проверок выгружается одним файлом и запускается консольной командой без интерфейса, в Jenkins, GitLab CI или GitHub Actions. Сборка получает привычный JUnit XML и краснеет на нужном шаге.

Посмотрите, что написано в упавшем шаге. Поле статуса ожидалось PAID, фактически пришло NEW. Итог ожидался 900, потому что количество умножается на цену, фактически пришло 800. И лишнее поле debug, которого нет среди разрешённых. Всё это читается человеком, который в жизни не открывал редактор кода.
Именно в этом месте расходятся два подхода. Когда в сборке краснеет сгенерированный нейросетью автотест, начинается расследование, врёт тест или сломался сервис, и на него уходит вечер. Когда краснеет правило, расследования нет вообще, потому что в отчёте написано, какое ожидание не сошлось и какое значение пришло вместо него. Дальше остаётся скопировать строку и отправить разработчику.
Напоследок
зачем это, если можно спросить нейросеть. Нейросеть не подключена к вашему стенду, не видела ваших логов и не знает, сколько стоит позиция в вашем прайсе. Она предполагает. Правило проверяет.
чем это отличается от Postman. Postman показывает ответ. Здесь ответ сверяется с документацией и с логами, и результат один и тот же при каждом прогоне.
куда уходят данные. Никуда. Программа работает на вашей машине, доступ к стенду и логам остаётся внутри вашей сети.
Первые 14 дней после регистрации бесплатно и с полным функционалом. Дальше оплата пока не подключена, продление делается письмом в поддержку.
Спрашивают про системы. Windows и Linux.
Расскажите в комментариях, как вы у себя ловите поля, которых нет в документации, и сверяете ли вообще ответ с логами. Соберу способы в отдельный пост.
Программа тут, ⟨ссылка на checkcraft.ru⟩.
Только зарегистрированные пользователи могут участвовать в опросе. Войдите, пожалуйста.
KioskNews shows a cleaned-up reading view extracted from the publisher’s page — the original always lives on their site, not ours.