Привет, Хабр! Для большинства разработчиков тесты – это нелюбимая часть работы. Недавно мы убедились в этом, опросив больше 400 разработчиков на конференциях Joker и Heisenbug об их отношении к AI-инструментам для тестирования. В статье расскажем, что еще интересного мы от них узнали, а также какие существуют AI-инструменты для автоматической генерации тестов, какие у них есть плюсы и минусы.

Почему никто не хочет писать тесты и причем здесь языковые модели

Итак, какие выводы нам помогли сделать участники Joker и Heisenbug. Во-первых, оказалось, что несмотря на то, что с появлением трансформеров у сообщества появился сильный инструмент для генерации кода, большая часть опрошенных не пользуется никакими AI-инструментами в повседневной работе:

Предполагаем, что это связано с требованиями безопасности. Много специалистов, с которыми нам удалось пообщаться, подтвердили, что без on-premise рассматривать AI-ассистентов они не готовы.

Во-вторых, по словам разработчиков, есть несколько основных проблемы с написанием тестов:

  • лень/долго/скучно (подавляющее большинство!)

  • одинаковая работа

  • сложно придумать много краевых случаев

  • сложно правильно мокировать зависимости

Если процесс однообразен и скучен, стоит подумать о его автоматизации. Проблема автогенерации тестов существует очень давно, стандартно её решали с помощью генерации шаблонов тестов, property-based тестирования, фаззинга и символьного исполнения. Первые два подхода вынуждают частично писать тесты вручную, например, придумывать тестовые данные или свойства. Последние два подхода порождают нечитаемые тесты, которые тяжело поддерживать. Так, например, хотя символьное исполнение способно создать 5 тысяч тестов со стопроцентным покрытием, но читать и поддерживать их в перспективе совершенно невозможно.

Таким образом, идеальный тестовый инструмент:

  • делает рутинную работу за разработчика

  • экономит время разработчика на придумывание корнер-кейсов

  • понимает контекст кодовой базы

  • генерирует поддерживаемые человеко-читаемые тесты

  • помогает в мокировании

Благодаря ChatGPT появился новый перспективный способ генерации тестов при помощи языковой модели: скопируй свой код в ChatGPT, попроси тесты и она тебе их сгенерирует.

Зачем вообще нужны специализированные плагины для генерации тестов?

Строго говоря, для генерации тестов плагин не требуется. Можно воспользоваться подпиской на одну из моделей и посылать запросы для генерации прямо в веб-чате chatgpt.com. Существует множество плагинов, которые интегрируют чат в IDE, например, Codeium, или дополняют код, как GitHub Copilot. Почему не использовать их и для генерации тестов?

Ключевая проблема – сбор кодового контекста. Если дать LLM только код функции без её зависимостей, странно ожидать, что получатся хорошие тесты или что они хотя бы будут компилироваться (представьте, что вам дали незнакомую кодовую базу, запретили в нее заглядывать и попросили написать тест для случайной функции). Указывать вручную все зависимости – также рутинная механическая работа. Значит хороший плагин для генерации тестов должен автоматически собирать разумные зависимости в промпт.

Очень важной частью взаимодействия с LLM являются промпты (описание задачи для LLM на естественном языке). От качества промпта зависит качество сгенерированных тестов: их компилируемость, соответствие стилю кодовой базы, какое эти тесты будут давать тестовое покрытие. Составить такой промпт качественно – трудоемкая задача. Получается, что монотонную задачу написания тестов разработчик заменяет на задачу исправления и переписывания промпта. LLM-плагины для тестогенерации стараются оградить пользователя от этого кошмара, предлагая готовые пайплайны для разных случаев генерации с уже «зашитыми внутрь» промптами для разных юзкейсов.

Зачем нужны специализированные плагины для генерации тестов, если собирать контекст и использовать заточенные под задачу промпты могут AI-ассистенты для генерации кода, такие как Codeium, Cursor, Gigacode? Их возможности шире, но менее специфичны с точки зрения пользовательского опыта: плагин должен не только автоматически генерировать код, но и интегрироваться с существующей кодовой базой. Например, он должен определять версию языка, build систему (Maven, gradle, Kotlin gradle), моковый фреймворк (mockito или mockk), тестовую библиотеку (ktest, junit, TestNG), стиль используемых в проекте тестов и так далее. Если всё это нужно указывать в промпте вручную, то уже нет особой разницы, генерируешь тесты при помощи chatgpt.com или Codeium.

