Redroid

от автора

Что такое 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 
Redroid

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 — можно записывать и затем воспроизводить сценарии сетевого взаимодействия для тестирования.

Настройка сети для тестирования:

  1. Запустите ReDroid с особыми сетевыми параметрами:

docker run --name redroid-test --network host redroid/redroid:11.0.0-latest 
  1. Настройте перехват трафика в Wireshark, используя фильтр для выделения трафика конкретного контейнера ReDroid:

ip.addr == [IP-адрес контейнера] 
  1. Для HTTPS-трафика настройте прокси в ReDroid через ADB:

adb connect localhost:5555 adb shell settings put global http_proxy "localhost:8080" 
  1. Запустите mitmproxy для расшифровки HTTPS:

mitmproxy --listen-port 8080 

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


https://t.me/akrylof

https://github.com/avkcode/resume/blob/main/resume.pdf


ссылка на оригинал статьи https://habr.com/ru/articles/915954/


Комментарии

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

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