Mochis NoticiasTecnologíaPruebas E2E automatizadas con Gauge y Selenium
Mochis NoticiasTecnologíaPruebas E2E automatizadas con Gauge y Selenium
Tecnología

Pruebas E2E automatizadas con Gauge y Selenium

Pruebas E2E automatizadas con Gauge y Selenium

Todo el mundo sabe lo importantes que son las pruebas en el desarrollo de software moderno. En el mundo actual de CI/CD, las pruebas son aún más cruciales y a menudo desempeñan el papel de criterios de aceptación del software. Teniendo esto en cuenta, está claro que el software moderno necesita pruebas buenas, rápidas, confiables y automatizadas para ayudar a entregar software de alta calidad rápidamente y sin errores importantes.

En este artículo, nos centraremos en cómo crear pruebas de aceptación/E2E para una aplicación micro-frontend utilizando el marco Gauge y Selenium. Verificaremos cómo probar ambas partes de nuestra aplicación: API y frontend dentro de un proceso que se puede integrar fácilmente en CD/CD.

¿Qué son las pruebas automatizadas de extremo a extremo (E2E)?

Las pruebas automatizadas de extremo a extremo son una de las técnicas de prueba que tiene como objetivo probar la funcionalidad de toda la aplicación (un microservicio en nuestro caso) y sus interacciones con otros microservicios, bases de datos, etc. Podemos decir que gracias a las pruebas automatizadas E2E , podemos simular escenarios del mundo real y probar nuestra aplicación desde la perspectiva del «usuario». En nuestro caso, podemos pensar en un «usuario» no solo como una persona que utilizará nuestra aplicación sino también como los consumidores de nuestra API (otros microservicios). Gracias a este enfoque de prueba, podemos estar seguros de que nuestra aplicación interactúa bien con el mundo circundante y que todos los componentes funcionan según lo diseñado.

¿Qué es una aplicación microfrontend?

Podemos decir que un concepto de micro-frontend es una especie de extensión del enfoque de microservicio que también cubre una parte del frontend. Por lo tanto, en lugar de tener una gran aplicación frontend y un equipo dedicado de especialistas frontend, podemos dividirla en partes más pequeñas e integrarla con microservicios y equipos backend. Gracias a esta aplicación frontal está «más cerca» del backend.

La competencia se concentra en un equipo que conoce muy bien su dominio. Esto significa que el equipo puede implementar el software de una manera más ágil, adaptarse a los requisitos cambiantes y entregar el producto mucho más rápido; es posible que también conozca el concepto de verticalización de equipo/software.

aplicación microfrontendaplicación microfrontend

Pruebas de aceptación en la práctica.

Echemos un vistazo a un ejemplo de la vida real de cómo podemos implementar pruebas de aceptación en nuestra aplicación.

Caso de uso

Nuestro equipo es responsable del desarrollo de API (microservicios backend) en una gran aplicación de comercio electrónico. Contamos con pruebas de API automatizadas integradas en nuestro proceso de CI/CD; utilizamos el marco Gauge para desarrollar pruebas de aceptación automatizadas para nuestras API de backend. Ejecutamos nuestras pruebas E2E en el entorno PreProd cada vez que implementamos una nueva versión de un microservicio. Si las pruebas tienen éxito, podremos implementar la nueva versión en el entorno de producción.

Canalización de CI/CDCanalización de CI/CD

Debido a cambios organizacionales y verticalización del equipo, tenemos que asumir la responsabilidad y propiedad de varios micro-frontends. Desafortunadamente, estas aplicaciones microfrontend no cuentan con pruebas automatizadas.

Decidimos solucionar este problema lo antes posible y con el menor esfuerzo posible. Para lograr este objetivo, decidimos ampliar nuestras pruebas de calibre automatizadas para cubrir también la parte frontal.

Como resultado de la investigación sobre cómo integrar pruebas frontend automatizadas en nuestra solución existente, llegamos a la conclusión de que la forma más sencilla de hacerlo es utilizar Selenium WebDriver. Gracias a esto, todavía podemos utilizar el marco Gauge como base: definición de casos de prueba, proporcionar datos de prueba, etc. – y prueba nuestra parte frontal.

En este artículo, veremos cómo integrar Selenium WebDriver con las pruebas de Gauge para una de nuestras páginas de microfrontend: «descripción general de pedidos».

Marco de medición

