Sugerencias de prueba supercargadas para 2019: un tutorial de prueba de automatización de Java
Publicado: 2022-03-11Cada año, los ingenieros de automatización de pruebas de todo el mundo investigarán las últimas herramientas y técnicas para hacer que su marco de automatización de pruebas sea más estable, más rápido y más fácil de usar y mantener. Esto es vital para garantizar la adopción generalizada continua de su marco dentro de su empresa. En general, los marcos inflados y desactualizados pasan de moda rápidamente.
En este artículo, veremos algunas de las formas en que puede actualizar su marco para 2019 y cómo estar preparado para 2020. Para mejorar mi marco, siempre me concentro en los "puntos débiles". Estas son las áreas que son complejas de configurar o causan la mayoría de las fallas. Identifiqué tres áreas principales que quería simplificar o mejorar:
- Rejilla de selenio
- Murga
- Herramientas para desarrolladores de Chrome
Selenium Grid es notoriamente difícil de configurar y puede fallar sin previo aviso. Quería ver qué, si algo, había mejorado aquí. También quería investigar si se habían agregado nuevas waits
a la API de Selenium para mejorar la estabilidad de las pruebas que creé. Finalmente, quería ver si podía comenzar a interactuar con Chrome DevTools a través de Selenium, que se ha convertido en una parte esencial del conjunto de herramientas de cualquier probador.
Consejo n.º 1: Dockerize su red de Selenium
Selenium Grid es notoriamente difícil de configurar, inestable y difícil de implementar o controlar versiones en una canalización de CI. Una forma mucho más fácil, estable y fácil de mantener es usar las imágenes preconstruidas de Selenium Docker.
Nota: La única desventaja de este método es que IE (Internet Explorer) no es compatible, ya que aún no es posible contenerizar el sistema operativo Windows.
Preparándose
Para comenzar a funcionar, primero debe tener Docker y Docker Compose instalados en su máquina. Si está ejecutando Windows 10 o una Mac, ambos se instalarán a través de Docker Desktop.
Comenzando su cuadrícula
El repositorio oficial de Selenium en Docker Hub contiene imágenes de Docker preconstruidas para su Selenium Hub y Firefox y Chrome Nodes.
La forma más sencilla de usarlos en un Selenium Grid local es construir un archivo Docker Compose dentro del directorio raíz de su proyecto. Nombre el archivo docker-compose.yml
para simplificar las cosas.
He incluido un ejemplo a continuación que crea la siguiente cuadrícula:
- Un solo Selenium Hub
- Un nodo de Chrome
- Un nodo de Firefox
#docker-compose.yml version: "3" services: selenium-hub: image: selenium/hub:3.141.59-neon container_name: selenium-hub ports: - "4444:4444" chrome: image: selenium/node-chrome:3.141.59-neon volumes: - /dev/shm:/dev/shm depends_on: - selenium-hub environment: - HUB_HOST=selenium-hub - HUB_PORT=4444 firefox: image: selenium/node-firefox:3.141.59-neon volumes: - /dev/shm:/dev/shm depends_on: - selenium-hub environment: - HUB_HOST=selenium-hub - HUB_PORT=4444
El archivo Docker Compose describe la configuración de su Grid. Para obtener más información sobre cómo crear archivos de Docker Compose, consulte la documentación oficial.
Para iniciar su Grid, simplemente use cualquier ventana de terminal (una ventana de powershell
o cmd
en Windows) para ejecutar el siguiente comando desde el directorio raíz de su proyecto:
docker-compose up
Conexión a la Red
Puede conectarse a su Selenium Grid exactamente de la misma manera que lo hace normalmente, ya que el Hub está escuchando en el puerto 4444 de su máquina local. Aquí hay un ejemplo en el que configuramos nuestro controlador para usar nuestro nodo de Chrome.
// Driver.java protected static RemoteWebDriver browser; DesiredCapabilities cap = new DesiredCapabilities(); ChromeOptions chromeOptions = new ChromeOptions(); cap.setCapability(ChromeOptions.CAPABILITY, chromeOptions); cap.setBrowserName("chrome"); driver = new RemoteWebDriver(cap);
Luego puede usar la biblioteca TestNG para ejecutar sus pruebas en múltiples nodos en paralelo como de costumbre.
Vale la pena señalar que es posible tener varios navegadores ejecutándose en cada nodo. Sin embargo, esto no se recomienda y el uso de un navegador por nodo se considera la mejor práctica para un rendimiento óptimo.
Consejos y trucos adicionales
Si desea ver lo que sucede en el navegador para poder depurar sus pruebas, vale la pena tener una versión de debug
de su archivo docker-compose.yml
que descarga los nodos del navegador de debug
. Estos contienen un servidor VNC para que pueda ver el navegador mientras se ejecuta la prueba.
También es posible ejecutar los navegadores sin cabeza para aumentar la velocidad (de la manera habitual) y Selenium también proporciona versiones base
de las imágenes para que pueda crear sus propias imágenes si necesita instalar software adicional.
Para crear una versión estable de Grid para su canalización de CI, también es posible implementar su Grid en Kubernetes o Swarm. Esto garantiza que los Dockers se restablezcan o reemplacen rápidamente si fallan.
Consejo #2: Esperas inteligentes
Como sabe cualquier ingeniero de automatización de pruebas, las waits
son cruciales para la estabilidad de su marco de automatización de pruebas. También pueden acelerar su prueba al hacer que cualquier sleeps
o pauses
sea redundante y superar los problemas de red lenta y de navegadores cruzados. A continuación se presentan algunos consejos para que sus waits
sean aún más resistentes.
Tutorial de prueba de automatización de Java n.° 2: Operadores lógicos en esperas: Sea específico con sus esperas
La clase ExpectedConditions
ha crecido con el tiempo y ahora abarca casi todas las situaciones imaginables. Si bien ExpectedConditions.presenceOfElementLocated(locator)
suele ser suficiente, se recomienda usar los métodos dentro de la clase ExpectedCondition
para cubrir todas las acciones del usuario incrustándolos en su clase Actions.java
. Esto protegerá sus pruebas contra la mayoría de los problemas de navegadores cruzados o sitios web lentos.
Por ejemplo , si al hacer clic en un enlace se abre una nueva pestaña, utilice ExpectedConditions.numberOfWindowsToBe(2)
. Esto asegurará que la pestaña esté allí antes de intentar cambiar a ella.
También puede usar una wait
para asegurarse de capturar todos los elementos presentes en la página cuando usa findElements
. Esto puede ser especialmente útil si una página de search
tarda en devolver sus resultados. Por ejemplo, esta línea:
List<WebElement> results = driver.findElements(locators.RESULTS);
Puede dar como resultado una matriz de List
vacía si los resultados de su búsqueda aún no se han cargado. En su lugar, es mejor usar la condición esperada numberOfElementsToBeMoreThan
para esperar a que los resultados sean más que cero. Por ejemplo:
WebElement searchButton = driver.findElement(locators.SEARCH_BUTTON); searchButton.click(); new WebDriverWait(driver, 30) .until(ExpectedConditions .numberOfElementsToBeMoreThan(locators.RESULTS, 0)); List<WebElement> results = driver.findElements(locators.RESULTS); results.get(0).click();
Ahora, su comando findElements
solo se ejecutará después de que se hayan devuelto los resultados de la búsqueda.
Esta wait
también es útil para encontrar un solo elemento cuando se trata de una interfaz que no funciona bien con Selenium (por ejemplo, sitios web angulares). Crear un método como este protegerá sus pruebas, haciéndolas mucho más estables.
protected static WebElement waitForElement(By locator){ try { new WebDriverWait(browser, 30) .until(ExpectedConditions .numberOfElementsToBeMoreThan(locator, 0)); } catch (TimeoutException e){ e.printStackTrace(); Assert.fail("Timeout: The element couldn't be found in " + WAIT + " seconds!"); } catch (Exception e){ e.printStackTrace(); Assert.fail("Something went wrong!"); } return browser.findElement(locator); }
Incluso es posible esperar a que los elementos dejen de ser visibles. Esto es especialmente útil si está esperando que desaparezca una ventana emergente después de haber hecho clic en el botón OK
o Save
antes de continuar con su prueba.
WebElement okButton = driver.findElement(locators.OK_BUTTON); okButton.click(); new WebDriverWait(driver, 30) .until( ExpectedConditions .invisibilityOfElementLocated(locators.POPUP_TITLE) );
Todos los métodos descritos anteriormente y más se enumeran en la documentación oficial. Vale la pena pasar diez minutos leyendo todas las posibilidades y mejorando la estabilidad de su marco.
Tutorial de pruebas de automatización de Java n.º 2: operadores lógicos en esperas
Una buena manera de generar resiliencia en sus waits
es mediante el uso de operadores lógicos. Por ejemplo, si quisiera verificar que se ha ubicado un elemento Y que se puede hacer clic en él, usaría el siguiente código (tenga en cuenta que estos ejemplos devuelven un valor booleano):
wait.until(ExpectedConditions.and( ExpectedConditions.presenceOfElementLocated(locator), ExpectedConditions.elementToBeClickable(locator) ) );
El operador OR sería apropiado si no estuviera seguro de si el título de la página podría cambiar o no. Luego puede incluir una verificación de la URL si falla la primera condición, para confirmar que definitivamente está en la página correcta.
wait.until(ExpectedConditions.or( ExpectedConditions.titleIs(expectedTitle), ExpectedConditions.urlToBe(expectedUrl) ) );
O si desea asegurarse de que una casilla de verificación ya no esté habilitada después de realizar una acción en la página, entonces el operador NOT es apropiado.