☝️?: Несмотря на очевидный плюс – понимание контекста – у языковых моделей есть недостатки. Так, вы не можете гарантировать, что код, который выдаст LLM, будет компилироваться и запускаться. А еще каждый из существующих LLM-инструментов оперирует так называемым «семантическим покрытием», а не реальным покрытием инструкций, поэтому, вообще говоря, у вас нет строгих гарантий, что с увеличением количества LLM-тестов, покрытие инструкций будет увеличиваться.

Какой выбрать?

Чтобы оценить преимущества специализированных плагинов для тестогенерации, имеет смысл сравнить их между собой. 

Для анализа мы рассмотрим Tabnine, Qodo, Explyt Test и TestSpark, а также упомянем Diffblue Cover, который представляет подход на основе ML без использования LLM. Codeium, GigaCode будут выступать в качестве альтернативы специализированным подходам.

Какие плагины мы будем сравнивать?

Я уже говорил, что для генерации тестов можно использовать AI-ассистента, который может работать с контекстом проекта. Для сравнения со специализированными инструментами возьмем два таких продукта: Codeium и GigaCode.

Типичные инструменты для генерации тестов с помощью LLM – Tabnine, Qodo, Explyt Test. Языковые модели позволяют быстро генерировать код на любом языке, UI и двухфазная генерация (тестовые сценарии, затем код) позволяют управлять corner-кейсами. Другой LLM-инструмент – TestSpark, плагин для генерации тестов на java и kotlin, в отличие от Tabnine и Codium пропускает генерацию сценариев, зато позволяет редактировать код каждого теста прямо в окне генерации и имеет открытый исходный код.

Существуют также решения на основе ML, но без использования LLM, например, Diffblue Cover. Утверждается, что сгенерированные им тесты, в отличие от тестов, сгенерированных LLM-инструментами, всегда компилируются и запускаются.

Сравнение

Базовый функционал у всех сравниваемых плагинов схож: выбираешь необходимый метод или класс, нажимаешь кнопку в интерфейсе, получаешь код тестовых методов или классов:

Qodo Gen
Qodo Gen
Tabnine
Tabnine
Explyt Test
Explyt Test

Что их тогда друг от друга отличает?

Какие уникальные фичи есть у этих плагинов?

Автоматическое исправление некомпилирующихся и падающих тестов

Frontier-языковые модели умеют классифицировать возникающие проблемы и предлагать для них решения «из коробки». Удобно, когда в плагине для генерации тестов есть кнопка, позволяющая автоматически исправить тест при помощи языковой модели.

Создание автофиксов – следствие неспособности LLM генерировать компилирующийся код, правильно импортировать зависимости. Об этих и других проблемах мы рассказали на JokerConf.

Использование своего LLM-ключа

Если у вас уже есть личный или корпоративный ключ от какого-либо провайдера, очень удобно, когда плагин для генерации тестов позволяет использовать его и взаимодействовать с провайдером напрямую.

Настройка провайдера и модели

В языковых моделях идёт гонка вооружений, и модели OpenAI устраивают не всех. Хорошо, когда плагин генерации тестов даёт возможность поменять провайдера и модель, чтобы лучше подходить вашему сценарию использования. Например, DeepSeek стоит значительно дешевле, чем топ-провайдеры, Groq генерирует тысячи токенов/сек, пока остальные измеряют скорость генерации в сотнях токенов/сек.

Дообучение модели для своей кодовой базы

Дообучение (fine-tuning) – процесс адаптации модели для конкретной задачи. Некоторые плагины позволяют дообучать языковые модели на вашей кодовой базе, чтобы улучшить качество генерации. Согласно Codeium, дообучение позволяет сильно улучшить качество предлагаемого AI-ассистентом кода

Codeium
Codeium

☝️?:  Стоит заметить, что дообучение в закрытом контуре – сложная задача и, возможно, игра не стоит свеч. Эффект дообучения сильно зависит от качества данных и само дообучение сложно автоматизировать.

Использование локально развёрнутой модели

Иногда хочется, чтобы код не уходил в интернет, или к интернету просто нет доступа (например, в самолете). Если компьютер достаточно мощный, на нём можно разместить достаточно большую языковую модель, которая будет генерировать осмысленный код. Для этого существует, например, проект Ollama, позволяющий развернуть локально любую модель с открытыми весами. Хорошо, если плагин для генерации тестов поддерживает возможность использовать локально развёрнутую модель.

☝️?: хотя возможность запуска модели локально действительно существует, нужно быть аккуратным при использовании моделей для генерации тестов. На большинстве рабочих ноутбуков и компьютеров произвольная открытая модель будет либо работать слишком медленно, либо выдавать некачественные результаты. Поскольку некоторые производители ноутбуков проектируют новые устройства со специализированными для нейронок процессорами, эта ситуация может исправиться через несколько лет.

