Про разработку, AI, open source, etc...
Ведет @smelukov
Post #131
493
Подумал тут про покрытие тестами кода, который написала модель
Есть отдельный интересный кейс, в который легко попасть даже если вроде бы делаешь все правильно
Например:
- попросили модель реализовать фичу
- посмотрели глазами, вроде работает
- попросили модель покрыть это тестами
- получили зеленые тесты
- пошли рефакторить
Казалось бы, всё хорошо. Код есть, тесты есть, можно жить. Да, но нет 🙂
Когда мы просим модель написать тесты на уже существующий код, она воспринимает этот код как источник истины
Но модель не знает, как этот код должен работать по задумке. Она видит только то, как он работает сейчас
А значит, если в коде уже есть странное поведение или баг на edge-case, модель может спокойно написать тест именно на это поведение
И дальше получается неприятная штука: ты начинаешь рефакторить код, меняешь реализацию, тесты падают, а потом выясняется, что ты не сломал поведение, а наоборот починил существующую проблему. Просто тесты уже успели зафиксировать ее как ожидаемую
Я несколько раз втыкался в такое на легаси-коде. Нужно было покрыть кусок кода перед рефакторингом, модель накидывала тесты, все выглядело адекватно. А потом часть этих тестов приходилось переписывать, потому что они проверяли не бизнес-логику, а конкретные особенности старой реализации
Важно: тесты, которые фиксируют текущее поведение, сами по себе не плохие
В легаси это иногда именно то, что нужно. Мы можем специально написать characterization tests, чтобы понять, что система сейчас делает, и не разнести ее случайно во время переписывания
Проблема начинается тогда, когда мы не разделяем два разных режима:
- зафиксировать текущее поведение (вместе со всеми багами)
- проверить что все работает как задумано
Для модели это легко смешивается в одно. Для нас - нет
Поэтому сейчас я стараюсь делать чуть иначе: перед тем как просить модель писать тесты, я сначала прошу ее изучить код и описать, как она его понимает
Потом прошу отдельно выписать спорные места:
- где поведение неочевидное
- где могут быть edge-cases
- где код выглядит так, будто он работает случайно
- где модель не уверена, что именно нужно проверять
И только после этого прошу задать вопросы, ответы на которые повлияют на тесты
В результате появляется важная синхронизация: я вижу, какое поведение модель собирается считать правильным
Если я с этим не согласен, значит либо модель не поняла код, либо код сейчас действительно делает не то, что я ожидал
Иногда я еще прошу сложить это понимание в md-файл, чтобы не потерять контекст при суммаризации. Особенно если задача не на 15 минут и будет несколько итераций
В итоговый промпт почти всегда добавляю что-то вроде:
Это не магическая фраза, конечно, но если не дать модели контекста, то она просто возьмет единственный доступный источник истины - текущий код
Мораль: LLM нормально помогает писать тесты, но просьба "просто покрой это тестами" для существующего кода может привести к тому, что вы закрепите не ожидаемое поведение, а текущее, а текущее поведение - это не всегда то, что вам нужно
Есть отдельный интересный кейс, в который легко попасть даже если вроде бы делаешь все правильно
Например:
- попросили модель реализовать фичу
- посмотрели глазами, вроде работает
- попросили модель покрыть это тестами
- получили зеленые тесты
- пошли рефакторить
Казалось бы, всё хорошо. Код есть, тесты есть, можно жить. Да, но нет 🙂
Когда мы просим модель написать тесты на уже существующий код, она воспринимает этот код как источник истины
Но модель не знает, как этот код должен работать по задумке. Она видит только то, как он работает сейчас
А значит, если в коде уже есть странное поведение или баг на edge-case, модель может спокойно написать тест именно на это поведение
И дальше получается неприятная штука: ты начинаешь рефакторить код, меняешь реализацию, тесты падают, а потом выясняется, что ты не сломал поведение, а наоборот починил существующую проблему. Просто тесты уже успели зафиксировать ее как ожидаемую
Я несколько раз втыкался в такое на легаси-коде. Нужно было покрыть кусок кода перед рефакторингом, модель накидывала тесты, все выглядело адекватно. А потом часть этих тестов приходилось переписывать, потому что они проверяли не бизнес-логику, а конкретные особенности старой реализации
Важно: тесты, которые фиксируют текущее поведение, сами по себе не плохие
В легаси это иногда именно то, что нужно. Мы можем специально написать characterization tests, чтобы понять, что система сейчас делает, и не разнести ее случайно во время переписывания
Проблема начинается тогда, когда мы не разделяем два разных режима:
- зафиксировать текущее поведение (вместе со всеми багами)
- проверить что все работает как задумано
Для модели это легко смешивается в одно. Для нас - нет
Поэтому сейчас я стараюсь делать чуть иначе: перед тем как просить модель писать тесты, я сначала прошу ее изучить код и описать, как она его понимает
Потом прошу отдельно выписать спорные места:
- где поведение неочевидное
- где могут быть edge-cases
- где код выглядит так, будто он работает случайно
- где модель не уверена, что именно нужно проверять
И только после этого прошу задать вопросы, ответы на которые повлияют на тесты
В результате появляется важная синхронизация: я вижу, какое поведение модель собирается считать правильным
Если я с этим не согласен, значит либо модель не поняла код, либо код сейчас действительно делает не то, что я ожидал
Иногда я еще прошу сложить это понимание в md-файл, чтобы не потерять контекст при суммаризации. Особенно если задача не на 15 минут и будет несколько итераций
В итоговый промпт почти всегда добавляю что-то вроде:
Тесты должны проверять ожидаемое поведение, а не просто фиксировать текущую реализацию. Если текущее поведение выглядит спорным - сначала задай вопрос
Это не магическая фраза, конечно, но если не дать модели контекста, то она просто возьмет единственный доступный источник истины - текущий код
Мораль: LLM нормально помогает писать тесты, но просьба "просто покрой это тестами" для существующего кода может привести к тому, что вы закрепите не ожидаемое поведение, а текущее, а текущее поведение - это не всегда то, что вам нужно
- 👍 16
- ❤ 3
- 🤔 1



