- PVSM.RU - https://www.pvsm.ru -

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

Quality pipelines в мобильной разработке, часть 1: Android - 1
фото с Unsplash по запросу "pipeline"

Общий подход

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

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

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

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

Quality pipelines в мобильной разработке, часть 1: Android - 2

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

Quality pipelines в мобильной разработке, часть 1: Android - 3

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

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

Android Studio

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

Quality pipelines в мобильной разработке, часть 1: Android - 4
Настройки инспекций в Android Studio

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

Quality pipelines в мобильной разработке, часть 1: Android - 5
Пример быстрого исправления от Android Studio

Android Lint

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

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

Quality pipelines в мобильной разработке, часть 1: Android - 6
Пример отчёта от Android Lint

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

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

Quality pipelines в мобильной разработке, часть 1: Android - 7
Пример отчёта от FindBugs

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Quality pipelines в мобильной разработке, часть 1: Android - 8
Пример отчёта на bitrise.io

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

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

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

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

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

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

Автор: Владимир Иванов

Источник [26]


Сайт-источник PVSM.RU: https://www.pvsm.ru

Путь до страницы источника: https://www.pvsm.ru/android/337309

Ссылки в тексте:

[1] Room: https://developer.android.com/topic/libraries/architecture/room

[2] Timber: https://github.com/JakeWharton/timber

[3] доклад: https://mobiusconf.com/en/2019/msk/talks/cfbaqtxfqyvuikcyhvxn1/?utm_source=habr&utm_medium=476624&utm_campaign=mobius19msc

[4] Java: https://blog.codacy.com/review-of-java-static-analysis-tools/

[5] Kotlin: https://proandroiddev.com/kotlin-static-analysis-why-and-how-a12042e34a98

[6] PMD: https://pmd.github.io/

[7] FindBugs: http://findbugs.sourceforge.net/

[8] SpotBugs: https://spotbugs.github.io/

[9] Checkstyle: http://checkstyle.sourceforge.net/

[10] Ktlink: https://ktlint.github.io/

[11] Detekt: https://github.com/arturbosch/detekt

[12] EPAM Systems: https://www.epam.com/

[13] здесь: https://vizteck.com/blog/benefits-using-sonarqube/

[14] гриба тестирования: https://automationrhapsody.com/what-is-the-test-mushroom-and-how-to-improve-your-testing/

[15] jacoco: https://www.eclemma.org/jacoco/

[16] Mobile Security Framework: https://github.com/MobSF/Mobile-Security-Framework-MobSF

[17] список: https://www.owasp.org/index.php/Source_Code_Analysis_Tools

[18] Find Security Bugs: https://find-sec-bugs.github.io/

[19] OWASP SonarCube Project: https://www.owasp.org/index.php/OWASP_SonarQube_Project

[20] здесь: https://medium.com/@alistair.cerio/android-ktlint-and-pre-commit-git-hook-5dd606e230a9

[21] докладом: https://www.youtube.com/watch?v=r7bb1jv4I1A

[22] в Твиттере: http://twitter.com/vvsevolodovich

[23] Mobius: https://mobiusconf.com/?utm_source=habr&utm_medium=476624&utm_campaign=mobius19msc

[24] vixentael: https://medium.com/@vixentael

[25] Алексею Никитину: https://medium.com/@nikialeksey

[26] Источник: https://habr.com/ru/post/476624/?utm_source=habrahabr&utm_medium=rss&utm_campaign=476624