wait.until(ExpectedConditions.not( ExpectedConditions.elementToBeClickable(locator) ) );
El uso de operadores puede hacer que sus waits
sean más resistentes y que las pruebas sean menos frágiles.
Consejo #3: Chrome DevTools: simulación de condiciones de red
Ejecutar su aplicación web en localhost o en una red local puede dar una impresión falsa en cuanto a su rendimiento cuando se ejecuta en la naturaleza. La capacidad de acelerar varias velocidades de carga y descarga le dará una mejor representación de cómo se ejecutará su aplicación en Internet, donde los tiempos de espera pueden hacer que las acciones fallen. Podemos comenzar a simular esto usando el poder de DevTools de Chrome.
El siguiente código abrirá la página de inicio de Toptal usando diferentes velocidades de carga y descarga. Primero, almacenaremos nuestras velocidades en un proveedor de datos TestNG usando el siguiente código:
import org.testng.annotations.DataProvider; public class ExcelDataProvider { @DataProvider(name = "networkConditions") public static Object[][] networkConditions() throws Exception { return new Object[][] { // Upload Speed, Dowload Speed in kb/s and latency in ms. { 5000 , 5000, 5 }, { 10000, 7000, 5 }, { 15000, 9000, 5 }, { 20000, 10000, 5 }, { 0, 0 }, }; } }
Nota: La limitación de carga y descarga está en kb/s
y la latencia está en ms
.
Luego, podemos usar estos datos para ejecutar nuestra prueba en diferentes condiciones de red. Dentro de la prueba, CommandExecutor
ejecutará el comando en la sesión actual del navegador. Esto, a su vez, activará la configuración necesaria en la funcionalidad de herramientas para desarrolladores de Chrome para simular nuestra red lenta. El código dentro de la declaración if
se puede incluir en un método @BeforeClass
cuando se ejecuta un conjunto de pruebas.
import org.testng.annotations.Test; import com.google.common.collect.ImmutableMap; import java.io.IOException; import java.util.HashMap; import java.util.Map; import org.openqa.selenium.remote.Command; import org.openqa.selenium.remote.CommandExecutor; import org.openqa.selenium.remote.Response; public class TestClass { // load our data provider @Test(dataProvider = "networkConditions") public void test(int download, int upload, int latency) throws IOException { // only run if the network is throttled if (download > 0 && upload > 0) { CommandExecutor executor = driver.getCommandExecutor(); // create a hashmap of the required network conditions Map map = new HashMap(); // you can even test 'offline' behaviour map.put("offline", false); map.put("latency", latency); map.put("download_throughput", downloadThroughput); map.put("upload_throughput", uploadThroughput); // execute our code Response response = executor.execute( new Command(driver.getSessionId(), "setNetworkConditions", ImmutableMap.of("network_conditions", ImmutableMap.copyOf(map)))); } // Open the website driver.get("https://www.toptal.com/"); // You can then check that elements are loaded etc. // Don't forget to use waits! } }
Consejo adicional: Cómo administrar sus cookies
Las cookies del navegador pueden causar diferentes comportamientos en su aplicación, dependiendo de si se han guardado o no de una sesión anterior (por ejemplo, la aplicación puede cargarse con un usuario que ya inició sesión). Es una buena práctica borrar las cookies antes de cada ejecución de prueba para asegurarse de que no causen problemas.
El siguiente código le permite eliminar todas sus cookies:
driver.manage().deleteAllCookies();
También puede eliminar una cookie por su nombre:
driver.manage().deleteCookieNamed("CookieName");
O obtener el contenido de una cookie:
String myCookie = driver.manage().getCookieNamed("CookieName").getValue();
O consigue todas las cookies:
List<Cookie> cookies = driver.manage().getCookies();
Automatización de pruebas en 2020: mirando hacia el futuro
Selenium 4 se lanzará en los próximos meses. Todavía está en desarrollo, pero como ya se ha lanzado una versión alfa, vale la pena echar un vistazo a las mejoras que ofrecerá.
Nota: puede realizar un seguimiento de su progreso consultando la hoja de ruta.
Estandarización de WebDriver W3C
Selenium ya no necesitará comunicarse con el navegador a través del protocolo de conexión JSON; en cambio, las pruebas automatizadas se comunicarán directamente con el navegador. Esto debería abordar la famosa naturaleza escamosa de las pruebas de Selenium, incluida la protección contra las actualizaciones del navegador. Esperemos que la velocidad de prueba también aumente.
Una cuadrícula de selenio más simple
Selenium Grid será más estable y más fácil de configurar y administrar en Selenium 4. Los usuarios ya no necesitarán configurar e iniciar concentradores y nodos por separado, ya que la cuadrícula actuará como un nodo y un concentrador combinados. Además, habrá un mejor soporte para Docker, las pruebas paralelas se incluirán de forma nativa y proporcionará una interfaz de usuario más informativa. El seguimiento de solicitudes con Hooks también lo ayudará a depurar su cuadrícula.
Documentación
La documentación de Selenium recibirá una revisión muy necesaria, ya que no se ha actualizado desde el lanzamiento de Selenium 2.0.
Cambios en la API
Se eliminará la compatibilidad con los navegadores Opera y PhantomJS. La ejecución sin cabeza se puede realizar con Chrome o Firefox, y Opera se basa en Chromium y, por lo tanto, las pruebas de Chromium se consideran suficientes para este navegador.
WebElement.getSize()
y WebElement.getLocation()
ahora se reemplazan con un solo método WebElement.getRect()
. Sin embargo, como a menudo se usan para crear capturas de pantalla de un solo elemento, vale la pena saber que también habrá un comando API para capturar una captura de pantalla de un elemento en Selenium 4.
Para WebDriver Window
, los métodos getPosition
y getSize
serán reemplazados por el método getRect
y los métodos setPosition
y setSize
serán reemplazados por el método setRect
. Los métodos de fullscreen
y minimize
estarán disponibles, por lo que estas acciones se pueden realizar dentro de su prueba.
Otros cambios notables:
- La clase
Options
para cada navegador ahora extenderá la claseCapabilities
. - Se ha agregado un método
driver.switchTo().parentFrame()
para facilitar la navegación por marcos. - Se incluirán
nice
localizadores que operen a un nivel superior a los actuales. Serán una subclase deBy
. - Habrá una implementación de la API de
DevTools
, que permitirá a los usuarios aprovechar las funciones que se ofrecen mediante el uso del Protocolo de depuración de Chrome (y sus equivalentes en otros navegadores). Éstos incluyen:- Capturas de pantalla de página completa (incluidos los elementos fuera de pantalla).
- Registros de transmisión.
- Esperando eventos de mutación en la página.
- También se eliminarán muchos métodos y clases en desuso.
Nota: Puede obtener una versión Alpha de Selenium 4 del repositorio de Maven. Se recomienda encarecidamente probar esto con su marco actual (idealmente en una rama de sandbox), para que esté listo para el cambio.
Conclusión
En este artículo, cubrí algunas áreas en las que mejoré mi marco de automatización de pruebas. Ahora es más estable y usable que antes, lo que tendrá un impacto positivo en todos los involucrados en el ciclo de vida de la entrega de software.
Hacer los cambios que describí anteriormente es un buen comienzo, sin embargo, le recomiendo que revise todo su marco de trabajo en busca de "puntos débiles", ya que puede haber mejoras que pueda hacer que no he cubierto. Por ejemplo, ¿está utilizando WebDriver Manager para administrar sus controladores o todavía los está actualizando manualmente?
También recomendaría establecer una fecha para hacerlo al menos una vez al año, aunque lo ideal sería cada seis meses. En el artículo, he incluido los cambios que se avecinan en Selenium 4.0. Revise las versiones alpha
de Selenium usted mismo. Los cambios serán drásticos y deberá estar preparado. Espero que hayas encontrado esto útil. Si descubre nuevos métodos o técnicas mientras realiza una limpieza general en su marco, compártalos con otros lectores de este blog agregándolos a la sección de comentarios a continuación.
Además, si desea ver las pruebas automatizadas en Selenium y cómo puede usar los modelos de objetos de página para escribir rutinas de prueba mantenibles y reutilizables, consulte Automatización en Selenium: Modelo de objetos de página y Fábrica de páginas .