Лампа с цифровым джинном: как я учил ИИ писать unit-тесты

Лампа с цифровым джинном: как я учил ИИ писать unit-тесты

Человек не сможет открыть новые океаны, пока не наберётся смелости потерять из виду берег. — Андре Жид

Меня зовут Александр Гирев, я тимлид в мобильном приложении WB Partners. Изначально я хотел поделиться опытом написания unit-тестов с помощью ИИ. Но по мере написания статья превратилась в историю о том, как моё отношение к нейросетям изменилось — от скептицизма и страха до любопытства и увлечённости.

Все примеры относятся к проекту под Android и используют локальную LLM или модель в корпоративном контуре.

Тем, кто хочет сразу к практике, — добро пожаловать в соответствующие разделы. Остальным — приготовьтесь к рефлексии и личному опыту.

Это не туториал и не исчерпывающее руководство. Некоторые технические детали и термины опущены. Вместо этого — ссылки на источники, где можно добрать знаний. Хотя, скорее всего, к моменту вашего чтения часть информации уже устареет. Таков ИИ: всё меняется слишком быстро.

Вдох. Выдох. Начинаем.

Первое знакомство с джинном

Как и у многих, моё знакомство с генеративным ИИ началось в 2023 году. Первые диалоги с GPT казались магией — словно джинн наконец выбрался из бутылки и поселился в цифровом мире.

Любопытство быстро сменилось тревогой: а вдруг эта штука займёт моё место?

Но времени на панику не было. Нужно было закрывать задачи, чинить баги, изучать технологии. ИИ стал эффективным помощником, ускоряющим поиск решений. Да, ответы бывали неточными, код — нерабочим, а библиотеки — вымышленными. Возможно, в стране джиннов другая версия Kotlin.

Тогда использование ИИ сопровождалось лёгким стыдом. Разве нельзя справиться самому? Хотя по сути это было не новее, чем копировать код с Stack Overflow. Просто источник стал другим.

Так я и жил до прошлой осени: иногда спрашивал у чата, если заходил в тупик. Побаловался Cursor — но вау-эффекта не было. Как можно впечатляться ИИ, который рисует розовых пони в UI не лучше меня?

Иногда меня посещала тревога. Казалось, вокруг идёт технологическая революция, а я сижу дома, пью чай с баранками и слушаю Шостаковича на патефоне.

Выступления про ИИ-агентов выглядели как откровения. Но в моём окружении никто не превратился в x10-программиста, а посты в духе «пока мои агенты пишут код, я изучаю язык эльфов» я списывал на хайп.

Глава 1. Я знаю, что ничего не знаю

Всё изменилось прошлой осенью. Я познакомился с Алексеем Утеповым, Android-разработчиком из QazCode. Он выступал на конференции с докладом про ИИ-агентов. В их команде активно использовались решения от Anthropic. Макеты из Фигмы превращались в код почти мгновенно.

Зал был переполнен. Я сидел на полу, впитывая каждое слово.

После доклада я задал вопросы по безопасности и метрикам. Но главное — я понял: ящик Пандоры открыт. Отставать дальше стало невозможно.

Подлил масла в огонь мой бывший руководитель. Мы гуляли по Батуми. Я пытался отмахнуться: «Справлюсь и без ИИ». Он ответил: «Но ты же руководитель. Тебе нужно понимать, что ИИ может и чего не может. Потому что однажды тебя спросят: сколько человек можно заменить, если выпустить джинна?»

И я почувствовал: я сижу у патеофона, а вокруг — будущее.

Но я успокоил себя: всё меняется так быстро, что отстать окончательно невозможно. То, что было актуально год назад, сегодня уже устарело. А ведь я когда-то выучил Java и Kotlin по вечерам после работы. Значит, справлюсь и с ИИ. Синдром самозванца ушёл в спячку. Я начал погружаться.

Глава 2. Истина где-то посередине

Я стал читать всё подряд: статьи, доклады, исследования, чаты. Хотел понять: насколько эффективен ИИ в реальных командах? Что он может? С чего начать?

Оказалось, истина — посередине. Чаще всего о «революции» писали те, кто сам разрабатывает ИИ, продаёт видеокарты или курсы.

Без программистов можно было обходиться до поры до времени. До тех пор, пока MVP не нужно было превратить в продукт, который работает и приносит деньги.

В коммерческих проектах ИИ использовали. Но «свою модель» зачастую оказывался форк опенсорсной, немного переобученной на русский. А цифры эффективности — не «99,8% кода от ИИ», а скромные +10–20%.

Хорошая новость: за три недели я понял, что почти ничего не пропустил. Как сказал один спикер на круглом столе, разница между джуном и сеньором в использовании ИИ — 3–4 месяца. Этого достаточно, чтобы войти в тему и начать делать полезные вещи. Позже я убедился: он был прав.

Глава 3. Начинаю тереть лампу

Я перешёл от теории к практике. Стал разбираться в терминах: MCP-протокол, RAG, OpenAI, системный промпт, ИИ-агенты. Если они звучат для вас как заклинания — есть хорошие видео, где всё объясняют.

