Primer test: abrir la app en el emulador con Appium

Proyecto Maven, conflicto Selenium/java-client con ContextAware resuelto, timeouts para 8GB RAM. Primer test verde abriendo la app en el emulador.

Emulador con Sauce Labs My Demo App Products y tres terminales PowerShell mostrando emulador Appium Server y BUILD SUCCESS
Las 3 piezas funcionando juntas: emulador con la app, Appium Server procesando, test verde.

El 'hola mundo' de mobile automation

Este post cubre el primer test funcional en Appium: abrir una app Android en el emulador desde código Java. Incluye la configuración Maven, un conflicto de versiones entre java-client y Selenium que vas a encontrar, y los ajustes de timeout necesarios para equipos con 8GB de RAM.

Abrir la app Sauce Labs My Demo App en el emulador desde código Java. Es el equivalente a abrir Google en el primer test de Selenium — el "hola mundo" de mobile automation.

Para eso necesito:

  1. Proyecto Maven con las dependencias de Appium
  2. El .apk de la app
  3. Un test que conecte con Appium Server, abra la app y verifique que cargó
  4. Emulador + Appium Server corriendo

El repo

En el Post 1 mencioné el repo appium-mobile-testing. Lo renombré a appium-java-framework para mantener consistencia con mis otros repos:

  • selenium-java-framework → herramienta + lenguaje + tipo
  • playwright-typescript-framework → herramienta + lenguaje + tipo
  • postman-api-testing → herramienta + disciplina + tipo

appium-mobile-testing rompía el patrón. Y "mobile" es redundante — Appium es mobile.

Repo: github.com/cesarbeassuarez/appium-java-framework


Proyecto Maven

Cloné el repo con SourceTree y creé el proyecto Maven en IntelliJ:

  • Name: appium-java-framework
  • Build system: Maven
  • JDK: temurin-17
  • GroupId: com.cesar.qa
  • ArtifactId: appium-java-framework

Sin código de ejemplo. Estructura Maven base limpia.

IntelliJ New Project con Maven JDK temurin-17 GroupId com.cesar.qa ArtifactId appium-java-framework
Proyecto Maven configurado. Misma estructura que el framework de Selenium.

Dependencias: el primer problema

Empecé con dos dependencias en el pom.xml:

<dependencies>
    <!-- Appium Java Client -->
    <dependency>
        <groupId>io.appium</groupId>
        <artifactId>java-client</artifactId>
        <version>9.4.0</version>
    </dependency>

    <!-- TestNG -->
    <dependency>
        <groupId>org.testng</groupId>
        <artifactId>testng</artifactId>
        <version>7.10.2</version>
        <scope>test</scope>
    </dependency>
</dependencies>

java-client trae Selenium como dependencia transitiva. En principio no hace falta agregarla explícitamente — a diferencia de un framework web donde Selenium se declara por separado.

Al escribir el test e intentar compilar:

java: cannot access org.openqa.selenium.ContextAware
  class file for org.openqa.selenium.ContextAware not found
IntelliJ build failed con 2 errores cannot access org.openqa.selenium.ContextAware class file not found
java-client trae Selenium 4.43.0 que eliminó ContextAware.

El diagnóstico

Corrí mvn dependency:tree para ver qué versión de Selenium estaba resolviendo Maven:

io.appium:java-client:jar:9.3.0:compile
   +- org.seleniumhq.selenium:selenium-api:jar:4.43.0:compile
   +- org.seleniumhq.selenium:selenium-remote-driver:jar:4.43.0:compile
   +- org.seleniumhq.selenium:selenium-support:jar:4.43.0:compile

El problema: java-client traía Selenium 4.43.0, pero esa versión de Selenium eliminó las clases ContextAware y LocationContext. El java-client todavía las referencia internamente. Es un conflicto de compatibilidad entre las dos librerías.

Es un problema conocido del ecosistema: java-client 9.x todavía referencia clases que Selenium 4.43.0 eliminó.

La solución

Forzar una versión de Selenium que sí tenga esas clases (4.25.0) y excluir la que trae java-client:

<dependencies>
    <!-- Selenium (versión compatible con java-client) -->
    <dependency>
        <groupId>org.seleniumhq.selenium</groupId>
        <artifactId>selenium-java</artifactId>
        <version>4.25.0</version>
    </dependency>

    <!-- Appium Java Client -->
    <dependency>
        <groupId>io.appium</groupId>
        <artifactId>java-client</artifactId>
        <version>9.3.0</version>
        <exclusions>
            <exclusion>
                <groupId>org.seleniumhq.selenium</groupId>
                <artifactId>*</artifactId>
            </exclusion>
        </exclusions>
    </dependency>

    <!-- TestNG -->
    <dependency>
        <groupId>org.testng</groupId>
        <artifactId>testng</artifactId>
        <version>7.10.2</version>
        <scope>test</scope>
    </dependency>
</dependencies>

El <exclusions> bloquea a java-client de traer su propia versión de Selenium. Usamos 4.25.0 que sí tiene ContextAware.

Después de esto: mvn clean test-compileBUILD SUCCESS.