Для удобства, свели все рассмотренные атрибуты для всех решений в одну табличку. Так как Diffblue Cover работает на базе RL, а не языковых моделей, параметры, связанные с LLM, к нему неприменимы. В Diffblue не поддержана починка тестов, нельзя выбрать ML-модель для генерации, нельзя ее дообучать. Также Diffblue Cover работает исключительно локально, хотя и требует подключения к интернету для всех тарифов кроме Enterprise.

Плагин

Автофикс тестов

Свой LLM-ключ

Выбор провайдера и модели

Дообучение

Локальный хостинг

Codeium

нет

нет

да

да

нет

GigaCode

нет

нет

нет

нет

нет

Tabnine

нет (для jvm)

да (enterprise)

Tabnine, OpenAI, Claude

да (enterprise)

нет

Qodo

нет (для jvm)

нет

OpenAI, Claude, Gemini

нет

нет

TestSpark

да

да

HuggingFace, OpenAI

нет

нет

Diffblue Cover

нет

-

-

-

работает только
локально

Explyt Test

да, но только для LLM-тестов (compile + runtime)

да

OpenAI, Claude, Gemini, DeepSeek, Groq, Cerebras, Anthropic

нет

да

Как плагины работают с контекстом проекта?

Правильный подбор контекста очень важен для получения качественных результатов от LLM.

Есть несколько способов собирать кодовый контекст. Более простым является эвристический, как, например, в GitHub Copilot: анализировать три последних открытых файла. Для генерации тестов такие эвристики плохо подходят, так как нужен специализированный алгоритм именно для генерации тестов. Хотя большинство AI-ассистентов требуют собирать контекст руками, для задачи генерации тестов может быть реализован автоматический сбор контекста.

Часто хочется, чтобы генерируемый тест был похож на уже существующие, с точностью до специфики тестируемого поведения. Чтобы обеспечить «похожесть» на пользовательский код автоматически, тестовый плагин должен уметь находить и использовать похожие тесты в качестве шаблона автоматически: посмотреть, как они устроены, и передать информацию в промпт. Также хорошо, если пользователь может выбрать такой референс руками.

Часто на работу кода влияет и не кодовый контекст. Он может включать файлы конфигураций приложения, не содержащие код, но важные для понимания контекста работы тестируемого приложения. Примеры не кодового контекста – xml-файл со Spring-конфигурацией бинов, env-файл с переменными окружения.

Плагин

Контекст

Использование похожего теста

Не кодовый контекст

Codeium

авто+руками

руками

нет информации

GigaCode

выделение или текущий файл

руками

нет информации

Tabnine

авто+руками

руками

нет информации

Qodo

авто+руками

руками

нет информации

TestSpark

авто

руками

нет информации

Diffblue Cover

авто

нет

нет информации

Explyt Test

авто

авто

в разработке

Что если важно, на какие сервера отправляется код?

Хотя существуют бесплатные чат-провайдеры и инструменты для генерации кода, наши опросы показывают, что подавляющее большинство специалистов AI-инструментами вообще не пользуется. На вопрос «почему?» обычно отвечают, что это запрещено политикой компании из-за требований безопасности: исходный код не должен выходить из контура компании, использовать инструменты с чужим хостингом запрещено. Но все-таки, если использовать инструмент очень хочется, можно выбрать хостинг, отвечающий вашим требованиям приватности:

  • Community. Ваши запросы отправляются на сервер провайдера LLM. В зависимости от выбранного плана, провайдер может обещать не использовать ваши данные для обучения моделей или предоставлять opt-out (так делает Qodo, для бесплатной версии предоставляет opt-out). У некоторых провайдеров (например, Tabnine) можно запросить zero data retention: данные вашего запроса не будут сохраняться на серверах вообще.

  • (Virtual) Private Cloud ((V)PC). Вы используете инфраструктуру облачного провайдера, при этом удаленный доступ к ней есть только у вас. Такой сервис предоставляет, например, Amazon, Yandex, cloud.ru от Сбера. 

  • On-premise hosting. Вы полностью управляете инфраструктурой, на которой разворачивается решение, так как используются ваши сервера или сервера, к которым у вас есть доступ.

Для международной сертификации ПО на безопасность используется протокол SOC 2. Если вкратце, то SOC 2-аттестованный поставщик SaaS-продукта отвечает пяти критериям: безопасность (защита от неавторизованного доступа), доступность (обеспечение доступности услуг согласно соглашениям), целостность обработки (точность и авторизация данных), конфиденциальность (ограничение доступа к данным), приватность (соблюдение политики обработки персональной информации). В РФ есть свой аналог – аттестация ФСТЭК, требования которой в целом похожи на SOC 2. Ни один из зарубежных плагинов аттестацию ФСТЭК, разумеется, не прошёл.

