Что такое ReDroid?
ReDroid — это легковесная альтернатива стандартному эмулятору Android, работающая как Docker-контейнер. ReDroid предоставляет полноценную Android-систему в контейнере, позволяя значительно сократить время запуска и потребление ресурсов по сравнению с традиционными эмуляторами.
ReDroid использует ядро Linux хост-системы и работает на базе проекта anbox-модуля, что обеспечивает запуск Android без виртуализации процессора. Это делает его идеальным решением для автоматизированного тестирования Android-приложений в среде CI/CD, где скорость и эффективность имеют решающее значение.
Сравнение с эмулятором Android Studio:
ReDroid идеально подходит для автоматизированного UI-тестирования в CI/CD, особенно когда важна скорость и эффективность использования ресурсов. Стандартный эмулятор Android Studio более подходит для локальной разработки, отладки и тестирования, требующего полной эмуляции возможностей устройства.
Ручное тестирование
Запустите контейнер ReDroid (Docker) и подождите около минуты для его загрузки:
docker run -d --name redroid --privileged -p 5555:5555 redroid/redroid:15.0.0_64only-latest sleep 30
Подключитесь к запущенному контейнеру через ADB:
adb connect localhost:5555 adb devices
Установите на ReDroid оба APK-файла:
adb -s localhost:5555 install ./app/build/outputs/apk/debug/app-debug.apk adb -s localhost:5555 install ./app/build/outputs/apk/androidTest/debug/app-debug-androidTest.apk
Запустите ваши Espresso/UI-тесты с ADB:
adb -s localhost:5555 shell am instrument -w your.package.name.test/androidx.test.runner.AndroidJUnitRunner
Выгрузите логи после тестирования:
adb -s localhost:5555 logcat -d > android-log.txt
После завершения тестов удалите контейнер:
docker stop redroid && docker rm redroid
Подготовка Android-проекта для UI-тестирования
Шаг 1: Настройка зависимостей в app/build.gradle
gradle
android { defaultConfig { testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" } } dependencies { // Основные компоненты для UI-тестирования androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1' androidTestImplementation 'androidx.test:runner:1.5.2' androidTestImplementation 'androidx.test:rules:1.5.0' // Дополнительные библиотеки Espresso для расширенного тестирования androidTestImplementation 'androidx.test.espresso:espresso-contrib:3.5.1' androidTestImplementation 'androidx.test.espresso:espresso-intents:3.5.1' // JUnit для интеграции с тестовым окружением androidTestImplementation 'androidx.test.ext:junit:1.1.5' }
Шаг 2: Создание примера UI-теста с Espresso
Создайте файл app/src/androidTest/java/com/example/app/MainActivityTest.java:
java
package com.example.app; import androidx.test.espresso.matcher.ViewMatchers; import androidx.test.ext.junit.rules.ActivityScenarioRule; import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.filters.LargeTest; import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import static androidx.test.espresso.Espresso.onView; import static androidx.test.espresso.action.ViewActions.click; import static androidx.test.espresso.assertion.ViewAssertions.matches; import static androidx.test.espresso.matcher.ViewMatchers.isDisplayed; import static androidx.test.espresso.matcher.ViewMatchers.withId; import static androidx.test.espresso.matcher.ViewMatchers.withText; @RunWith(AndroidJUnit4.class) @LargeTest public class MainActivityTest { @Rule public ActivityScenarioRule<MainActivity> activityRule = new ActivityScenarioRule<>(MainActivity.class); @Test public void welcomeTextIsDisplayed() { // Проверка, что текстовое поле с приветствием отображается onView(withId(R.id.welcome_text)) .check(matches(isDisplayed())) .check(matches(withText("Hello World!"))); } @Test public void buttonClickChangesText() { // Нажатие на кнопку onView(withId(R.id.action_button)) .perform(click()); // Проверка, что текст изменился onView(withId(R.id.welcome_text)) .check(matches(withText("Button Clicked!"))); } }
Настройка Jenkins для автоматизации UI-тестов с ReDroid
Шаг 1: Установка необходимых плагинов в Jenkins
В интерфейсе Jenkins перейдите в раздел «Настроить Jenkins» > «Управление плагинами» и установите:
-
Docker Pipeline
-
Gradle Plugin
-
HTML Publisher Plugin
-
JUnit Plugin
-
Allure Jenkins Plugin (опционально для улучшенной отчетности)
Шаг 2: Создание Jenkinsfile для пайплайна
Создайте файл Jenkinsfile в корне проекта:
groovy
pipeline { agent any environment { // Переменные окружения ANDROID_HOME = '/opt/android-sdk' REDROID_IMAGE = 'redroid/redroid:15.0.0_64only-latest' REDROID_CONTAINER = 'android-ui-test-container' ADB_PORT = '5555' TEST_RESULTS_DIR = 'app/build/outputs/androidTest-results' TEST_REPORT_DIR = 'app/build/reports/androidTests' } stages { stage('Checkout') { steps { checkout scm } } stage('Build APKs') { steps { sh './gradlew clean assembleDebug assembleDebugAndroidTest' } } stage('Start ReDroid Container') { steps { script { // Остановка и удаление контейнера, если он существует sh "docker stop ${REDROID_CONTAINER} || true" sh "docker rm ${REDROID_CONTAINER} || true" // Запуск ReDroid в Docker sh """ docker run -d --name ${REDROID_CONTAINER} \ --privileged \ -p ${ADB_PORT}:${ADB_PORT} \ -e REDROID_PROP_ro.debuggable=1 \ -e REDROID_PROP_service.adb.tcp.port=${ADB_PORT} \ ${REDROID_IMAGE} """ // Ожидание запуска ReDroid sh "sleep 30" } } } stage('Connect to ReDroid and Install APKs') { steps { script { // Подключение к устройству через ADB sh "adb connect localhost:${ADB_PORT}" sh "adb devices" // Ожидание полной загрузки системы sh "adb wait-for-device" // Установка APK приложения и тестов sh "adb -s localhost:${ADB_PORT} install -r app/build/outputs/apk/debug/app-debug.apk" sh "adb -s localhost:${ADB_PORT} install -r app/build/outputs/apk/androidTest/debug/app-debug-androidTest.apk" } } } stage('Run UI Tests') { steps { script { // Создание директорий для результатов sh "mkdir -p ${TEST_RESULTS_DIR}" // Получение имени пакета приложения def packageName = sh( script: "aapt dump badging app/build/outputs/apk/debug/app-debug.apk | grep package | awk '{print \$2}' | sed s/name=//g | sed s/\\'//g", returnStdout: true ).trim() // Запуск UI-тестов sh """ adb -s localhost:${ADB_PORT} shell am instrument -w \ -e debug false \ -e junit.output.format=xml \ -e additionalTestOutputDir=/sdcard/test-results \ ${packageName}.test/androidx.test.runner.AndroidJUnitRunner """ // Копирование результатов с устройства sh "adb -s localhost:${ADB_PORT} pull /sdcard/test-results ${TEST_RESULTS_DIR}" // Сбор логов sh "adb -s localhost:${ADB_PORT} logcat -d > ${TEST_RESULTS_DIR}/device-log.txt" // Сделать скриншот для диагностики (опционально) sh "adb -s localhost:${ADB_PORT} shell screencap -p /sdcard/screen.png" sh "adb -s localhost:${ADB_PORT} pull /sdcard/screen.png ${TEST_RESULTS_DIR}/" } } } } post { always { // Публикация JUnit-результатов junit "${TEST_RESULTS_DIR}/**/*.xml" // Публикация отчетов тестирования publishHTML([ allowMissing: true, alwaysLinkToLastBuild: true, keepAll: true, reportDir: "${TEST_REPORT_DIR}/connected", reportName: 'Espresso Test Report', reportFiles: 'index.html' ]) // Остановка и удаление контейнера script { sh "docker stop ${REDROID_CONTAINER} || true" sh "docker rm ${REDROID_CONTAINER} || true" } // Очистка ADB sh "adb disconnect localhost:${ADB_PORT} || true" // Архивация артефактов archiveArtifacts artifacts: "${TEST_RESULTS_DIR}/**/*", allowEmptyArchive: true } } }
Scrcpy
Scrcpy — это легковесная бесплатная утилита с открытым исходным кодом для отображения и управления экраном Android-устройств на компьютере. Работает по USB (ADB) или по Wi-Fi без каких-либо мобильных приложений на стороне устройства.
Примеры использования:
-
Подключение и запуск (устройство подключено по USB):
scrcpy
-
Подключение через Wi-Fi (зная IP-адрес устройства):
adb connect 192.168.1.5:5555 scrcpy -s 192.168.1.5:5555
-
Изменение разрешения видео:
scrcpy -m 1024
-
Запись видео с устройства:
scrcpy --record file.mp4
-
Управление устройством без отображения экрана (только ввод с клавиатуры и мыши):
scrcpy -N
Если вам нужен визуальный контроль за процессом выполнения тестов, можно интегрировать Scrcpy в пайплайн:
groovy
stage('Visual Debug with Scrcpy') { when { expression { return params.ENABLE_VISUAL_DEBUG } } steps { script { // Установка Scrcpy, если еще не установлена sh ''' if ! command -v scrcpy &> /dev/null; then apt-get update && apt-get install -y scrcpy fi ''' // Запуск Scrcpy для записи видео процесса тестирования sh "mkdir -p ${TEST_RESULTS_DIR}/recordings" for (int i = 0; i < DEVICE_COUNT; i++) { def adbPort = BASE_ADB_PORT + i sh """ nohup scrcpy --no-display --record=${TEST_RESULTS_DIR}/recordings/device-${i}-recording.mp4 \ --serial=localhost:${adbPort} & """ } // Ограничение длительности записи sh "sleep 60" // Запись первой минуты тестирования sh "pkill scrcpy || true" } }
Kubernetes
Зачем использовать ReDroid в Kubernetes
ReDroid в Kubernetes упрощает тестирование Android-приложений. Вот главные плюсы:
Параллельные тесты — запускаешь сразу много виртуальных Android-устройств и экономишь время на тестировании.
Меньше расходов на ресурсы — ReDroid легкий, а Kubernetes грамотно распределяет нагрузку между серверами.
Автоматическое управление — система сама запускает, перезапускает и останавливает Android-контейнеры без твоего участия.
Простая связь с CI/CD — легко встраивается в существующие пайплайны Jenkins или GitLab CI.
Изоляция тестов — каждое тестовое окружение работает независимо, без помех другим тестам.
Централизованное управление — все контролируется через один интерфейс.
Экономия бюджета — виртуальные устройства вместо дорогих реальных телефонов.
Одинаковые условия — все тесты в одинаковой среде, что повышает надежность результатов.
Доступ к аппаратному ускорению — можно настроить использование GPU для лучшей производительности.
Это решение подходит командам, которым нужно регулярно тестировать Android-приложения в разных конфигурациях быстро и предсказуемо.
apiVersion: apps/v1 kind: StatefulSet metadata: name: redroid-farm namespace: android-testing spec: serviceName: "redroid" replicas: 3 # Количество параллельных экземпляров устройств selector: matchLabels: app: redroid-device template: metadata: labels: app: redroid-device spec: securityContext: runAsUser: 0 # Запуск от имени root containers: - name: redroid image: redroid/redroid:15.0.0_64only-latest securityContext: privileged: true # Требуется для redroid ports: - containerPort: 5555 name: adb env: - name: REDROID_PROP_ro.debuggable value: "1" - name: REDROID_PROP_service.adb.tcp.port value: "5555" - name: ANDROID_ARCH value: "x86_64" resources: requests: cpu: 2 memory: 3Gi limits: cpu: 4 memory: 6Gi volumeMounts: - name: dri mountPath: /dev/dri - name: kvm mountPath: /dev/kvm lifecycle: preStop: exec: command: ["/system/bin/reboot", "-p"] volumes: - name: dri hostPath: path: /dev/dri - name: kvm hostPath: path: /dev/kvm nodeSelector: hardware-acceleration: "true" # Выбор узлов с GPU/аппаратным ускорением
Wireshark и ReDroid: перехват и анализ сетевого трафика Android-приложений
Wireshark в сочетании с ReDroid предоставляет инструментарий для тестирования и отладки сетевого взаимодействия Android-приложений. Эта комбинация особенно полезна для анализа API-запросов, проверки безопасности соединений и отладки проблем с сетью.
Основные возможности:
Наблюдение за реальным трафиком — Wireshark позволяет видеть все сетевые пакеты, которыми обменивается Android-приложение в ReDroid с внешними сервисами.
Простота настройки — поскольку ReDroid работает как Docker-контейнер, его сетевой трафик легко перехватывается через Docker-сеть без дополнительных инструментов на самом устройстве.
Анализ защищенного трафика — при правильной настройке можно исследовать даже HTTPS-трафик (с использованием инструментов типа mitmproxy для ReDroid).
Поиск проблем производительности — легко выявлять медленные запросы и задержки в работе приложения по сетевым данным.
Автоматизированное тестирование API — можно записывать и затем воспроизводить сценарии сетевого взаимодействия для тестирования.
Настройка сети для тестирования:
-
Запустите ReDroid с особыми сетевыми параметрами:
docker run --name redroid-test --network host redroid/redroid:11.0.0-latest
-
Настройте перехват трафика в Wireshark, используя фильтр для выделения трафика конкретного контейнера ReDroid:
ip.addr == [IP-адрес контейнера]
-
Для HTTPS-трафика настройте прокси в ReDroid через ADB:
adb connect localhost:5555 adb shell settings put global http_proxy "localhost:8080"
-
Запустите mitmproxy для расшифровки HTTPS:
mitmproxy --listen-port 8080
Это решение помогает разработчикам и тестировщикам глубже понимать, как их Android-приложения взаимодействуют с сетью, выявлять проблемы безопасности и оптимизировать сетевые взаимодействия без необходимости использования физических устройств или сложных настроек эмуляторов.
ссылка на оригинал статьи https://habr.com/ru/articles/915954/
Добавить комментарий