Как стать автором
Обновить
297.93
TINKOFF
IT’s Tinkoff — просто о сложном

Автоматическая проверка качества Java-кода (итерация 1)

Время на прочтение6 мин
Количество просмотров6.7K
Инспектор
Данный цикл статей я планирую, как историю в нескольких частях о том, как настраивается автоматическая проверка качества кода в нашем проекте. Процесс этот, вроде бы простой, оказался полным неочевидных деталей, так что появилось желание разъяснить подстерегаютщие трудности и их решения широкой аудитории, чтобы все могли сделать свой код чуть лучше, обойдя побольше грабель.

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

В этой итерации, я буду настраивать проверку инспекций. Мы всей командой используем IntelliJ IDEA и TeamCity компании JetBrains, поэтому можно использовать те средства, которые они предоставляют. Для начала в IntelliJ IDEA будет настроен профиль инспекций, соответствие кода которому будет проверяться при каждой сборке при помощи TeamCity. Метод это штатный и описан в официальной базе знаний по TeamCity, но не всё получалось очень гладко…

Для начала надо определиться, что же проверять, для этого запустим IntelliJ IDEA, откроем проект и найдём настройки (Settings). Теперь перейдём в раздел инспекции (Inspections), для чего удобно воспользоваться поиском. В результате перед вами предстанет такая картина — полный список инспекций, разделённый по группам (синим выделены инспекции, настройки которых отличаются от стандартных):

Выбор инспекций

Тут большое поле для творчества: каждой инспекции можно сопоставить серьёзность, с которой она будет оцениваться. Простое включение всех инспекций не заставит писать код идеально без включения мозга. Инспекции только дадут почувствовать плохие запахи раньше. Так существуют абсолютно противоположные инспекции, например, «Constant on left side of comparison» и «Constant on right side of comparison». Выбор тут зависит от ваших предпочтений и от тех стандартов, которые вы собираетесь поддерживать. Инспекций действительно очень много, полный проход займёт несколько часов, так что не забудьте запастись хорошим чаем.

Из полезных примечательных инспекций:
  • I/O resource opened but not safely closed — позволит проверить, что для всех открытых ресурсов вызывается close и притом в нужном месте (аналогично с JDBC, JNDI и nio);
  • Missing Override annotation — я пофорсил жёстко, чтобы обрабатывалось как ошибка, потому что этими самыми ошибками и чревато (недаром в Scala для подобной декларации используется обязательное ключевое слово);
  • Iteration over 'keySet()' may be replaced with 'entrySet()' iteration — как ни странно немногие задумываются, что второй способ быстрее и вообще существует;
  • Chain of 'instanceof' checks — позволяет намекнуть злостным нарушителям LSP, что можно жить по-другому;
  • Overly long method, Class with too many methods — позволяют следить, что методы и классы вовремя разбиваются и помещаются на разумном числе экранов.
Когда необходимый набор инспекций выбран, ему лучше всего назначить собственное имя и можно экспортировать его нажатием кнопки Export, самой правой в верхнем ряду. Дальше выбираем место куда сохранить xml-файл с профилем. Я сохранил файл сразу в папку проекта, чтобы загрузить его в систему контроля версий и использовать дальше, при настройке TeamCity.

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

Итак, мы перешли к настройке TeamCity. TeamCity позволяет собирать проект большим количеством разных способов. Для разных способов используются т.н. Runners: Maven, Ant и ещё около десятка. В их числе есть специальный — Inspections Runner. Для того, чтобы его использовать, надо создать отдельную конфигурацию сборки (Configuration) или добавить шаг (Build step) к существующей. На рисунке ниже показана заполненная форма для этого шага:

Настройка Inspections runner

У нас Maven-проект, и для меня было сюрпризом найти: «The specified path should be relative to the checkout directory. Should reference either project file (.ipr) or project directory for directory-based (.idea) projects.», благо в документации на этот счёт всё ясно: «For Maven2 project: path to the pom.xml file.». Мы у себя собираем один из модулей (tinkoff-portal-web) многомодульного Maven-проекта, поэтому указываем путь к pom-файлу в нём. Working Directory, соответственно, тоже надо поправить.

Ещё один интересный момент: потребление памяти. Без увеличения стандартного максимально выделяемого размера памяти и размера Permanent Generation, проверка инспекций будет падать. В новых версиях TeamCity, например, в установленной у нас 6.5.6 в поле JVM command line parameters заранее вписано:
-Xmx512m -XX:MaxPermSize=150m

В том же поле можно заставить TeamCity проверять или не проверять определённые пакеты, например, не очень интересно смотреть, какие претензии есть к стабам, сгенерированным для работы с веб-сервисами, поэтому мы смотрим только на классы, которые сами написали (для Maven, как видно, путь указывается относительно корня проверяемого модуля):
-Didea.include.patterns=src/main/java/ru/tcsbank/portal/*

Следующий пункт — путь к нашему xml-файлу с профилем инспекций. Поскольку путь надо указывать относительно рута, а проект может собираться на разных агентах и, соответственно, в разных папках. В теории, можно положить файл с профилем на сервер сборки в отдельное сакральное место, но менять его тогда будет крайне затруднительно (что, кстати, может быть даже разумно с какой-то стороны), мне же хотелось иметь возможность оперативно корректировать выполняемые проверки. Путём экспериментов и вывода в лог всех подходящих по названию параметров окружения, был найден рецепт:
%system.teamcity.build.checkoutDir%/tcsInspectionsProfile.xml

Теперь осталось указать только название профиля, которое мы задали при сохранении в IDEA и количество предупреждений и ошибок, которые мы считаем смертельными — при которых, проект перестаёт собираться.
Изначально, я брал количество чуть большее, чем общее число непройденных проверок, затем, по мере улучшения качества кода, это количество уменьшалось и продолжает уменьшаться.

Итак, запускаем нашу сборку и видим, что-то в этом духе:

Что же, теперь мы всегда знаем улучшил ли коммит качество кода или ухудшил.

В завершение хочется сказать, что TeamCity скорее предназначается для сборки проектов IntelliJ IDEA, чем Maven, это несёт ряд ограничений: не проверяются стили кода, вдобавок к Maven загружается экземпляр IDEA на сервере (при сборке пробегает строка «Starting up IntelliJ IDEA 10.5.2…») и ещё… Inspection Runner странно себя ведёт на некоторых типах инспекций, например был случай, когда «Unused import» считал неиспользуемым класс, который использовался для создания анонимного наследника. Такие инспекции, к большому сожалению, пришлось отключить, чтобы не компрометировать правильность проверки.

Последующий выбор инспекций можно проводить вместе с командой по методу Pizza-Driven-Development :)

В следующей итерации я планирую попробовать использовать «IntelliJ IDEA Project» runner, есть надежда, что это позволит сборке проходить побыстрее и исправит проблемы с точностью инспекций и позволит отказаться от постоянных reimport’ов профиля инспекций.
Теги:
Хабы:
0
Комментарии2

Публикации

Информация

Сайт
www.tinkoff.ru
Дата регистрации
Дата основания
Численность
свыше 10 000 человек
Местоположение
Россия