En Selenium nunca tuve este problema porque agregaba Selenium directamente sin intermediarios. Acá hay una capa extra (java-client) que complica el manejo de versiones. Es la primera diferencia real entre armar un framework web y uno mobile.

Lo que intenté antes de llegar a esta solución

No fue directo. Probé varias cosas que no funcionaron:

  1. Agregar Selenium 4.27.0 explícitamente sin exclusiones → mismo error
  2. Dejar solo java-client sin Selenium → mismo error (la versión transitiva era la que fallaba)
  3. Limpiar cache de Maven con Remove-Item en .m2/repository → no alcanzó
  4. Invalidar caches de IntelliJ con File → Invalidate Caches → no era problema de IntelliJ
  5. Cambiar java-client a versión 9.3.0 sin exclusiones → mismo error (traía Selenium 4.43.0 también)

Lo que finalmente resolvió fue la combinación: Selenium 4.25.0 explícita + exclusión de Selenium en java-client.

Tiempo perdido: como una hora entre pruebas, rebuilds y búsquedas. IntelliJ se congeló varias veces por la RAM (tenía el emulador corriendo). Terminé compilando desde PowerShell con mvn clean test-compile para evitar IntelliJ y ahorrar RAM.


El .apk

Descargué mda-2.2.0-25.apk (17.1 MB) desde las releases de Sauce Labs en GitHub: https://github.com/saucelabs/my-demo-app-android/releases

GitHub releases de Sauce Labs My Demo App mostrando mda-2.2.0-25.apk de 17.1 MB versión 2.2.0
El .apk que se descarga. La otra (androidTest) es para Espresso, no la necesitamos.

Lo puse en apk/ dentro del proyecto:

appium-java-framework/
├── apk/
│   └── mda-2.2.0-25.apk
├── src/
├── pom.xml

El test

PrimerTest.java en IntelliJ con setUp BeforeMethod UiAutomator2Options timeouts extendidos y verificarAppAbre Test
El test final con los 3 timeouts extendidos a 120 segundos. Sin ellos, falla en 8GB de RAM.

Qué hace cada parte

UiAutomator2Options — las capabilities que le dicen a Appium qué dispositivo usar, qué app abrir y con qué driver automatizar. Es el equivalente a ChromeOptions en Selenium, pero para mobile.

setDeviceName("emulator-5554") — el emulador que creé en el Post Setup completo: Node.js, Android Studio, Appium Server y emulador. Lo podés verificar con adb devices.

setApp(...) — la ruta absoluta al .apk. Appium la instala en el emulador automáticamente.

setAutomationName("UiAutomator2") — el driver que instalamos en el Post Setup completo Appium.

Los 3 timeouts extra — esto no está en ningún tutorial básico. Los valores por defecto (20-30 segundos) no alcanzan en equipos con 8GB de RAM. Sin estos timeouts, el test falla porque Appium no logra instalar su propia app auxiliar a tiempo. Los puse en 120 segundos (2 minutos).

new AndroidDriver(new URL("http://127.0.0.1:4723"), options) — conecta con el Appium Server que está escuchando en el puerto 4723. Es la línea equivalente a new ChromeDriver() en Selenium.

@BeforeMethod / @AfterMethod — mismo patrón que en Selenium: setup antes de cada test, cleanup después. En Selenium abro Chrome, acá abro la app en el emulador.

Paralelo con Selenium

Concepto Selenium Appium
Options ChromeOptions UiAutomator2Options
Driver new ChromeDriver() new AndroidDriver(url, options)
Target URL del sitio web Ruta al .apk
Setup WebDriverManager descarga el driver Appium Server + UiAutomator2 Driver
Servidor No necesita (driver local) Appium Server en puerto 4723
Teardown driver.quit() driver.quit()

La diferencia más grande: en Selenium el driver corre localmente. En Appium hay un servidor intermedio. Por eso necesitás 3 procesos corriendo (emulador + Appium Server + test) en vez de solo 1 (el test).


La ejecución: 3 terminales y mucha paciencia

Arrancar todo

3 terminales de PowerShell, en orden:

Terminal 1 — emulador:

emulator -avd Pixel_8 -memory 1024 -no-snapshot-load
Emulador Pixel 8 con home screen y terminal mostrando adb devices emulator-5554 device conectado
Emulador arrancado y adb lo ve como device. Recién acá se puede correr el test.

Terminal 2 — Appium Server:

appium

Esperé a que diga "Appium REST http interface listener started on http://0.0.0.0:4723".

Terminal PowerShell con Appium Server 3.3.1 escuchando en puerto 4723 y UiAutomator2 7.2.0 cargado
Appium Server listo. Queda esperando conexiones del test.

Terminal 3 — test:

cd D:\Proyectos\Testing\appium-java-framework\appium-java-framework
mvn clean test
Terminal PowerShell mostrando mvn clean test con Tests run 1 Failures 0 BUILD SUCCESS Total time 4 min 50 s
BUILD SUCCESS al cuarto intento. 4 minutos 50 segundos para un solo test.

Errores comunes en la primera ejecución

