Хабрахабр

[Перевод] Quality pipelines в мобильной разработке, часть 1: Android


фото с Unsplash по запросу "pipeline"

Общий подход

Я начинаю серию постов о пайплайнах в разработке и не только, которые помогают удостовериться в качестве разрабатываемых мобильных приложений. Привет! Я начну с Android, но сначала хотел бы дать общее представление, о чём это всё. Главная идея в том, чтобы осветить все подходы к мобильной разработке, актуальные сейчас: нативную разработку для Android и iOS, React Native, Xamarin и Flutter.

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

Ради чего это всё?

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

Я не говорю, что есть серебряная пуля, избавляющая от всех багов — это невозможно. Много часов труда можно было бы сэкономить, если бы у вас были механизмы, предотвращающие появление багов в самом начале. Но что возможно, так это воздвигнуть барьеры (также известные как quality gates), повышающие вероятность отловить баги в вашем коде как можно раньше.

На компьютере разработчика

Давайте посмотрим, что существует для Android-разработчиков. Вы как разразботчик всегда работаете на своей машине с IDE и инструментами командной строки.

Android Studio

Советую договориться в команде о конкретных правилах, которые вы хотите использовать, сконфигурировать их на одном компьютере и закинуть файл settings.jar с этими правилами в вашу систему контроля версий или какой-либо инструмент коллаборативной работы (вроде Confluence). Это сейчас вариант по умолчанию для Android-разработчика, и поскольку он основан на платформе IntelliJ, там есть множество инспекций для Java, Kotlin и XML.


Настройки инспекций в Android Studio

В AS также есть быстрые исправления, которые можно применить к своему коду по нажатию Alt+Enter.


Пример быстрого исправления от Android Studio

Android Lint

Lint может и запускаться из Gradle-задачи (task), и давать подсказки прямо в Android Studio, и генерировать отчёт. Это инструмент статического анализа конкретно для Android-разработки, «из коробки» снабжённый сотнями правил, любые из которых вы можете использовать. У него множество проверок, разделённых по категориям — безопасность, интернационализация, юзабилити, производительность...

Например, у Room есть свой набор правил, у библиотеки логирования Timber — свой. Но особенно мощным его делает возможность добавлять свои собственные правила. (Кстати, скоро на конференции Mobius будет доклад об этом, объясняющий и теоретическую сторону, и практическую). Можно создать правила для вашей команды или проекта и быть уверенным, что никто не совершает определённые типичные ошибки.


Пример отчёта от Android Lint

Ещё статический анализ

Выберите себе по душе, интегрируйте его в свой пайплайн и обеспечьте его реальное использование (как именно? Конечно, есть много инструментов статического анализа, предназначенных не конкретно для Android, а в целом для Java и Kotlin: PMD, FindBugs (заброшен, используйте SpotBugs), Checkstyle, Ktlink, Detekt и другие. читайте дальше).


Пример отчёта от FindBugs

Вам также пригодится следующая информация: Но недостаточно наличия инструмента, предоставляющего данные о том, что надо поправить.

  1. Как изменяется со временем покрытие кода тестами?
  2. Сколько времени мне потребуется для исправления всех найденных проблем?
  3. Сколько в проекте дублирующегося кода?
  4. Как мне распространить свои правила на несколько команд?

Мы в EPAM Systems уделяем внимание качеству, поэтому выбрали SonarQube как инструмент для ответов на эти вопросы. И многие другие. О других преимуществах SonarQube можно узнать здесь.

Юнит-тестирование

Не имеет значения, следуете ли вы TDD, придерживаетесь принципа пирамиды тестирования или новой идеи гриба тестирования. Надеюсь, не требуется вновь убеждать вас, что вашему коду, чёрт возьми, требуются юнит-тесты по различным причинам. А значит, вам надо их писать и запускать! Не так важно, какой уровень покрытия вы ставите целью, в любом случае ваши юнит-тесты — необходимая составляющая. К счастью, за 11 лет эволюции мы получили довольно удобный механизм запуска тестов из Gradle и Android Gradle-плагина.

Убедитесь, что её используют и что покрытие кода со временем растёт. В андроид гредл-проекте по умолчанию есть задача testDebugUnitTest (у вас она, естественно, может отличаться в зависимости от флейворов), и именно она запускает тесты. Плюс Java юнит-тестов в том, что они работают на JVM рабочей станции, а не на Dalvik/ART, что даёт преимущество в скорости.