Gauge framework es un marco gratuito y de código abierto para crear y ejecutar pruebas de aceptación/E2E. Admite diferentes lenguajes como Java, JavaScript, C#, Python y Golang por lo que podemos elegir nuestro lenguaje preferido para implementar los pasos de prueba.

Cada escenario de prueba consta de pasos, cada uno independiente para que podamos reutilizarlo en muchos escenarios de prueba. Los escenarios se pueden agrupar en especificaciones. Para crear un escenario, todo lo que necesitamos hacer es llamar a los pasos apropiados con los argumentos deseados en el orden apropiado. Por lo tanto, contar con los pasos adecuados hace que crear el escenario sea bastante fácil, incluso para una persona sin conocimientos técnicos.

Una especificación de calibre es un conjunto de casos de prueba (escenarios) que describen la característica de la aplicación que se va a probar. Cada especificación está escrita utilizando una sintaxis similar a Markdown.

Visit store and search for the products
=======================================

Tags: preprod 
table:testData.csv

Running before each scenario
* Login as a user <user> with password <password>

Search for products
-------------------------------------
* Goto store home page
* Search for <product>

Tear down steps for this specification
---------------------------------------
* Logout user <user>

En esta especificación Visita la tienda y explora los productos. es el encabezado de la especificación, Buscar productos es un escenario único que consta de dos pasos Ir a la página de inicio de la tienda y Buscar .

Inicia sesión como usuario es un paso que se realizará antes de cada escenario en esta especificación. Lo mismo se aplica a la Usuario desconectado paso, que se ejecutará después de cada escenario.

Soporte para etiquetado de especificaciones de medición y pruebas basadas en datos.

La función de etiqueta nos permite etiquetar una especificación o escenarios y luego ejecutar pruebas solo para etiquetas específicas.

Las pruebas basadas en datos nos permiten proporcionar datos de prueba en forma de tabla. Gracias a esto, el escenario se ejecutará para todas las filas de la tabla. En nuestro ejemplo, Buscar productos El escenario se ejecutará para todos los productos enumerados en el archivo testData.csv. Gauge admite pruebas basadas en datos utilizando archivos CSV externos y tablas de Markdown definidas en la Especificación.

Para obtener más información sobre cómo escribir especificaciones de calibre, visite: https://docs.gauge.org/writing-specifications?os=windows&language=java&ide=vscode#specifications-spec. El marco de medición también nos proporciona un informe de prueba en forma de documento HTML en el que podemos encontrar información detallada sobre la ejecución de la prueba.

Los informes de prueba también se pueden ampliar con capturas de pantalla de fallas o mensajes personalizados.

Para obtener más información sobre el marco y cómo instalarlo y usarlo, visite la página oficial: https://gauge.org/.

Controlador web de selenio

Gauge en sí no tiene capacidad para automatizar navegadores, por lo que si queremos usarlo para cubrir las pruebas de interfaz, entonces necesitamos usar algún controlador web para eso. En nuestro ejemplo, usaremos Selenium WebDriver.

Selenium WebDriver es parte del conocido Selenium Framework. Utiliza API de navegador proporcionadas por diferentes proveedores para controlar los navegadores. Esto nos permite utilizar diferentes implementaciones de WebDriver y ejecutar nuestras pruebas utilizando casi cualquier navegador popular. Gracias a esto, podemos probar fácilmente nuestra UI en diferentes navegadores dentro de una única ejecución de prueba.

Para obtener más información, visite: https://www.selenium.dev/.

Para lograr nuestro objetivo de probar ambas partes de nuestra aplicación (puntos finales frontend y API) en el alcance de un proceso, podemos combinar estas dos soluciones, por lo que usamos Selenium WebDriver mientras implementamos los pasos de prueba de Gauge.

Un ejemplo

Si ya sabemos qué tipo de herramienta queremos usar para implementar nuestras pruebas como esta, veamos cómo podemos hacerlo.

