Integración de capturas de pantalla y otros archivos adjuntos en Allure Report con Selenium y JUnit 5
Leer los resultados de las pruebas debe ser rápido. Idealmente, la persona que revisa los resultados debería poder identificar qué salió mal sin revisar código adicional, usar un depurador o pedir ayuda a sus compañeros de equipo.
Para lograr esto, debemos proporcionar mucha información en un espacio reducido, y tomar capturas de pantalla es una excelente manera de hacerlo. Probemos capturar capturas de pantalla con JUnit 5 y Selenium y luego visualizarlas usando Allure Report.
1. Preparación
Requisitos previos
Asegúrate de cumplir con los siguientes requisitos previos:
Lista de dependencias
Esta guía utiliza los siguientes paquetes:
- org.aspectj:aspectjweaver: 1.9.22
- org.junit:junit-bom: 5.12.0
- org.junit.jupiter:junit-jupiter-api: 5.12.0
- org.junit.jupiter:junit-jupiter-engine: 5.12.0
- org.seleniumhq.selenium:selenium-java: 4.29.0
- io.qameta.allure:allure-bom: 2.29.1
- io.qameta.allure:allure-junit5: 2.29.1
Ejemplo de código
El código fuente utilizado en esta guía está disponible en https://github.com/allure-examples/guide-junit5-selenium-screenshots.
Configuración
Para ejecutar los ejemplos en esta guía:
Instala Java
Instala Gradle
Instala Allure Report
Descarga el repositorio de ejemplo
Navega al repositorio y ejecuta el siguiente comando:
shell./gradlew test
2. Capturas de pantalla con Selenium
Para tomar capturas de pantalla con Selenium en cualquier momento, puedes usar el método getScreenshotAs
proporcionado por la interfaz TakesScreenshot
. Todos los WebDrivers y WebElements de Selenium implementan esta interfaz. Por ejemplo:
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardCopyOption;
import org.openqa.selenium.OutputType;
import org.openqa.selenium.TakesScreenshot;
import org.openqa.selenium.WebDriver;
public class ScreenshotUtils {
public static void savePageScreenshot(WebDriver driver, Path path) {
File screenshotFile = ((TakesScreenshot) webDriver).getScreenshotAs(OutputType.FILE);
try {
Files.copy(screenshotFile.toPath(), path, StandardCopyOption.REPLACE_EXISTING);
} catch (IOException e) {
System.out.println("Can't copy the screenshot file:" + e.getMessage());
}
}
}
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardCopyOption;
import org.openqa.selenium.OutputType;
import org.openqa.selenium.WebElement;
public class ScreenshotUtils {
public static void saveElementScreenshot(WebElement webElement, Path path) {
File screenshotFile = webElement.getScreenshotAs(OutputType.FILE);
try {
Files.copy(screenshotFile.toPath(), path, StandardCopyOption.REPLACE_EXISTING);
} catch (IOException e) {
System.out.println("Can't copy the screenshot file:" + e.getMessage());
}
}
}
Cada vez que llames a cualquiera de las funciones de ejemplo, se guardará una captura de pantalla en path
.
3. Capturas de pantalla automáticas en caso de fallo
Para tomar capturas de pantalla automáticamente cada vez que falle una prueba, puedes crear una clase que implemente la interfaz TestExecutionExceptionHandler
de JUnit 5 y sobrescriba el método handleTestExecutionException
. Cuando una prueba falla, se genera una excepción, y el método handleTestExecutionException
permite manejar esta excepción. Dentro del método sobrescrito, debes obtener un objeto WebDriver
o WebElement
y usar la función de la sección anterior. Por ejemplo:
import java.nio.file.Path;
import java.util.Objects;
import java.util.function.Function;
import org.junit.jupiter.api.extension.ExtensionContext;
import org.junit.jupiter.api.extension.TestExecutionExceptionHandler;
import org.openqa.selenium.WebDriver;
public class AutoScreenshotExtension implements TestExecutionExceptionHandler {
// Función para extraer WebDriver del ExtensionContext
private final Function<ExtensionContext, WebDriver> driverSupplier;
public AutoScreenshotExtension(Function<ExtensionContext, WebDriver> driverSupplier) {
this.driverSupplier = driverSupplier;
}
@Override
public void handleTestExecutionException(final ExtensionContext context, final Throwable throwable) throws Throwable {
final WebDriver webDriver = this.driverSupplier.apply(context);
if (Objects.nonNull(webDriver)) {
final Path path = Path.of("Screenshot on failure (" + throwable.getClass().getSimpleName() + ").png");
ScreenshotUtils.savePageScreenshot(webDriver, path);
}
throw throwable;
}
}
Después de esto, debes agregar tu clase que implementa la interfaz TestExecutionExceptionHandler
como una extensión en tu clase de prueba. En el ejemplo, existe WebdriverExtension
, que crea los web drivers para las pruebas. Esta extensión también proporciona la instancia actual del web driver a AutoScreenshotExtension
cuando una prueba falla. Esto se hace a través de la función lambda que pasamos al constructor de AutoScreenshotExtension
:
import org.junit.jupiter.api.extension.RegisterExtension;
public class ScreenshotTest {
// Extensión para WebDriver
@RegisterExtension
WebdriverExtension webDriverManager = new WebdriverExtension();
@RegisterExtension
AutoScreenshotExtension screenshotManager = new AutoScreenshotExtension(
c -> this.webDriverManager.getWebDriver(c));
// Lógica de prueba
}
De esta manera, en cada fallo de prueba, se guardará una captura de pantalla en path
.
4. Integración con Allure Report
Tomar capturas de pantalla ayuda a comprender por qué fallan las pruebas, pero verlas por separado puede llevar mucho tiempo. Cuando la información de la prueba está dispersa en diferentes lugares, encontrar y solucionar problemas tarda más.
Para facilitar esto, las capturas de pantalla deben agregarse directamente a los informes de Allure. De este modo, todos los detalles importantes de la prueba estarán en un solo lugar para un análisis y solución de problemas más rápidos.
En los informes de Allure, puedes ver las capturas de pantalla junto a las pruebas en las que ocurrieron. También encontrarás mensajes de error y otros detalles importantes, lo que facilita la revisión de los resultados en un solo lugar:
Para adjuntar capturas de pantalla a Allure con Selenium, puedes usar una de las siguientes opciones:
- la anotación
@Attachment
- el método estático
Allure.attachment
- el método estático
Allure.addAttachment
Con la anotación @Attachment
, debes definir un método que devuelva un array de bytes byte[]
o una String
que represente los datos adjuntos. Para asegurarte de que el navegador muestra correctamente el adjunto, recomendamos especificar el tipo de medio en los argumentos de la anotación. Por ejemplo:
import io.qameta.allure.Attachment;
import org.openqa.selenium.OutputType;
import org.openqa.selenium.TakesScreenshot;
import org.openqa.selenium.WebDriver;
public class ScreenshotUtils {
@Attachment(type = "image/png")
public static byte[] attachPageScreenshot(WebDriver webDriver) {
return ((TakesScreenshot) webDriver).getScreenshotAs(OutputType.BYTES);
}
}
import io.qameta.allure.Attachment;
import org.openqa.selenium.OutputType;
import org.openqa.selenium.WebElement;
public class ScreenshotUtils {
@Attachment(type = "image/png")
public static byte[] attachElementScreenshot(WebElement webElement) {
return webElement.getScreenshotAs(OutputType.BYTES);
}
}
Con el método estático Allure.attachment
, puedes usar funciones ligeramente modificadas de la sección Capturas de pantalla con Selenium.
import io.qameta.allure.Allure;
import java.io.ByteArrayInputStream;
import org.openqa.selenium.OutputType;
import org.openqa.selenium.TakesScreenshot;
import org.openqa.selenium.WebDriver;
public class ScreenshotUtils {
public static void attachPageScreenshot(WebDriver webDriver, String name) {
byte[] screenshotBytes = ((TakesScreenshot) webDriver).getScreenshotAs(OutputType.BYTES);
Allure.attachment(name, new ByteArrayInputStream(screenshotBytes));
}
}
import io.qameta.allure.Allure;
import java.io.ByteArrayInputStream;
import org.openqa.selenium.OutputType;
import org.openqa.selenium.WebElement;
public class ScreenshotUtils {
public static void attachElementScreenshot(WebElement webElement, String name) {
byte[] screenshotBytes = webElement.getScreenshotAs(OutputType.BYTES);
Allure.attachment(name, new ByteArrayInputStream(screenshotBytes));
}
}
Para tomar automáticamente una captura de pantalla cuando falla una prueba con Allure, puedes usar la implementación de TestExecutionExceptionHandler
como se describe en Capturas de pantalla automáticas en caso de fallo y actualizar el método handleTestExecutionException
. Por ejemplo, para usar el método estático Allure.attachment
:
import java.util.Objects;
import java.util.function.Function;
import org.junit.jupiter.api.extension.ExtensionContext;
import org.junit.jupiter.api.extension.TestExecutionExceptionHandler;
import org.openqa.selenium.WebDriver;
public class AutoScreenshotExtension implements TestExecutionExceptionHandler {
private final Function<ExtensionContext, WebDriver> driverSupplier;
public AutoScreenshotExtension(Function<ExtensionContext, WebDriver> driverSupplier) {
this.driverSupplier = driverSupplier;
}
@Override
public void handleTestExecutionException(final ExtensionContext context, final Throwable throwable) throws Throwable {
final WebDriver webDriver = this.driverSupplier.apply(context);
if (Objects.nonNull(webDriver)) {
final String attachmentName = "Screenshot on failure (" + throwable.getClass().getSimpleName() + ")";
ScreenshotUtils.attachPageScreenshot(webDriver, attachmentName);
}
throw throwable;
}
}
5. Otros tipos de archivos adjuntos
Allure Report también puede manejar otros tipos de archivos adjuntos, como texto, tablas, listas de URI, documentos (XML, JSON, YAML):
Allure.addAttachment("response content", "text/xml", responseContent);
Un ejemplo de un informe con este tipo de archivo adjunto:
Puedes consultar la documentación oficial para más información sobre archivos adjuntos con JUnit 5 y tipos de archivos adjuntos.
6. Conclusión
Con Selenium y JUnit 5, puedes capturar capturas de pantalla en cualquier momento durante tus pruebas, o puedes configurar una función que tome capturas de pantalla automáticamente en momentos específicos, como cuando una prueba falla o cuando pasa. Allure Report te ayuda a ver estas capturas de pantalla junto con otros tipos de archivos (como texto, documentos, tablas y videos) para cada caso de prueba. Esto proporciona a cualquier persona que revise tus pruebas suficiente información para comprender y solucionar cualquier problema que surja.