- Использование отладчика Android Studio по максимуму
- Шаг 1 — Необходимо определить конфигурацию запуска
- Автоматизируем UI-тесты Android приложения с использование паттерна Page Object
- Подготовка проекта
- Слой тестов
- Бизнес-логика
- Описание элементов страницы
- Запуск тестов
- Что такое Android Lint и как он помогает писать поддерживаемый код
- Привет, Lint
- Привет, пользовательские проверки Lint
- Реализация
- Проблема
- Детектор
- Реестр
- Использование
- Стоит ли оно того?
Использование отладчика Android Studio по максимуму
Это хитрость, о которой я узнал совсем недавно у Senior Android разработчика в моей компании, и теперь я чувствую себя несчастным, сожалея о времени, которое я провел в ожидании сборки Gradle, чтобы проверить свои изменения при написании Android приложений.
Вот типичный сценарий, который каждый Android разработчик мог бы встретить, по крайней мере, один раз в течение своего жизненного цикла разработки. У вас есть список элементов, которые вы хотите показать в ListView или RecyclerView.
Ниже приведен наш возлюбленный метод onBindViewHolder , который связывает вашу модель с вашими view-компонентами RecyclerView.
Теперь, допустим, вы захотели изменить цвет текста для каждого третьего элемента в списке. Таким образом, код будет выглядеть примерно так:
Затем вы нажмёте Run и дождётесь завершения сборки и увидите ваши изменения, так?
Теперь вы бы подумали, существует ли другой путь для достижения этой же цели?
Твой выход, Android Studio! Да, нам не нужен внешний плагин или инструмент для достижения вышеупомянутой задачи и более того, нам даже не придется заново собирать проект. Вы не ослышались, мы обойдёмся без Gradle 🙂 Вот как!
Шаг 1 — Необходимо определить конфигурацию запуска
Такая конфигурация запуска позволит нам запускать наше приложение и присоединять к нему отладчик из Android Studio, а также вы сможете присоединить его к уже запущенному процессу.
Нажмите Run → Edit Configurations.
Edit Configurations» data-src=»https://habrastorage.org/getpro/habr/post_images/925/25e/e1a/92525ee1a0fa26e7cca96d237563c9fa.png»/>
В верхнем левом углу диалогового окна щелкните значок «+» и выберите Android App.
Теперь дайте ему имя, мне нравится называть его Run-Only, но вы можете называть его как угодно.
Выберите модуль, который содержит код вашего приложения, в приведенном ниже скриншоте он называется app.
Важный шаг:
В разделе Installation Options выберите Nothing;
В Launch Options выберите Default Activity;
В разделе Before Launch удалите Gradle-aware Make.
Таким образом, конфигурация должна выглядеть следующим образом:
Теперь вы можете применить и сохранить эту конфигурацию. Сейчас она должна быть выбрана автоматически. Если нет, то просто выберите её из списка.
Теперь поставьте breakpoint поближе к строке, которую вы хотите проверить. В нашем случае мы разместим ее там, где мы устанавливаем текст.
Щелкните правой кнопкой мыши на breakpoint и снимите флажок Suspend (рус. приостановить).
Как только вы снимете флажок, диалог расширится и покажет больше опций.
Нам интересен раздел Evaluate and log. Мы напишем там выражение, чтобы проверить изменения в нашем элементе RecyclerView. Нажмите на маленький значок голубого цвета справа от окна ввода Evaluate and log, чтобы развернуть его до более крупного редактора, и добавьте выражение для тестирования, и нажмите Ok, а затем Done.
Теперь нажмите на иконку Debug с выбранной конфигурацией Run-Only и посмотрите на эту магию.
Приложение должно запуститься с вашей Activity по умолчанию, и вы должны увидеть внесенные там изменения. Также, если вы уделяете пристальное внимание IDE, в самом низу вы увидите только одну запускаемую задачу: Launching Activity.
Хотелось бы услышать ваши впечатления, когда вы опробуете эту хитрость!
Источник
Автоматизируем UI-тесты Android приложения с использование паттерна Page Object
Паттерн Page Object появился в тестировании web и очень хорошо себя там зарекомендовал. Когда я начал автоматизировать тесты для android приложения, то первым делом подумал про него. Поискал информацию в сети, поспрашивал коллег и, в принципе, не нашел доводов не попробовать. Предлагаю посмотреть, что из этого вышло.
Классический Page Object подразумевает два уровня абстракции: элементы страницы и тесты. Я выделяю еще один — бизнес-логика. Отмечу, что то, как вы построите ваш фреймворк, будет очень сильно влиять на простоту написания тестов в будущем, а так же на их поддержку. Я стараюсь делать так, чтобы код теста выглядел как будто это обычный тест-кейс, написанный рядовым тестером. Т.е. начинаю с конца:
- Пишу красивый и понятный код тест-кейса,
- Реализую методы из тест-кейса в слое бизнес-логики,
- Описываю элементы, которые нужны для работы теста.
Данный подход хорош тем, что мы не делаем ничего лишнего — фреймворк построен на столько, на сколько это нужно для работы тестов. Можно сказать, что это концепция MVP в тестировании: быстро сделали кусочек, и он уже начал приносить пользу. Если вы сначала пишете тысячи строк, описывая страницы вашего приложения и способы взаимодействия с ними, а месяца через три вылезаете из «норы» для первого клика и осознаете, что надо было сделать все по-другому, то большая часть вашего творения будет обречена навсегда «пылиться» в подвалах git’а… Истинный тестировщик знает, что чем раньше нашел ошибку, тем дешевле ее исправлять. Используйте этот подход во всем — написал тест за пару часов, попробовал, не понравилось — выкинул, извлек урок, поехал дальше.
Итак, входные данные:
- Android приложение для торговли на бирже;
- Java, чтобы работать в одном стэке с разработчиками;
- базовый фреймворк UI Automator;
- нужно написать тест логина в приложение.
Подготовка проекта
Так как я старался максимально интегрироваться в процесс разработчиков, то новый проект создавать не стал. Согласно документации, инструментальные тесты необходимо разместить в папке src/androidTest/java . В моем случае сборщик уже был настроен, если у вас не так, то почитайте про конфигурацию билда. Также нам нужна среда разработки, Android SDK, Emulator, tools, platform-tools и необходимые платформы для эмулятора. Если вы пользуетесь Android Studio, то все это можно быстро поставить через SDK Manager:
Слой тестов
Как писал выше, будем автоматизировать тест на логин в приложении. Помним, что код должен выглядеть так же, как обычный тест-кейс:
Precondition: запустить приложение.
Step 1: осуществить логин под учетной записью myLogin/myPassword.
Step 2: проверить имя текущего пользователя.
Expected Result: текущий пользователь «Иванов Иван».
Небольшой дисклеймер: согласно лучшим практикам тест дизайна, в предусловии нужно создать/найти учетную запись. Я этот момент опустил для простоты примера.
Наш класс будет выглядеть так:
Бизнес-логика
В тесте используется класс TestApplication() и два его метода: login() и getCurrentUserName() . Плюс нужен конструктор класса (в нем запуск приложения) и метод close() Фронт работы ясен:
У экземпляра нашего класса будет две переменные:
- device , принадлежащая классу android.support.test.uiautomator.UiDevice — через нее взаимодействуем с нашим устройством;
- page , класс PageObject , который мы будем создавать в следующем разделе.
Начнем с конструктора. В нем создадим экземпляры наших переменных и запустим приложение:
Замечание: запуск приложения через android.content.Context.getTargetContext() подходит только в том случае, если ваши тесты в одном проекте с самим приложением. Если отдельно, то необходимо будет запускать через меню.
Бизнес-логика теста — это конкретные шаги, которые должен совершить пользователь для получения какого-либо значимого (для пользователя) результата. Осуществление входа под своей УЗ — значимый результат. Шаги: клик на кнопку «Login», ввести имя пользователя в поле «Login», ввести пароль в поле «Password», кликнуть на кнопку «Sign In». Таким образом, наш метод наполняется шагами:
Для получения текущего пользователя все проще, просто получаем значение поля:
А для закрытия приложения просто нажмем на кнопку Home:
Описание элементов страницы
Концепция данного слоя — он должен возвращать готовые к использованию элементы (в нашем контексте это класс android.support.test.uiautomator.UiObject2 ). Т. е., потребитель не должен переживать на счет состояния объекта, если он вернулся, то с ним сразу же можно взаимодействовать: кликать, заполнять или считывать текст. Отсюда важное следствие — в этом слое будем реализовывать ожидания:
Метод, определенный выше, будет использоваться публичным интерфейсом нашего класса PageObject . Пример для поля «Login»:
Осталось определить селектор, по которому будем находить поле. Экземпляр android.support.test.uiautomator.BySelector удобнее всего получить с помощью статических методов класса android.support.test.uiautomator.By . Я договорился с разработкой, что везде, по возможности, будут уникальные resource-id:
Инспекцию интерфейса удобно производить в утилите uiautomatorviewer, входящей в пакет tools (устанавливали в разделе Подготовка):
Выделяем нужный элемент и в разделе Node detail смотрим resource-id. Он состоит из названия пакета и, собственно, айдишника. Название пакета мы получили в конструкторе класса TestApplication , и использовали при создании объекта PageObject .
Запуск тестов
На этом все, осталось запустить. Для начала подключаемся к устройству или стартуем эмулятор. Проверим подключение командой adb devices (утилита adb входит в состав platform-tools):
Если у вас gradle, то далее делаем
и наслаждаемся как «вкалывают роботы, а не человек» (с).
Источник
Что такое Android Lint и как он помогает писать поддерживаемый код
Когда разработчик недостаточно осторожен, дела могут пойти весьма плохо. Например, классические упущения разработчика — использование новой версии API, которая не совместима со старым кодом, выполнение действий, которые требуют специальных пользовательских разрешений, пробелы в локализации приложения. И это только некоторые из них.
Кроме того, в Java и Kotlin, как и в любых других языках программирования, есть свои собственные конструкции, которые могут привести к снижению производительности.
Привет, Lint
Мы используем инструмент под названием Lint (или Linter) для избежания таких проблем. Lint — это инструмент для статического анализа кода, который помогает разработчикам изловить потенциальные проблемы ещё до того, как код скомпилируется. Lint выполняет многократные проверки исходного кода, которые могут обнаружить такие проблемы, как неиспользуемые переменные или аргументы функций, упрощение условий, неправильные области видимости, неопределённые переменные или функции, плохо оптимизированный код и т.д. Когда мы говорим о разработке для Android, существуют сотни проверок Lint, доступных «из коробки».
Но иногда нам нужно найти конкретные проблемы в нашем коде, которые не охватываются этими существующими проверками.
Привет, пользовательские проверки Lint
Прежде чем мы начнем кодить, давайте определим нашу цель и посмотрим, как реализовать её шаг за шагом с помощью Lint API. Цель состоит в том, чтобы создать проверку для обнаружения неправильного вызова метода для объекта. Идея этой проверки состоит в том, чтобы определить, является ли метод установки слушателя на View-компонент таким, который будет прерывать несколько последовательных кликов по компоненту, чтобы мы могли избежать открытия одной и той же Activity или обращения к сети несколько раз.
Пользовательские проверки Lint написаны как часть стандартного модуля Java (или Kotlin). Самый простой способ начать — создать простой проект на основе Gradle (это не обязательно должен быть проект Android).
Затем добавим зависимости Lint. В файле build.gradle вашего модуля добавьте:
Теперь есть хитрость, о которой я узнал, исследуя эту тему. lintVersion должен быть gradlePluginVersion + 23.0.0 . gradlePluginVersion — это переменная, определённая в файле build.gradle на уровне проекта. И на данный момент последняя стабильная версия — 3.3.0. Это означает, что lintVersion должен быть 26.3.0.
Каждая проверка Линт состоит из 4 частей:
- Проблема — проблема в нашем коде, которую мы пытаемся предотвратить. Когда проверка Lint завершается неудачей, то об этом сообщается разработчику.
- Детектор — инструмент для поиска проблемы, который предоставляет API Lint.
- Реализация — область, в которой может возникнуть проблема (исходный файл, файл XML, скомпилированный код и т.д.).
- Реестр — настраиваемый реестр проверок Lint, который будет использоваться вместе с существующим реестром, содержащим предопределённые проверки.
Реализация
Давайте начнём с создания реализации для нашей пользовательской проверки. Каждая реализация состоит из класса, который реализует детектор и область действия.
Помните, что Scope.JAVA_FILE_SCOPE также будет работать для классов Kotlin.
Проблема
Следующим шагом является использование этой реализации для определения проблемы. Каждая проблема состоит из нескольких частей:
- ID — уникальный идентификатор.
- Описание — краткое (5-6 слов) изложение проблемы.
- Объяснение — полное объяснение проблемы с предложением, как это исправить.
- Категория — категория проблемы (производительность, перевод, безопасность и т.д.).
- Приоритет — важность проблемы, в диапазоне от 1 до 10, где 10 является самым высоким. Это будет использоваться для сортировки проблем в отчёте, созданном при запуске Lint.
- Серьёзность — серьёзность проблемы (фатальная, ошибка, предупреждение, информация или игнорирование).
- Реализация — реализация, которая будет использоваться для обнаружения этой проблемы.
Детектор
Lint API предлагает интерфейсы для каждой области, которую вы можете определить в реализации. Каждый из этих интерфейсов предоставляет методы, которые вы можете переопределить и получить доступ к интересующим вас частям кода.
- UastScanner — файлы Java или Kotlin (UAST — Unified Abstract Syntax Tree (рус. унифицированное абстрактное синтаксическое дерево)).
- ClassScanner — скомпилированные файлы (байт-код).
- BinaryResourceScanner — двоичные ресурсы, такие как растровые изображения или файлы res/raw .
- ResourceFolderScanner — папки ресурсов (не конкретные файлы в них).
- XmlScanner — XML-файлы.
- GradleScanner — Gradle-файлы.
- OtherFileScanner — всё остальное.
Кроме того, класс Detector является базовым классом, который имеет пустые реализации всех методов, предоставляемых каждым из вышеперечисленных интерфейсов, поэтому вам не нужно реализовывать полный интерфейс в случае, если вам нужен только один метод.
Теперь мы готовы реализовать детектор, который будет проверять правильный вызов метода для объекта.
Реестр
Последнее, что нам нужно сделать, это добавить проблемы в наш реестр и сообщить Lint, что существует специальный реестр проблем, который он должен использовать наряду со стандартным.
В build.gradle уровня модуля:
где co.infinum.lint — это пакет класса MyIssueRegistry . Теперь вы можете запустить задачу jar , используя скрипт gradlew , и библиотека должна появиться в каталоге build/libs .
Здесь есть ещё один пример пользовательской проверки Lint, где вы можете увидеть, как обрабатывать XML-файлы.
Использование
Ваша новая проверка Lint готова к использованию в проекте. Если эту проверку можно применить ко всем проектам, вы можете поместить её в папку
/.android/lint (вы можете создать её, если она ещё не существует).
Кроме того, вы можете вынести свою проверку в отдельный модуль в своём проекте и включить этот модуль как любую другую зависимость, используя метод lintChecks .
Стоит ли оно того?
Lint — действительно хороший инструмент, который следует использовать каждому разработчику. Возможность обнаружить потенциальные проблемы с вашим кодом на раннем этапе очень полезна. Хотя настраиваемые проверки писать не так просто, в основном из-за сложности API, они определённо стоят того и могут сэкономить много времени и усилий в будущем.
Источник