En primer lugar, echemos un vistazo al archivo POM de nuestro proyecto.

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>3.1.4</version>
        <relativePath/>
    </parent>

    <groupId>com.gauge.automated</groupId>
    <artifactId>testautomation-gauge</artifactId>
    <version>1.0.0-SNAPSHOT</version>
    <name>testautomation-gauge</name>
    <description>testautomation - user acceptance tests using gauge framework</description>

    <properties>
        <java.version>17</java.version>
        <gauge-java.version>0.10.2</gauge-java.version>
        <selenium.version>4.14.1</selenium.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-webflux</artifactId>
        </dependency>
        <dependency>
            <groupId>com.thoughtworks.gauge</groupId>
            <artifactId>gauge-java</artifactId>
            <version>${gauge-java.version}</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.junit.jupiter</groupId>
            <artifactId>junit-jupiter-engine</artifactId>
            <version>5.9.3</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>org.seleniumhq.selenium</groupId>
            <artifactId>selenium-java</artifactId>
            <version>${selenium.version}</version>
        </dependency>
        <dependency>
            <groupId>org.seleniumhq.selenium</groupId>
            <artifactId>selenium-api</artifactId>
            <version>${selenium.version}</version>
        </dependency>
        <dependency>
            <groupId>org.seleniumhq.selenium</groupId>
            <artifactId>selenium-chrome-driver</artifactId>
            <version>${selenium.version}</version>
        </dependency>
        <dependency>
            <groupId>org.seleniumhq.selenium</groupId>
            <artifactId>selenium-chromium-driver</artifactId>
            <version>${selenium.version}</version>
        </dependency>
        <dependency>
            <groupId>org.seleniumhq.selenium</groupId>
            <artifactId>selenium-json</artifactId>
            <version>${selenium.version}</version>
        </dependency>
        <dependency>
            <groupId>org.seleniumhq.selenium</groupId>
            <artifactId>selenium-remote-driver</artifactId>
            <version>${selenium.version}</version>
        </dependency>
        <dependency>
            <groupId>org.seleniumhq.selenium</groupId>
            <artifactId>selenium-http</artifactId>
            <version>${selenium.version}</version>
        </dependency>
        <dependency>
            <groupId>org.seleniumhq.selenium</groupId>
            <artifactId>selenium-support</artifactId>
            <version>${selenium.version}</version>
        </dependency>
        <dependency>
            <groupId>org.seleniumhq.selenium</groupId>
            <artifactId>selenium-manager</artifactId>
            <version>${selenium.version}</version>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <executions>
                    <execution>
                        <goals>
                            <goal>build-info</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
            <plugin>
                <groupId>com.thoughtworks.gauge.maven</groupId>
                <artifactId>gauge-maven-plugin</artifactId>
                <version>1.6.1</version>
                <executions>
                    <execution>
                        <phase>test</phase>
                        <configuration>
                            <specsDir>specs</specsDir>
                        </configuration>
                        <goals>
                            <goal>execute</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>

</project>

Como podemos ver, todo lo que necesitamos hacer para usar Selenium WebDriver junto con Gauge es agregar las dependencias apropiadas a nuestro archivo POM. En este ejemplo, nos centramos en una implementación de Chrome WebDriver, pero si desea utilizar otro navegador (Firefox, Edge o Safari), todo lo que necesita hacer es agregar la dependencia de Selenium adecuada y configurar el controlador.

A continuación, lo que debemos hacer para habilitar Chrome Selenium WebDriver es configurarlo:

