Одна идея этого урока: тесты – это не проверка «работает ли сейчас», а страховка, которая позволяет быстро менять систему, не боясь сломать то, что уже работало.
Знакомая ситуация
Твой планировщик для школы работает третий месяц. Ты просишь агента добавить напоминания об оплате. Он бодро отчитывается: «Готово». Напоминания работают. А через два дня выясняется, что перестала работать выгрузка учеников – агент по пути «улучшил» общую функцию, и старое поведение тихо сломалось.
Ты проверил новую фичу. Но кто проверил все старые? Никто. В этом и проблема: с каждой новой фичей список «что могло сломаться» растёт, а проверять его руками ты физически не успеваешь.
Тест – это зафиксированное ожидание: «система в такой-то ситуации ведёт себя так-то». Ценность тестов не в том, что они находят ошибки сегодня, а в том, что они разрешают тебе смело менять систему завтра.
Регрессия – проблема №1 в разработке с ИИ
Регрессия (regression) – это когда новое изменение ломает старое поведение. Для разработки с агентом это главный риск, и вот почему:
1
Агент правит смело и широкоЧеловек-джун боится трогать чужой код. Агент не боится ничего: попросишь мелочь – он походя перепишет соседнюю логику, потому что «так лучше». Каждая такая правка – лотерея для старых фич.
2
У агента нет памяти о договорённостяхТы три недели назад решил, что скидка не суммируется с промокодом. Агент этого не помнит – если правило не зафиксировано тестом, оно живёт только в твоей голове.
3
Ручная проверка не масштабируется10 фич ещё можно прокликать. 50 – уже нет. Тесты – это твоя ручная проверка, записанная один раз и выполняемая машиной за секунды после каждого изменения.
Отсюда практическое правило: тест – это спецификация поведения (specification), договорённость с системой, которую агент не сможет молча нарушить. Если тест упал – значит, изменение задело то, о чём вы договаривались.
Пирамида тестов: много мелких, мало сквозных
Не все тесты одинаково полезны. Классическая модель – пирамида тестов (test pyramid) Мартина Фаулера:
1
Основание: юнит-тесты unit testsМного быстрых проверок отдельных кусочков логики: «скидка 20% от 1000 даёт 800». Выполняются за секунды, точно показывают, ЧТО сломалось.
2
Середина: интеграционные тесты integration testsМеньше и медленнее: проверяют, что части дружат между собой – «заказ сохраняется в базу и попадает в отчёт».
3
Вершина: сквозные тесты end-to-end testsЕдиницы: прогон целого сценария глазами пользователя – «ученик оплатил и получил доступ». Медленные, хрупкие, зато проверяют систему целиком.
Почему пирамида, а не наоборот: сквозные тесты медленные и часто ломаются по мелочам, поэтому их держат немного – только на критичные пути (оплата, регистрация). Основную массу поведения фиксируют быстрыми мелкими тестами. Если агент предлагает «прокликать всё через интерфейс» – это перевёрнутая пирамида, она будет тормозить каждое изменение.
Качество и скорость – не компромисс
Интуиция подсказывает: «тесты – это дополнительное время, значит, медленнее». Фаулер в статье «Is High Quality Software Worth the Cost?» показывает обратное: высокое внутреннее качество окупается уже через недели, а не годы. Без страховки каждое следующее изменение всё дороже: больше ручных проверок, больше страха, больше откатов. С тестами скорость держится, потому что цена ошибки – упавший тест за 10 секунд, а не разбор жалоб учеников в чате.
Для тебя это выражается в двух привычках: требовать от агента тесты на ключевую логику (деньги, доступы, расписание – не на каждую кнопку) и просить прогонять их после каждого изменения. Это дешёвая привычка с огромным плечом.
Как думают три уровня
Джун«Тесты – бюрократия, которая крадёт время у фич. Я же вижу, что работает – я проверил». Проверил он новую фичу, а сломалась старая.
МидлПишет тесты после кода, для галочки: «покрытие 80% – отчёт красивый». Тесты повторяют то, что код и так делает, вместо того чтобы фиксировать, что он ДОЛЖЕН делать.
СеньорТесты – это спецификация поведения и сеть безопасности. Без них быстро меняться нельзя в принципе. Вопрос не «писать ли тесты», а «какое поведение настолько важно, что его нужно зафиксировать».
Проверь себя
1. Агент добавил фичу и отчитался: «Готово, я проверил – новая фича работает». Что здесь упущено с точки зрения сеньора?
Проверка новой фичи – самая лёгкая часть: её и так все смотрят. Главный риск – регрессия (regression): изменение тихо задело старую логику. Именно поэтому сеньор после любого изменения прогоняет тесты на всё, а не любуется новой фичей.
2. Агент предлагает: «Давай я покрою приложение тестами – напишу 40 сквозных сценариев, которые прокликивают интерфейс от логина до оплаты». Твоя реакция?
40 сквозных тестов – это перевёрнутая пирамида: каждый прогон будет длиться долго и падать по мелочам, ты быстро перестанешь их запускать. Но и выбрасывать вершину пирамиды нельзя – пара сквозных проверок критичных путей (оплата, доступ) незаменима. Много быстрых внизу, мало медленных наверху.
3. Ты запускаешь мини-сервис для школы и думаешь: «Тесты замедлят разработку, добавлю их потом, когда проект вырастет». Что говорит про это опыт индустрии?
Фаулер показывает: высокое внутреннее качество окупается через недели, а не годы – «потом» наступает быстрее, чем кажется. Но и вариант «покрыть всё до запуска» – крайность: сеньор фиксирует тестами ключевое поведение (деньги, доступы), а не каждую кнопку.
Что говорить агенту уже сегодня
При новой фиче: напиши тесты на ключевую логику этой фичи – они должны фиксировать ожидаемое поведение, а не повторять код
После любого изменения: прогони все тесты и покажи результат, прежде чем отчитываться «готово»
Для старого проекта: какое поведение в проекте самое критичное для бизнеса? предложи 5 тестов, которые зафиксируют его от регрессий
Если тест упал: не подгоняй тест под новый код – сначала объясни, почему изменилось старое поведение, и спроси меня
Источники
Martin Fowler, The Test Pyramid – почему быстрых мелких тестов должно быть много, а медленных сквозных – мало.