Плагин

Опции приватного хостинга

Сертификации

Аттестация ФСТЭК

Codeium

on-prem (enterprise)

SOC 2

нет

GigaCode

on-prem

нет

да

Tabnine

on-prem (enterprise)

GDPR, SOC 2

нет

Qodo

on-prem (enterprise)

SOC 2

нет

TestSpark

недоступно

нет

нет

Diffblue Cover

запускается только локально

-

нет

Explyt Test

on-prem (enterprise)

планируется SOC 2, GDPR

планируется

Что можно получить бесплатно, а что за деньги?

Чаще всего, за деньги вы получаете доступ к более мощным языковым моделям, снятие ограничений по количеству запросов или улучшенный UX. Tabnine в платной подписке убирает ограничение на использование frontier-моделей (самые продвинутые доступные модели, например, GPT-4o), Codeium в варианте Pro даёт кредиты для использования с frontier-моделями и более продвинутую версию алгоритма сбора контекста. GigaCode предлагает покупку токенов для своих моделей напрямую. Qodo же предоставляет все функции для генерации тестов в бесплатной версии без ограничений, в том числе пользование frontier-моделями, добавляя в платную версию автодопополнение кода и несколько других, не относящихся к тестам функций. Explyt Test позволяет приобрести токены, чтобы использовать их для генерации. При обычном сценарии использования, программист в месяц в среднем тратит 3000 токенов.

Лимиты Diffblue отличаются от всех остальных провайдеров тем, что он предоставляет ограниченное число генераций – нажатий на кнопку «создать тест». 

Плагин

Работает в РФ

Бесплатно

За деньги

Codeium

нет

бесплатно только модели от Codeium

15$

GigaCode

да

10^6 бесплатных токенов

в зависимости от модели

Tabnine

нет

Tabnine модели: без ограничений, frontier-модели: 2-4 запроса в день

9$ (90 дней бесплатно)

Qodo

нет

без ограничений

19$ (14 дней бесплатно)

TestSpark

из исходников

-

-

Diffblue Cover

нет

25 генераций/месяц

30$: 100 генераций/месяц

Explyt Test

да

одноразово: 1000 токенов

1 руб/1 токен

В заключение

Существуют и другие подходы к генерации тестов. Для критически важного кода можно рассматривать инструменты, основанные на символьном исполнении, например, UTBot Java. Символьное исполнение позволяет эффективно перебирать состояния, в которые может попасть программа, а потому хорошо покрывает программу тестами.

В качестве менее фундаментального подхода можно выбрать решения, основанные на автоматическом анализе кода, например Squaretest, Jtest. За счет того, что гарантии корректности этих инструментов более слабые, код генерируется быстрее.

Мы готовим материал про альтернативные подходы к генерации тестов. О чем еще вам бы хотелось узнать и что интересно обсудить? Пробовали ли вы уже инструменты для автоматической генерации тестов, с LLM и без? Делитесь своим опытом и мнениями в комментариях. Спасибо, что дочитали до конца :)