Переломный момент наступил, когда я с помощью Cursor написал чат-бота на Python. Язык я не знал. Код был для меня чёрным ящиком. Я мог понять, что написано, но не мог исправить или отладить.

Странное ощущение — как будто сел в машину с роботом-водителем и не знаешь, куда едешь.

В какой-то момент я понял: я знаю достаточно, чтобы применить это в работе. Скептик внутри шептал: «И ты, Брут?». Возможно. Но если не сделаю я — сделает кто-то рядом. Теория игр в действии.

Глава 4. Выбор первого желания

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

Правила были ясны: использовать только локальные или корпоративные модели. Я их принял.

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

Мне нужно было выбрать инструмент для общения с LLM. Я рассмотрел несколько вариантов:

  • Continue — удобный плагин для IDE. Джинн прямо в Android Studio. Настройка простая, есть автокомплит. Но устойчивой работы добиться не удалось. Модель падала при долгих задачах. По отзывам — не у меня одного.
  • Встроенный агент Android Studio — вышел в начале 2026 года. Я ждал от него многого. Но и здесь были проблемы с устойчивостью. Возможно, Google тестировал его с Gemini, а не с локальными моделями.
  • Cursor — форк VS Code с глубокой интеграцией ИИ. Удобен для pet-проектов, но не для Android: не хватает инструментов сборки и отладки. Главный минус — проект индексируется и отправляется на серверы Cursor. Прощай, безопасность. Ухожу. Но за pet-проекты — спасибо. Это единственный платный ИИ-инструмент, на который у меня подписка.
  • RooCode, ClioCode и другие расширения для VS Code — слышал много хорошего, но не пробовал. Возможно, из-за негативного опыта с Cursor.
  • Claude Code — для тех, кто чувствует себя в терминале как рыба в воде. Интерфейс — консоль. Сначала скептически отнёсся, но потом понял: всё очень нативно. Много лестных отзывов. Но я не стал устанавливать: нужно было настраивать адаптер между OpenAI и Anthropic. Плюс были сложности с установкой в Беларуси и РФ.
  • OpenCode — опенсорсный аналог Claude Code. Похожий интерфейс, те же возможности. Проблемы с устойчивостью были: сначала использовал модель без поддержки reasoning — запросы падали. Оказалось, не у одного меня. Решения: форкнуть и починить или откатиться. Я выбрал откат. Позже перешёл на модель с reasoning — и проблема исчезла.

В итоге я выбрал OpenCode.

Теперь я держал в руках лампу. Джинн дремал внутри. Готов исполнить желание. Что же я хочу?

Мне нравится писать код. Но есть рутина: перевод моделей из API в DTO, добавление Compose Preview, написание unit-тестов…

Точно. Тесты.

Все, кто работал в Альфа-Мобайл, знают: хуже, чем писать unit-тесты, может быть только писать их на Groovy. Хотя нет — ещё хуже переписывать с Groovy на Kotest.

Шутка. Надеюсь, адепты TDD не обиделись. Тесты важны. Есть люди, которым они нравятся. Я — не из их числа.

Жребий был брошен. Первое желание готово. Я ещё не знал, что впереди — два месяца экспериментов, чтобы результат стал по-настоящему магическим.

Глава 5. Первый тест комом

Что нужно для успеха? Больше контекста, решил я. Тогда я ещё не знал про context rot.

Я написал большой системный промпт, описал проект, шаблон тестов, создал md-файл с инструкциями. С чувством выполненного долга нажал «Пуск». На мгновение почувствовал себя Илоном Маском. Но, как и у него, первая ракета не взлетела. Хорошо, хоть без взрыва.

Что пошло не так?

  • Скорость — тест на простой маппер писался 20 минут.
  • Качество — вместо рабочего кода получил ошибки импорта и некомпилируемый код.
  • Игнорирование инструкций — из-за переизбытка деталей модель запуталась и начала галлюцинировать.

Попробовал запускать несколько сессий параллельно. Через 20 минут получил 5 битых тестов. Время на правки выросло.

А что, если попросить модель саму проверять тест? Стало только хуже. Выводы Gradle засоряли контекст. Модель уходила в цифровое забвение или падала из-за переполнения.

Править такие тесты вручную — долго, нудно, больно. Проще переписать с нуля.

А когда я попробовал написать тест на сложную вьюмодель — всё закончилось фиаско. Модель не понимала, какие инструменты использовать. Максимум — набросала скелет, который я потом дописал сам.

Словно рядом был подмастерье, способный только на самую грубую работу.

Как называется человек, который повторяет одни и те же действия, ожидая другого результата? Правильно — программист. В данном случае — автор статьи.

Две недели я улучшал промпты, выделял важное БОЛЬШИМИ БУКВАМИ. Но тесты не заработали. Я упустил что-то важное. Позже понял — что именно.

Глава 6. «Он ожил!»