Это одна из причин, по которым появились все эти подходы к UI-слою вроде MVP, MVVM, MVI и прочие MV*. В случае с андроидными юнит-тестами есть одна фундаментальная проблема: зависимость от Android SDK. Конечно, существует пара вариантов: либо пропустить тесты для этого класса, либо извлечь часть логики в другие классы, либо создавать интерфейсы для Android-зависимых классов для тестирования какой-то высокоуровневой логики, либо использовать Robolectric (что далеко от идеала). Конкретная проблема в зависимости класса от Android в том, что юнит-тесты просто падают из-за использования стабов этого самого Android, которые просто бросают исключение. Другой вариант — использовать инструментированные тесты, которые могут подходить для проверки поведения Activity, но современный тренд в том, что Activity не должна содержать тестов.

Насколько мне известно, jacoco — индустриальный стандарт для Java, и у него есть поддержка Kotlin. К вопросу о покрытии: вы хотите знать, какое оно у вас в данный момент и как меняется со временем, так что вам пригодился бы инструмент и для этого.

Инструментированные тесты

К сожалению, они медленные и нестабильные (из-за некоторых проблем с эмулятором), так что большинство известных лично мне разработчиков старается их избегать. Эти тесты запускаются на эмуляторе Android, что позволяет им использовать Android Framework. Но их поддержка есть в Gradle и Android Studio, так что для вас они, может, и подойдут.

Аудит безопасности

Конечно, Android Lint уже предоставляет некоторые соответствующие подсказки, но лучше озаботиться специализированными инструментами конкретно для этой задачи. Помимо простых ошибок, опечаток, проблем при копипейсте и тому подобного, есть ещё и большая категория проблем, на которую вам стоит обращать внимание: безопасность. Возможно, вы захотите начать, например, с Mobile Security Framework, а позже рассмотреть платные варианты. Эти инструменты могут работать как в статическом, так и в динамическом режимах; в зависимости от ваших требований к безопасности вы можете хотеть использовать как один из этих режимов, так и оба.

Например, можете выбрать Find Security Bugs или использовать OWASP SonarCube Project. К счастью, есть список инструментов статического анализа, составленный непосредственно OWASP.

Удостовериться в выполнении проверок

Так что хочется быть уверенным, что код соответствует продакшн-качеству ещё до того, как он попадёт в репозиторий или даже будет закоммичен локально. Как я уже сказал, чем короче цикл фидбека, тем меньше времени и денег вы тратите на исправление багов. Конечно, можно просто попросить своих разработчиков выполнять проверки, но есть вариант куда лучше: Git hooks.

Пример процесса настройки можно найти здесь. Я предлагаю добавить pre-commit hook для всех проверок, которые мы обсудили выше: Lint, статического анализа кода и юнит-тестов.

CI/CD-пайплайн

Ваша цель — повторить все вышеописанные проверки ещё и на этапе сборки. Очень сложно представить Android-проект без CI/CD-пайплайна. На то есть несколько причин:

  1. Git hooks можно легко обойти с помощью параметра '--no-verify'
  2. Код может успешно проходить все проверки локально, но вносить проблемы уже после merge
  3. Вам нужны отчёты о тестах и покрытии


Пример отчёта на bitrise.io

Если у вас есть сложности с выстраиванием пайплайна, недавно на конференции DevOops я выступил с докладом о мобильном DevOps в 2019-м. К счастью, вам достаточно или упомянуть эти проверки безопасности непосредственно в билд-скрипте Gradle, или вызывать соответствующие задачи в вашем CI/CD-пайплайне.

Пожалуйста, делайте также следующее:

  1. Прогоняйте все проверки для пулл-реквестов. Не позволяйте мерджить ни один реквест, нарушающий любое из правил. Это очень важно: если правило не выполняется, то оно, по сути, не существует.
  2. Прогоняйте все проверки при сборке и деплое. Вы не хотите понижать свою планку качества.
  3. Если билд сломался — это первоочередная задача. Команда должна исправить проблему немедленно, потому что она нарушает вашу практику continuous delivery и не даёт команде писать качественный код.

И удачи в улучшении своего кода!

А если вы в декабре будете в Москве или можете приехать, приходите на нашу конференцию Mobius и узнайте много другого о разработке для Android (и iOS)! Если вам понравилась эта статья, подписывайтесь на меня в Твиттере, чтобы не пропустить следующие.

S. P. Спасибо vixentael за подходы к вопросам безопасности, Алексею Никитину за ревью и комментарии, Александру Баканову за пруфридинг.

Теги
Показать больше

Похожие статьи

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *

Кнопка «Наверх»
Закрыть