Комментарии (6)


  1. Shatun
    24.12.2024 12:28

    Мне из статьи так и не очевидно у кого по итогу тесты лучше генерируются.
    Удивительно отсуствие набиолее популярного инструмента - copilot.


    1. mrga Автор
      24.12.2024 12:28

      у кого по итогу тесты лучше генерируются

      С высокой долей вероятности, качество генерации у специализированных плагинов сходно, так как плагины работают на одних и тех же языковых моделях. Почти все что может сделать плагин - дать качественный контекст. Поэтому выбирать нужно по другим параметрам: сертификациям, возможности выбора модели и т д

      отсуствие набиолее популярного инструмента - copilot

      В данной статье фокус на сравнении специализированных инструментов для генерации тестов, Codeium и GigaCode можно использовать, если пул задач у вас шире, чем генерация тестов. Но вы правы, copilot как пример подошел бы лучше


      1. Shatun
        24.12.2024 12:28

        С высокой долей вероятности, качество генерации у специализированных плагинов сходно, так как плагины работают на одних и тех же языковых моделях. Почти все что может сделать плагин - дать качественный контекст

        Разный промпт+ разный контекст дает достаточно существенную разницу. Плюс вполне может подаваться дополнительня конекст который можно получить из кода например используемые бибилотеки, фреймворки. Так что теоретически разница может быть существенная(а может они все в этом примерно на одном уровне).
        Так же разница интересна разница с общими инструментами(в данном случае codeium и gigacode) и есть ли она. Я использую copilot и мне интересно имеет ли смысл жти плагины или нет.


  1. typik89
    24.12.2024 12:28

    Мне одному непонятна ценность таких сгенерированных тестов? Т.е. разработчик пишет реализацию. Затем отдает AI инструменту, AI инструмент успешно генерирует тесты которые проходят без участия разработчика. И какой выхлоп от таких тестов? Даже если опустить за скобки, что в целом хорошо бы работать если не по TDD, то по крайней мере писать тесты параллельно с кодом. Тесты разработанные AI без участия программиста не несут никакой смысловой нагрузки. Сегодня я написал реализацию и сгенерил тесты, завтра мне нужно подправить реализацию - я иду и тоже сгенерю тесты, получается от этих тестов мир лучше не стал. А вот если я как разработчик вложил в реализацию и в тесты этой реализации хоть какую-то идею, дальше при изменении реализации есть шанс, что я отловлю что-то, что я забыл или не продумал, даже если это и приведет к правке тестов - все равно заставит меня критически оценить логику тестов которые были и правда ли я меняю реализацию так, что эти сценарии тоже меняются.

    Я не полностью против использования таких инструментов, более того я сам использую для генерации каркаса таких тестов, но вот генерация уже самих тестов и сценариев бездумно - это на мой взгляд какой-то мартышкин труд и имитация деятельности, правда это справедливо и для бездумного написания тестов без AI инструментов, которые проходят.


    1. Shatun
      24.12.2024 12:28

      Сегодня я написал реализацию и сгенерил тесты, завтра мне нужно подправить реализацию - я иду и тоже сгенерю тесты, получается от этих тестов мир лучше не стал

      Тесты в первую очередь не проверяют поведение, а фиксируют его, чтобы при рефакторинге/добавлении фичи вы нес ломали что-то что уже работает. Поэтому автосгенерированные тесты(при проверке что сгенерировало) вполне имеют смысл и при рефакторинге в общем случае должен проходить также как и раньше.

      А в целом тесты генерируются не полностью случайным образом, а те которые вам нужны. С копайлотом исходя из названия теста обычно сгенерируется с большего правильный тест, которому нужны минимальные правки.


      1. typik89
        24.12.2024 12:28

        А вы знакомы с концепциями TDD, для чего вообще нужны по Вашему юнит тесты?

        Какое такое поведение они фиксируют, зачем его фиксировать? Вот Вы написали или сгенерировали какой-то класс с помощью chatgpt, затем сгенерировали тесты и "зафиксировали" поведение. А Вы уверены, что вы зафиксировали то что надо? Как можно полагаться на зафиксированное поведение сгенеренного по реализации теста? Рефакторинг строго говоря бывает разный и не всегда это добавить еще один if в метод и радоваться, что старые тесты не упали, написав еще один новый тест. Что Вы делаете с этими сгенерированными по прошлой реализации тестами? Вы их не писали, получается их можно выкидывать в мусорку и заново генерить, если рефакторинг или добавление новой фичи выливается в что-то чуть большее чем пару строк кода в конце метода? А если бы вы их писали ( возвращаясь к практикам TDD), то они бы Вам в этом рефакторинге помогли, а вот эти Ваши сгенерированные вряд ли помогут. Есть еще такой момент, что масштаб вызываемой боли при написании юнит теста обычно коррелирует с тем насколько нехорошо собственно написана реализация и декомпозирован код, а генерация тестов не дает шанса подумать об этом ( концепции TDD).

        Меня не покидает ощущения творящегося идиотизма, как будто тесты пишутся по не для разработки качественного продукта и дальнейшей его поддержки, а для реализации хотелок эффективных менеджеров. Сгенерим 100 классов и 100 классов тестов для них за 5 секунд и все довольны, а то как там в реальности это работает не важно, скорей всего потом будем еще неделю вручную тестировать, но зато все формальные требования закрыты: 100 классов есть и 100 юнитов есть со 100% покрытием.

        Современные AI инструменты бесспорно мощные и нужные инструменты, с помощью которых можно оптимизировать работу, но все надо делать с умом и вот эти конкретные фичи в таком виде как рекламируется в статье их использовать - на мой взгляд не имеет ничего общего с повышением эффективности работы разработчика и улучшением качества продукта, а скорее пыль в глаза. Я бы даже сказал, что такая реклама такого использования copilot и др скорее даже вредна для неопытных разработчиков.