Que Es Appium?
Appium es un framework de automatizacion movil de codigo abierto que te permite escribir tests para aplicaciones Android e iOS usando el protocolo estandar WebDriver. La filosofia clave detras de Appium es que no deberias necesitar recompilar tu app o modificarla de ninguna manera para automatizarla, y deberias poder escribir tests en cualquier lenguaje de programacion.
Appium actua como un servidor que recibe comandos WebDriver de tu codigo de test y los traduce en acciones de automatizacion especificas de la plataforma. Para Android, usa UIAutomator2 o Espresso como motor de automatizacion subyacente. Para iOS, usa XCUITest. Esta capa de abstraccion es lo que hace a Appium multiplataforma — tu codigo de test llama la misma API WebDriver sin importar la plataforma objetivo.
Arquitectura de Appium
Script de Test (Java/Python/JS/C#)
|
Cliente WebDriver
|
HTTP (Protocolo W3C WebDriver)
|
Servidor Appium (Node.js)
|
+---------+---------+
| |
Android iOS
(UIAutomator2) (XCUITest)
| |
Dispositivo/ Dispositivo/
Emulador Simulador
Componentes Clave
Servidor Appium: Una aplicacion Node.js que recibe comandos WebDriver via HTTP, los traduce en comandos especificos de plataforma y devuelve resultados. Gestiona sesiones, conexiones de dispositivos y drivers de automatizacion.
Drivers de Appium: Modulos especificos de plataforma que saben como automatizar cada una. El driver UiAutomator2 controla Android; el driver XCUITest controla iOS. Cada driver comprende el framework de accesibilidad y la jerarquia de UI de la plataforma.
Bibliotecas Cliente: Bibliotecas cliente WebDriver estandar (bindings de Selenium) con extensiones especificas de Appium. Disponibles para Java, Python, JavaScript, C#, Ruby y mas.
Appium Inspector: Una herramienta GUI para inspeccionar el arbol de elementos de la app movil, probar locators y grabar acciones. Esencial para construir selectores de elementos.
Configurando Appium
Prerrequisitos
Para Android:
- Java JDK 11+
- Android SDK con platform tools
- Un emulador Android o dispositivo fisico con depuracion USB habilitada
- Variable de entorno ANDROID_HOME configurada
Para iOS (solo macOS):
- Xcode con herramientas de linea de comandos
- Un simulador iOS o dispositivo fisico con perfil de aprovisionamiento valido
Instalacion
# Instalar Appium 2.x globalmente
npm install -g appium
# Instalar drivers
appium driver install uiautomator2 # Para Android
appium driver install xcuitest # Para iOS
# Iniciar el servidor
appium
# Instalar Appium Inspector (descarga separada)
# https://github.com/appium/appium-inspector/releases
Verificar Configuracion
# Verificar entorno
npx appium-doctor --android # Verificar setup de Android
npx appium-doctor --ios # Verificar setup de iOS
W3C Capabilities
Las capabilities le dicen a Appium que dispositivo, plataforma y app usar:
// Ejemplo Java — Android
UiAutomator2Options options = new UiAutomator2Options()
.setPlatformName("Android")
.setDeviceName("Pixel_7_API_34")
.setApp("/path/to/app.apk")
.setAutomationName("UiAutomator2")
.setAppPackage("com.example.myapp")
.setAppActivity("com.example.myapp.MainActivity")
.setNoReset(true);
AndroidDriver driver = new AndroidDriver(
new URL("http://localhost:4723"), options
);
// Ejemplo Java — iOS
XCUITestOptions options = new XCUITestOptions()
.setPlatformName("iOS")
.setDeviceName("iPhone 15")
.setPlatformVersion("17.0")
.setApp("/path/to/app.ipa")
.setAutomationName("XCUITest")
.setBundleId("com.example.myapp");
IOSDriver driver = new IOSDriver(
new URL("http://localhost:4723"), options
);
Encontrando Elementos
Appium Inspector
Appium Inspector se conecta a una sesion en ejecucion y muestra el arbol de elementos de la app. Puedes:
- Navegar la jerarquia de UI
- Hacer click en elementos para ver sus atributos
- Probar estrategias de localizacion en tiempo real
- Copiar codigo de localizacion en tu lenguaje preferido
Estrategias de Localizacion
// Por Accessibility ID (recomendado — multiplataforma)
driver.findElement(AppiumBy.accessibilityId("loginButton"));
// Por ID (Android resource ID)
driver.findElement(AppiumBy.id("com.example:id/login_button"));
// Por XPath (lento pero flexible)
driver.findElement(AppiumBy.xpath("//android.widget.Button[@text='Login']"));
// Por Class Name
driver.findElement(AppiumBy.className("android.widget.EditText"));
// Por selector Android UIAutomator (solo Android, poderoso)
driver.findElement(AppiumBy.androidUIAutomator(
"new UiSelector().text(\"Login\")"
));
// Por iOS predicate string (solo iOS)
driver.findElement(AppiumBy.iOSNsPredicateString(
"label == 'Login' AND type == 'XCUIElementTypeButton'"
));
Mejor practica: Usa Accessibility ID siempre que sea posible. Funciona en ambas plataformas y es la estrategia de localizacion mas confiable.
Acciones Moviles Comunes
Tap, Escritura y Swipe
// Tap en un elemento
WebElement loginBtn = driver.findElement(AppiumBy.accessibilityId("loginButton"));
loginBtn.click();
// Escribir texto
WebElement emailField = driver.findElement(AppiumBy.accessibilityId("emailInput"));
emailField.sendKeys("user@example.com");
// Limpiar y reescribir
emailField.clear();
emailField.sendKeys("new@example.com");
// Ocultar teclado (Android)
driver.hideKeyboard();
Gestos con W3C Actions
// Swipe arriba (scroll abajo)
Dimension size = driver.manage().window().getSize();
int startX = size.width / 2;
int startY = (int) (size.height * 0.8);
int endY = (int) (size.height * 0.2);
PointerInput finger = new PointerInput(PointerInput.Kind.TOUCH, "finger");
Sequence swipe = new Sequence(finger, 1);
swipe.addAction(finger.createPointerMove(Duration.ZERO, PointerInput.Origin.viewport(), startX, startY));
swipe.addAction(finger.createPointerDown(PointerInput.MouseButton.LEFT.asArg()));
swipe.addAction(finger.createPointerMove(Duration.ofMillis(500), PointerInput.Origin.viewport(), startX, endY));
swipe.addAction(finger.createPointerUp(PointerInput.MouseButton.LEFT.asArg()));
driver.perform(List.of(swipe));
Patron Page Object para Movil
// BasePage.java
public abstract class BasePage {
protected AndroidDriver driver;
protected WebDriverWait wait;
public BasePage(AndroidDriver driver) {
this.driver = driver;
this.wait = new WebDriverWait(driver, Duration.ofSeconds(10));
}
protected WebElement waitForElement(By locator) {
return wait.until(ExpectedConditions.visibilityOfElementLocated(locator));
}
}
// LoginPage.java
public class LoginPage extends BasePage {
private final By emailInput = AppiumBy.accessibilityId("emailInput");
private final By passwordInput = AppiumBy.accessibilityId("passwordInput");
private final By loginButton = AppiumBy.accessibilityId("loginButton");
private final By errorMessage = AppiumBy.accessibilityId("errorMessage");
public LoginPage(AndroidDriver driver) {
super(driver);
}
public DashboardPage loginAs(String email, String password) {
waitForElement(emailInput).sendKeys(email);
waitForElement(passwordInput).sendKeys(password);
waitForElement(loginButton).click();
return new DashboardPage(driver);
}
public String getErrorMessage() {
return waitForElement(errorMessage).getText();
}
}
// Clase de test
@Test
public void testSuccessfulLogin() {
LoginPage loginPage = new LoginPage(driver);
DashboardPage dashboard = loginPage.loginAs("admin@test.com", "password123");
assertEquals("Welcome, Admin", dashboard.getWelcomeText());
}
Tests en Dispositivos Reales vs Emuladores
| Aspecto | Emulador/Simulador | Dispositivo Real |
|---|---|---|
| Velocidad | Rapido para iniciar, ejecucion mas lenta | Mas lento para configurar, velocidad realista |
| Costo | Gratis | Compra de dispositivo o servicio cloud |
| Confiabilidad | Consistente, reproducible | Problemas ocasionales de conectividad |
| Precision | Puede omitir bugs especificos de hardware | Prueba condiciones reales del usuario |
| CI/CD | Facil de provisionar | Requiere device farm o cloud |
Recomendacion: Usa emuladores para ejecuciones diarias de CI/CD y dispositivos reales para validacion pre-lanzamiento y funcionalidades especificas de hardware (camara, GPS, biometria).
Ejercicios
Ejercicio 1: Configuracion de Appium y Primer Test
- Instala Appium 2.x y el driver UiAutomator2
- Descarga una app de ejemplo (como la app de test de Appium)
- Abre Appium Inspector y explora el arbol de elementos de la app
- Escribe un test que abra la app, navegue a una pantalla especifica y verifique visibilidad de elementos
Ejercicio 2: Flujo de Login con Page Objects
- Crea page objects para un flujo de login: LoginPage, DashboardPage
- Escribe tests para: login exitoso, password invalido, campos vacios
- Usa locators de Accessibility ID para todos los elementos
- Agrega esperas explicitas para estados de carga
Ejercicio 3: Automatizacion de Gestos
- Escribe un test que haga scroll a traves de una lista para encontrar un item especifico
- Implementa una accion de long-press que active un menu contextual
- Crea un test de pinch-to-zoom para una vista de imagen
- Testea un gesto de swipe-to-delete en un item de lista