Este artículo descrieb cómo configurar y ejecutar pruebas de Appium simultáneamente en varios dispositivos Android utilizando TestNG y Maven.
Se presentan dos clases de prueba de ejemplo, XiaoMiTest y WanDouJiaTest, cada una diseñada para interactuar con una aplicación específica en un dispositivo Android. Ambas clases utilizan AndroidDriver y configuran las capacidades deseadas para la ejecución de pruebas.
Clase de Prueba 1: XiaoMiTest
package com.example.tests;
import io.appium.java_client.android.AndroidDriver;
import org.openqa.selenium.remote.DesiredCapabilities;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Parameters;
import org.testng.annotations.Test;
import java.io.File;
import java.net.URL;
import java.text.SimpleDateFormat;
import java.util.Date;
public class XiaoMiTest {
private AndroidDriver driver;
private String appiumPort;
private String deviceUdid;
// Simulación de utilidad para capturas de pantalla
private void takeScreenshot(String deviceName, String stepName, int stepNumber) {
System.out.println("Captura de pantalla para: " + deviceName + " - Paso: " + stepName + " (" + stepNumber + ")");
// Aquí iría la lógica real para tomar la captura de pantalla
}
@BeforeMethod
@Parameters({"port", "udid"})
public void setupTest(String port, String udid) throws Exception {
this.appiumPort = port;
this.deviceUdid = udid;
System.out.println("Configurando prueba para dispositivo: " + udid + " en puerto: " + port);
File app = new File("apps", "mi_app.apk"); // Ruta de ejemplo para la app
DesiredCapabilities capabilities = new DesiredCapabilities();
capabilities.setCapability("deviceName", udid); // Usar UDID como deviceName
capabilities.setCapability("udid", udid);
capabilities.setCapability("platformName", "Android");
capabilities.setCapability("platformVersion", "5.1"); // Versión de ejemplo
capabilities.setCapability("app", app.getAbsolutePath());
capabilities.setCapability("appPackage", "com.example.miui.home"); // Package de ejemplo
capabilities.setCapability("appActivity", ".ui.HomeActivity"); // Activity de ejemplo
driver = new AndroidDriver(new URL("http://127.0.0.1:" + port + "/wd/hub"), capabilities);
}
@Test(groups = {"smoke"})
public void verifyHomePageNavigation() throws InterruptedException {
takeScreenshot("XiaoMi", "Verificar Navegación Página Principal", 1);
System.out.println("Ejecutando prueba en XiaoMi...");
// Lógica de prueba específica para la app de Xiaomi
Thread.sleep(2000); // Simulación de acciones
System.out.println("Prueba XiaoMi completada.");
}
@AfterMethod
public void tearDown() {
if (driver != null) {
driver.quit();
System.out.println("Driver cerrado para dispositivo: " + deviceUdid);
}
}
}
Clase de Prueba 2: WanDouJiaTest
package com.example.tests;
import io.appium.java_client.android.AndroidDriver;
import org.openqa.selenium.remote.DesiredCapabilities;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Parameters;
import org.testng.annotations.Test;
import java.io.File;
import java.net.URL;
import java.text.SimpleDateFormat;
import java.util.Date;
public class WanDouJiaTest {
private AndroidDriver driver;
private String appiumPort;
private String deviceUdid;
// Simulación de utilidad para capturas de pantalla
private void takeScreenshot(String deviceName, String stepName, int stepNumber) {
System.out.println("Captura de pantalla para: " + deviceName + " - Paso: " + stepName + " (" + stepNumber + ")");
// Aquí iría la lógica real para tomar la captura de pantalla
}
@BeforeMethod
@Parameters({"port", "udid"})
public void setupTest(String port, String udid) throws Exception {
this.appiumPort = port;
this.deviceUdid = udid;
System.out.println("Configurando prueba para dispositivo: " + udid + " en puerto: " + port);
File app = new File("apps", "wandoujia.apk"); // Ruta de ejemplo para la app
DesiredCapabilities capabilities = new DesiredCapabilities();
capabilities.setCapability("deviceName", udid); // Usar UDID como deviceName
capabilities.setCapability("udid", udid);
capabilities.setCapability("platformName", "Android");
capabilities.setCapability("platformVersion", "6.0"); // Versión de ejemplo
capabilities.setCapability("app", app.getAbsolutePath());
capabilities.setCapability("appPackage", "com.wandoujia.market"); // Package de ejemplo
capabilities.setCapability("appActivity", ".ui.NewMainActivity"); // Activity de ejemplo
driver = new AndroidDriver(new URL("http://127.0.0.1:" + port + "/wd/hub"), capabilities);
}
@Test(groups = {"regression"})
public void testAppDownloadFunctionality() throws InterruptedException {
takeScreenshot("WanDouJia", "Probar Funcionalidad Descarga App", 1);
System.out.println("Ejecutando prueba en WanDouJia...");
// Lógica de prueba específica para la app de WanDouJia
Thread.sleep(3000); // Simulación de acciones
System.out.println("Prueba WanDouJia completada.");
}
@AfterMethod
public void tearDown() {
if (driver != null) {
driver.quit();
System.out.println("Driver cerrado para dispositivo: " + deviceUdid);
}
}
}
La configuración clave para la ejecución paralela reside en el archivo testng.xml. Aquí se definen los <test> individuales, cada uno asociado a una clase de prueba específica y configurado con parámetros únicos para el puerto de Appium y el UDID del dispositivo.
Archivo testng.xml
<?xml version="1.0" encoding="UTF-8"?>
<suite name='AppiumParallelSuite' parallel="tests" thread-count="3" verbose="1">
<test name="XiaoMiDeviceTest">
<parameter name = "port" value = "4723"/>
<parameter name = "udid" value = "emulator-5554"/> <!-- O UDID real del dispositivo -->
<classes>
<class name="com.example.tests.XiaoMiTest"/>
</classes>
</test>
<test name="WanDouJiaDeviceTest">
<parameter name = "port" value = "4725"/>
<parameter name = "udid" value = "emulator-5556"/> <!-- O UDID real del dispositivo -->
<classes>
<class name="com.example.tests.WanDouJiaTest"/>
</classes>
</test>
<!-- Se pueden añadir más pruebas para otros dispositivos aquí -->
</suite>
En el archivo testng.xml, el atributo parallel="tests" indica a TestNG que ejecute los elementos <test> en paralelo. El atributo thread-count especifica el número máximo de hilos que se utilizarán para la ejecución paralela. Es crucial asignar puertos de Appium únicos (ej. 4723, 4725) y los UDIDs correspondientes a cada dispositivo que se utilizará.
Para integrar la ejecución de TestNG con Maven, se configura el plugin maven-surefire-plugin en el archivo pom.xml. Este plugin se encarga de ejecutar los archivos de suite de TestNG especificados.
Configuración de pom.xml
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>3.0.0-M5</version<!-- Versión recomendada -->
<configuration>
<suiteXmlFiles>
<suiteXmlFile>testng.xml</suiteXmlFile>
</suiteXmlFiles>
<!-- Opcional: Configurar propiedades del sistema si es necesario -->
<systemProperties>
<property>
<name>platform.version</name>
<value>${platform.version}</value>
</property>
</systemProperties>
</configuration>
</plugin>
<!-- Otros plugins... -->
</plugins>
</build>
Al ejecutar el comando mvn clean install o mvn test, Maven utilizará el maven-surefire-plugin para lanzar las pruebas definidas en testng.xml, distribuyéndolas entre los dispositivos y puertos configurados para una ejecución paralela eficiente.