Эксперименты пришлось отложить. Была большая задача, которую делали вдвоём. Иногда делегировал мелочи модели, но это не то, о чём я мечтал. Я хотел готовые тесты в один клик.

За это время вышли новые опенсорсные модели — мощнее и умнее. В сообществе появилось больше информации по настройке агентов и навыков. Коллега добавил крутые расширения для тестов через Kotlin DSL. Всё было готово для второй попытки.

Я снова взялся за дело.

Первое — давно хотел настроить RAG с проиндексированным проектом, чтобы ускорить поиск файлов. Можно сделать своё или использовать готовое, например, ast-index.

Второе — научить модель самой проверять и исправлять тесты. Проблема: вывод Gradle засорял контекст. Нужно было оставить только полезную информацию. Решение — написать свой фильтр или использовать rtk.

Итог: меньше шума, больше смысла. Отлично.

Дальше — структура. Я настроил систему из саб-агентов и скилов. Принцип аналогичен Claude Code и другим инструментам.

Объясняю просто: если дать мне инструкцию на 100 страниц, я запутаюсь. А если добавить закладки — шансов больше.

Всю настройку делал через саму модель. Просил её обновлять конфиги после каждой итерации. Джинн настраивал самого себя. Магия.

Я разделил задачу между тремя саб-агентами:

  • Планировщик — изучает класс, создаёт todo-лист: какие методы тестировать, на каких кейсах сосредоточиться.
  • Писатель тестов — реализует пункты из списка.
  • Ревьюер — проверяет компиляцию, полноту, соответствие стилю и требованиям.

Оркестрацией занимался основной агент. У каждого саб-агента были свои скилы с детальными инструкциями. Возникал вопрос: как OpenCode поймёт, кого вызывать? Оказалось, достаточно прописать это в конфиг. Ручной вызов тоже возможен.

Позже я понял: для простых классов основной агент справляется и без помощников. Это условие добавил в конфиг.

Последний штрих — замечание коллеги: «Не забывай про edge case, где параметр null». Внёс в скилл. Через джинна, конечно.

Всё было готово. Я выбрал тест, потёр лампу, нажал кнопку.

Результат — готовый, рабочий, компилируемый тест. Merge request прошёл ревью с замечанием по стилю. Я добавил его в скилл. Модель сама исправила тест.

Но приглядитесь. Вас что-то смущает?

Глава 7. 19 минут на тест

19 минут на тест. Скорость не выросла. Не феноменально. Но пока модель работала, я проводил 1:1 с коллегой. Так что 19 минут — нормально. Хотелось бы быстрее, но сойдёт.

Вдохновлённый, я дал модели баг. Решение не продумывал. Только указал класс и суть проблемы. Удивительно: агент повторил мои шаги. Неужели оцифровал мою идентичность?

Опять же — пока он работал, я был на звонке.

Очевидно, локальные модели уступают облачным. Разве что я не купил списанный дата-центр и не поставил его рядом с клубникой у дедушки. Но у нас растёт картошка, так что приходится довольствоваться тем, что есть.

Зато я не гнался за скоростью. Я проверял гипотезу: можно ли делегировать ИИ рутину, пока я занят. И он справился.

Токены — бесплатные (если не считать электричество), безопасность — не нарушена. Результат — более чем удовлетворительный.

UPD: за время написания статьи протестировал систему на мощных серверах. Время на тест сократилось до 5–10 минут.

Напомню цель: развить экспертизу в применении ИИ и использовать её на реальной задаче. Оба — достигнуто. Для первого раза — неплохо.

Вместо заключения: будущее уже здесь

Если вы читаете это спустя полгода (а я уже ушёл в сельское хозяйство — привет Джону Коннору), возможно, всё описанное покажется древним. Но если дочитали — статья вас зацепила.

Четыре года назад страшилки про замену программистов казались близкими. У нас даже был спор с автором Костей Рисковым на эту тему.

Сегодня ИИ-агенты постепенно проникают в компании. Полной замены нет. А громкие новости о сокращениях из-за ИИ — скорее «они свой недуг определяют в подвиг», как герой «ДМБ».

Сэм Альтман это подтверждает: ИИ — не замена, а инструмент.

Некоторые менеджеры мечтают обойтись без разработчиков. Если получится — буду рад послушать доклад. Но пока это фантазии.

Зато многие уже не представляют разработку без ИИ. Медленно, но верно агенты распространяются по компаниям.

Сравню это с распространением Kotlin Coroutines и Jetpack Compose. Сегодня есть проекты на XML и RxJava. Но стандарт — уже другой. Кто знает, может, скоро исчезнет и возможность вручную править код.

Среди программистов много скептиков. Говорят: «ИИ плохо пишет код, я буду писать сам». У меня были такие мысли полгода назад.

Но вспомнил: естественный отбор — не про сильнейших. Эволюция — за тех, кто лучше адаптируется.

Настройка ИИ-агентов — интересное инженерное занятие. Если вы скептически относитесь к ИИ — попробуйте решить с его помощью реальную задачу. Приложите весь свой опыт. Вдруг понравится?

Читать оригинал