ErrorCausaSolución
Could not find a connected Android device in 20000msEl emulador arrancó pero adb no lo registra (RAM al límite, estado offline)Verificar adb devices antes de correr el test. Si dice offline, reiniciar emulador
Appium Settings app is not running after 30000msTimeout default insuficiente para instalar la app auxiliarSubir appWaitDuration a 120000ms
uiautomator2ServerInstallTimeout timed out after 20000msMismo problema con el server de UiAutomator2Subir uiautomator2ServerInstallTimeout a 120000ms

Primer intento: "Could not find a connected Android device"

SessionNotCreatedException: Could not start a new session.
Message: Could not find a connected Android device in 20000ms

Corrí adb devices y el emulador no aparecía. Después apareció como offline.

Terminal PowerShell mostrando adb devices con emulator-5554 offline después de dos intentos
El emulador aparece pero está offline. En este estado no sirve correr el test.

El emulador estaba en la home screen pero adb no se conectaba. La RAM estaba al límite — 97%.

Solución: reiniciar todo este proceso y esperar.

Segundo intento: "Appium Settings app is not running after 30000ms"

SessionNotCreatedException: Could not start a new session.
Message: Appium Settings app is not running after 30000ms

Appium logró conectarse al emulador pero no pudo instalar su app auxiliar (Appium Settings) a tiempo. El timeout de 30 segundos no alcanzó.

Tercer intento: "uiautomator2ServerInstallTimeout
timed out after 20000ms"

Message: Error executing adbExec. Original error: 'Command ... install ... 
appium-uiautomator2-server-v9.11.2.apk timed out after 20000ms'.
Try to increase the 20000ms adb execution timeout represented by 
'uiautomator2ServerInstallTimeout' capability

Mismo problema pero con el server de UiAutomator2. Los 20 segundos por defecto no alcanzan.

Acá fue cuando agregué los 3 timeouts extendidos al test (120 segundos cada uno).

Emulador Android mostrando popup Appium Settings isn't responding con terminal de warnings device offline
Appium intentó instalar su app auxiliar pero el emulador no respondió a tiempo. RAM al límite.

Cuarto intento: funciona

Cerré absolutamente todo excepto las 3 terminales. Ni browser, ni IntelliJ.

Terminal PowerShell con BUILD SUCCESS Session ID y App abierta correctamente en el emulador
BUILD SUCCESS al cuarto intento. 4 minutos 50 segundos para un solo test.
Session ID: 2ecc26a7-1e38-4c6f-b4b0-92f09a30a862
App abierta correctamente en el emulador

Tests run: 1, Failures: 0, Errors: 0, Skipped: 0
BUILD SUCCESS
Total time: 04:50 min

4 minutos 50 segundos para un solo test. En Selenium el primer test tardó 13 segundos.

La app se abrió en el emulador: pantalla de Products con las mochilas de Sauce Labs.

Emulador con Sauce Labs My Demo App Products y tres terminales PowerShell mostrando emulador Appium Server y BUILD SUCCESS
Las 3 piezas funcionando juntas: emulador con la app, Appium Server procesando, test verde.

Consideraciones para equipos con 8GB de RAM

El problema causado por la RAM. Probé de esperar para que se estabilice el emulador y aun así se quedó en offline por 45 minutos. IntelliJ y toda la pc se ralentizaba porque el emulador consumía todo.

Terminé compilando y corriendo los tests desde PowerShell con mvn clean test para no necesitar IntelliJ abierto. Eso liberó suficiente RAM para que el test pase.

Tips que funcionaron:

  • Cerrar Chrome antes de correr el test
  • No abrir IntelliJ mientras el emulador corre
  • Usar emulator -avd Pixel_8 -memory 1024 -no-snapshot-load para limitar la RAM del emulador
  • Subir los timeouts a 120 segundos (los defaults asumen que la máquina es rápida)
  • Verificar adb devices antes de correr el test — si dice offline, no vale la pena intentar

En equipos con 16GB+ esto no pasa. Pero en LATAM, 8GB es la realidad de mucha gente. Queda documentado.

Para los próximos posts voy a evaluar usar mi dispositivo físico (Motorola G51) por USB. Libera toda la RAM del emulador y los tests corren más rápido.


Estado actual

Tengo:

Elemento Detalle
Proyecto Maven com.cesar.qa:appium-java-framework
java-client 9.3.0 (con exclusión de Selenium)
Selenium 4.25.0 (explícita, compatible)
TestNG 7.10.2
App target Sauce Labs My Demo App 2.2.0
Primer test Abre la app, verifica sesión, cierra
Resultado BUILD SUCCESS (04:50 min)

Estructura del proyecto:

appium-java-framework/
├── apk/
│   └── mda-2.2.0-25.apk
├── src/
│   ├── main/java/
│   └── test/java/
│       └── PrimerTest.java
├── .gitignore
├── pom.xml
└── README.md

Repo: github.com/cesarbeassuarez/appium-java-framework


Próximo paso

Appium Inspector: encontrar elementos en la app. Es la herramienta que reemplaza al DevTools del browser. Sin ella no puedo escribir tests reales — necesito saber qué locators usar para tocar botones, leer textos, navegar entre pantallas.