protected ChromeDriver setupChromeDriver()
{
    ChromeOptions chromeOptions = new ChromeOptions();
    // we should configure our environment to run chrome as non-root user instead
    chromeOptions.addArguments("--no-sandbox");
    chromeOptions.addArguments("--remote-allow-origins=*");
    // to run chrome in a headless mode
    chromeOptions.addArguments("--headless=new");
    // to avoid Chrome crashes in certain VMs
    chromeOptions.addArguments("--disable-dev-shm-usage");
    chromeOptions.addArguments("--ignore-certificate-errors");
    return new ChromeDriver(chromeOptions);

Y eso es todo, ahora podemos usar Selenium WebDriver en la implementación del medidor de pasos. Si desea utilizar una implementación de WebDriver diferente, debe configurarla correctamente, pero todos los demás pasos siguen siendo los mismos. Ahora echemos un vistazo a algunos detalles de implementación.

Especificación de muestra

Create order for a login user with default payment and shipping address
============================================================================================================

Tags: test,preprod, prod
table:testData.csv

Running before each scenario
* Login as a user <user> with password <password>


Case-1: Successfully create new order
----------------------------------------------------------------------------------
* Create order draft with item "TestItem"
* Create new order for a user
* Verify order details
* Get all orders for a user <user>
* Change status <status> for order <orderId>
* Fetch and verify order <orderId>
* Remove order <orderId>


Tear down steps for this specification
---------------------------------------------------------------------------------------------------------------------------------------------------
* Delete orders for a user <user>

En nuestro ejemplo, solo usamos unos pocos pasos simples, pero puedes usar tantos pasos como quieras y pueden ser mucho más complicados con más argumentos, etc.

Implementación de los pasos.

A continuación se muestra una implementación de algunos de los pasos de la prueba. Usamos Java para implementar los pasos, pero Gauge admite muchos otros lenguajes para hacer esto, así que siéntete libre de usar tu favorito.

import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeDriver;
import org.springframework.http.HttpHeaders;
import org.springframework.http.ResponseEntity;
import org.springframework.web.reactive.function.client.WebClientResponseException;
import com.thoughtworks.gauge.Step;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;


public class ExampleSpec extends BasicSpec
{
    @Step("Login as a user <user> with password <password>")
    public void logInAsAUser(final String login, final String password)
    {
       final ChromeDriver driver = setupChromeDriver();
       login(driver, login, password);
    }

    @Step("Create order draft with item <itemName>")
    public void createOrderDraft(final String itemName)
    {
       OrderDraftRequest request = buildDraftRequest(itemName);
       ResponseEntity<String> response = callOrderDraftEndpoint(request);

       assertNotNull(response);
       assertEquals(201, response.getStatusCodeValue());
    }

    @Step("Create new order for a user")
    public void createOrder(final String itemName)
    {
       final ChromeDriver driver = setupChromeDriver();
       createOrder(driver);
    }

    @Step("Verify order details")
    public void verifyOrderDetails()
    {
    final WebDriver driver = (WebDriver) ScenarioDataStore.get 
    (SCENARIO_DATA_STORE_WEB_DRIVER);
    final WebElement orderId = driver.findElement(By.tagName("order-id"));
    validateWebElement(orderId);
    final WebElement orderDate = popLinkHeader.findElement(By.className("order-date"));
    validateWebElement(orderId);
   }
    private ResponseEntity<String> callOrderDraftEndpoint(final OrderDraftRequest request)
    {
       ResponseEntity<String> response;
       final String traceId = generateXTraceId();
       log.info("addToCart x-trace-id {}", traceId);
       try
       {
          response = webClient.post()
             .uri(uriBuilder -> uriBuilder.path(appConfiguration.getOrderDraftEndpoint())
             .header(HttpHeaders.AUTHORIZATION, "Bearer " + appConfiguration.getToken())
             .header("Accept-Language", "de")
             .bodyValue(request)
             .retrieve()
             .toEntity(String.class)
             .block(Duration.ofSeconds(100));
       }
       catch (final WebClientResponseException webClientResponseException)
       {
          response = new ResponseEntity<>(webClientResponseException.getStatusCode());
       }
       return response;
    }

    private void login(final WebDriver driver, final String login, final String password)
    {
       driver.get(getLoginUrl().toString());
       // find email input
       WebElement emailInput = driver.findElement(By.xpath("//*[@id=\"email\"]"));
       // find password input
       WebElement passwordInput = driver.findElement(By.xpath("//*[@id=\"password\"]"));
       // find login button
       WebElement loginButton = driver.findElement(By.xpath("//*[@id=\"btn-login\"]"));
       // type user email into email input
       emailInput.sendKeys(login);
       // type user password into password input
       passwordInput.sendKeys(password);
       // click on login button
       loginButton.click();
    }

    private void createOrder(WebDriver driver) {
       driver.get(getCheckoutUrl().toString());
       WebElement createOrderButton = driver.findElement(By.xpath("//*[@id=\"create-     
       order\"]"));
       createOrderButton.click();
    
}
    private void validateWebElement(final WebElement webElement)
    {
      assertNotNull(webElement);
      assertTrue(webElement.isDisplayed());
    }

Como podemos ver, es bastante sencillo utilizar Selenium WebDriver dentro de las pruebas de Gauge. Los complementos de WebDriver proporcionan una poderosa extensión para nuestras pruebas y nos permiten crear escenarios de Gauge que también prueban la interfaz de nuestra aplicación. Puede utilizar múltiples implementaciones de WebDriver para cubrir diferentes navegadores web, asegurando que su interfaz de usuario se vea y se comporte igual en diferentes entornos.

El ejemplo presentado se puede integrar fácilmente en su proceso de CI/CD. Gracias a esto podrá formar parte de las pruebas de aceptación de nuestra aplicación. Esto le permite entregar su software aún más rápido con la confianza de que nuestros cambios están bien probados.

Source link

Hi, I’m Corina Guzman

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *