Capítulo 1. Introducción al selenio
Este trabajo se ha traducido utilizando IA. Agradecemos tus opiniones y comentarios: translation-feedback@oreilly.com
Selenium es una suite de código abierto compuesta por un conjunto de bibliotecas y herramientas que permiten la automatización de los navegadores web. Podemos ver Selenium como un proyecto paraguas de con tres componentes básicos: WebDriver, Grid e IDE (Entorno de Desarrollo Integrado). Selenium WebDriver es una biblioteca que permite manejar navegadores mediante programación. Así, podemos utilizar Selenium WebDriver para navegar por sitios web e interactuar con páginas web (por ejemplo, hacer clic en enlaces, rellenar formularios, etc.) como lo haría un usuario real, de forma automatizada. El uso principal de Selenium WebDriver es la prueba automatizada de aplicaciones web. Otros usos de Selenium son la automatización de tareas de administración basadas en web o el web scraping (extracción automatizada de datos web).
Este capítulo ofrece en una visión general de los componentes principales de Selenium: WebDriver, Grid e IDE. A continuación, revisa el ecosistema de Selenium, es decir, otras herramientas y tecnologías a su alrededor. Por último, analiza los fundamentos de las pruebas de software relacionados con Selenium.
Componentes principales de Selenium
Jason Huggins y Paul Hammant crearon Selenium en 2004 mientras trabajaban en Thoughtworks. Eligieron el nombre "Selenium" como contrapartida a Mercury, un marco de pruebas existente desarrollado por Hewlett-Packard. El nombre es significativo porque el selenio químico es conocido por reducir la toxicidad del mercurio.
Esa versión inicial de Selenium (conocida hoy como Selenium Core) es una biblioteca JavaScript que suplanta las acciones del usuario en aplicaciones web. Selenium Core interpreta los llamados comandos Selenese para realizar esta tarea. Estos comandos se codifican como una tabla HTML compuesta de tres partes: comando (acción ejecutada en un navegador web, como abrir una URL o hacer clic en un enlace), objetivo (localizador que identifica un elemento web, como el atributo de un componente determinado) y valor (datos opcionales, como el texto escrito en un campo de formulario web).
Huggins y Hammant añadieron una capa de scripting a Selenium Core en un nuevo proyecto llamado Selenium Remote Control (RC). Selenium RC sigue una arquitectura cliente-servidor. Los clientes utilizan un lenguaje de enlace (como Java o JavaScript) para enviar comandos Selenese a través de HTTP a un proxy intermedio llamado Servidor Selenium RC. Este servidor lanza navegadores web a petición, inyectando la biblioteca Selenium Core en un sitio web y enviando las peticiones de los clientes a Selenium Core. Además, el Servidor Selenium RC enmascara el sitio web de destino en la misma URL local de la biblioteca Selenium Core inyectada para evitar problemas de política de mismo origen. Este enfoque supuso un cambio de juego para la automatización del navegador en aquel momento, pero tenía limitaciones significativas. En primer lugar, dado que JavaScript es la tecnología subyacente para soportar la automatización, algunas acciones no están permitidas porque JavaScript no las permite; por ejemplo, cargar y descargar archivos o manejar ventanas emergentes y cuadros de diálogo, por nombrar algunas. Además, Selenium RC introduce una sobrecarga relevante que afecta a su rendimiento.
Paralelamente, Simon Stewart creó el proyecto WebDriver en 2007. WebDriver y Selenium RC eran equivalentes desde una perspectiva funcional, es decir, ambos proyectos permiten a los programadores hacerse pasar por usuarios web utilizando un lenguaje de programación. Sin embargo, WebDriver utiliza el soporte nativo de cada navegador para llevar a cabo la automatización y, por tanto, sus capacidades y rendimiento son muy superiores a los de RC. En 2009, tras una reunión en entre Jason Huggins y Simon Stewart en la Conferencia de Automatización de Pruebas de Google, decidieron fusionar Selenium y WebDriver en un único proyecto. El nuevo proyecto se llamó Selenium WebDriver o Selenium 2. Este nuevo proyecto utiliza un protocolo de comunicación basado en HTTP combinado con el soporte nativo de automatización en el navegador. Ese enfoque sigue siendo la base de Selenium 3 (publicado en 2016) y Selenium 4 (publicado en 2021). Ahora nos referimos a Selenium RC y Core como "Selenium 1", y se desaconseja su uso en favor de Selenium WebDriver. Este libro se centra en la última versión de Selenium WebDriver hasta la fecha, es decir, la versión 4.
Consejo
El Apéndice A resume las novedades que incorpora Selenium 4. Este apéndice también contiene una guía de migración para pasar de Selenium 3 a 4.
Hoy en día, Selenium es una conocida suite de automatización compuesta por tres subproyectos: WebDriver, Grid e IDE. En las subsecciones siguientes de se presentan las principales características de cada uno de ellos.
Selenium WebDriver
Selenium WebDriver es una biblioteca que permite controlar los navegadores web de forma automática. Para ello, proporciona una API multiplataforma en diferentes enlaces de lenguaje. Los lenguajes de programación oficiales admitidos por Selenium WebDriver son Java, JavaScript, Python, Ruby y C#. Internamente, Selenium WebDriver utiliza el soporte nativo implementado por cada navegador para llevar a cabo el proceso de automatización. Por esta razón, necesitamos colocar un componente llamado driver entre el script que utiliza la API de Selenium WebDriver y el navegador. La Tabla 1-1 resume los navegadores y controladores soportados oficialmente por Selenium WebDriver.
Nota
El nombre Selenium se utiliza ampliamente para referirse a la biblioteca para la automatización del navegador. Puesto que este término es también el nombre del proyecto paraguas, en este libro utilizo Selenium para identificar la suite de automatización del navegador, que está formada por tres componentes: Selenium WebDriver (biblioteca), Selenium Grid (infraestructura) y Selenium IDE (herramienta).
Navegador | Conductor | Sistema operativo | Mantenedor | Descarga |
---|---|---|---|---|
Cromo/Chromium |
cromodriver |
Windows/macOS/Linux |
||
Perímetro |
msedgedriver |
Windows/macOS/Linux |
Microsoft |
https://developer.microsoft.com/en-us/microsoft-edge/tools/webdriver |
Firefox |
geckodriver |
Windows/macOS/Linux |
Mozilla |
|
Ópera |
operadriver |
Windows/macOS/Linux |
Opera Software AS |
|
Internet Explorer |
IEDriverServer |
Windows |
Proyecto Selenio |
|
Safari |
safaridriver |
macOS |
Manzana |
Incorporado |
Los controladores (por ejemplo, chromedriver, geckodriver, etc.) son archivos binarios dependientes de la plataforma que reciben comandos de un script WebDriver y los traducen a algún lenguaje específico del navegador. En las primeras versiones de Selenium WebDriver (es decir, en Selenium 2), estos comandos (también conocidos como protocolo Selenium) eran mensajes JSON a través de HTTP (el llamado Protocolo JSON Wire). Hoy en día, esta comunicación (todavía JSON sobre HTTP) sigue una especificación estándar denominada W3C WebDriver. Esta especificación es el protocolo Selenium preferido a partir de Selenium 4.
La Figura 1-1 resume la arquitectura básica de Selenium WebDriver que hemos visto hasta ahora. Como puedes ver, esta arquitectura tiene tres niveles. En primer lugar, encontramos un script que utiliza la API de Selenium WebDriver (Java, JavaScript, Python, Ruby o C#). Este script envía comandos W3C WebDriver a la segunda capa, en la que encontramos los controladores. Esta figura muestra el caso concreto de de utilizar chromedriver (para controlar Chrome) y geckodriver (para controlar Firefox). Por último, la tercera capa contiene los navegadores web. En el caso de Chrome, el navegador nativo sigue el protocolo DevTools. DevTools es un conjunto de herramientas de desarrollo para navegadores basados en el motor de renderizado Blink, como Chrome, Chromium, Edge u Opera. El Protocolo DevTools se basa en mensajes JSON-RPC y permite inspeccionar, depurar y perfilar estos navegadores. En Firefox, el soporte nativo de automatización utiliza el protocolo Marionette. Marionette es un protocolo remoto basado en JSON, que permite instrumentar y controlar navegadores web basados en el motor Gecko (como Firefox).
En general, Selenium WebDriver permite controlar los navegadores web como lo haría un usuario, pero programáticamente. Para ello, la API de Selenium WebDriver proporciona una amplia variedad de funciones para navegar por páginas web, interactuar con elementos web o suplantar acciones del usuario, entre otras muchas capacidades. La aplicación objetivo está basada en la web, como sitios web estáticos, aplicaciones web dinámicas, aplicaciones de página única (SPA), sistemas empresariales complejos con una interfaz web, etc.
Rejilla Selenio
El segundo proyecto de la familia Selenium es Selenium Grid. Philippe Hanrigou comenzó el desarrollo de este proyecto en 2008. Selenium Grid es un grupo de hosts en red que proporciona una infraestructura de navegador para Selenium WebDriver. Esta infraestructura permite la ejecución (paralela) de scripts Selenium WebDriver con navegadores remotos de distinta naturaleza (tipos y versiones) en múltiples sistemas operativos.
La Figura 1-2 muestra la arquitectura básica de Selenium Grid. Como puedes ver, un grupo de nodos proporciona los navegadores utilizados por los scripts Selenium. Estos nodos pueden utilizar distintos sistemas operativos (como vimos en la Tabla 1-1) con varios navegadores instalados. El punto de entrada central a esta Rejilla es el Hub (también conocido como Servidor Selenium). Este componente del lado del servidor realiza un seguimiento de los nodos y procesa las solicitudes de los scripts de Selenium. Al igual que en Selenium WebDriver, la especificación W3C WebDriver es el protocolo estándar para la comunicación entre estos scripts y el Hub.
La arquitectura hub-nodes en Grid está disponible desde Selenium 2. Esta arquitectura también está presente en Selenium 3 y 4. Sin embargo, esta arquitectura centralizada puede provocar cuellos de botella en el rendimiento si el número de peticiones al Hub es elevado. Selenium 4 proporciona una versión totalmente distribuida de Selenium Grid para evitar este problema. Esta arquitectura implementa mecanismos avanzados de equilibrio de carga para evitar la sobrecarga de cualquier componente.
Consejo
El Capítulo 6 describe cómo configurar Selenium Grid siguiendo el enfoque clásico (basado en un concentrador y un conjunto de nodos). Este capítulo también cubre el modo autónomo (es decir, concentrador y nodo(s) alojados en la misma máquina) y la arquitectura totalmente distribuida.
IDE Selenio
Selenium IDE es el último componente básico de la suite Selenium. Shinya Kasatani creó este proyecto en 2006. Selenium IDE es una herramienta de que implementa la denominada técnica de automatización de grabación y reproducción (R&P). Como su nombre indica, esta técnica consta de dos pasos. En primer lugar, en Selenium IDE, la parte de grabación captura las interacciones del usuario con un navegador, codificando estas acciones como comandos Selenium. En segundo lugar, utilizamos el script Selenium generado para ejecutar automáticamente una sesión de navegador(reproducción).
Esta primera versión de Selenium IDE era un complemento de Firefox que incrustaba Selenium Core para grabar, editar y reproducir scripts de Selenium. Estas primeras versiones eran módulos XPI (es decir, una tecnología utilizada para crear extensiones de Mozilla). A partir de la versión 55 (publicada en 2017), Firefox migró la compatibilidad con complementos a la especificación W3C Browser Extension. Como consecuencia, se dejó de utilizar Selenium IDE, y durante algún tiempo no ha sido posible utilizarlo. El equipo de Selenium reescribió Selenium IDE siguiendo la recomendación de Extensiones de Navegador para solucionar este problema. Gracias a ello, ahora podemos utilizar Selenium IDE en varios navegadores, como Chrome, Edge y Firefox.
La Figura 1-3 muestra la nueva GUI (Interfaz Gráfica de Usuario) Selenium IDE.
Mediante esta GUI, los usuarios pueden registrar interacciones con un navegador y editar y ejecutar el script generado. Selenium IDE codifica cada interacción en diferentes partes: un comando (es decir, la acción ejecutada en el navegador), un objetivo (es decir, el localizador del elemento web) y un valor (es decir, los datos manejados). Opcionalmente, podemos incluir una descripción del comando. La Figura 1-3 muestra un ejemplo grabado de estos pasos:
-
Abre el sitio web(https://bonigarcia.dev/selenium-webdriver-java). Utilizaremos este sitio web como sitio de prácticas en el resto del libro.
-
Haz clic en el enlace con el texto "GitHub". Como resultado, la navegación se desplaza al código fuente del repositorio de ejemplos.
-
Comprueba que el título del libro(Hands-On Selenium WebDriver with Java) está presente en la página web.
-
Cierra el navegador.
Una vez que hemos creado un script en Selenium IDE, podemos exportar este script como una prueba Selenium WebDriver. Por ejemplo, la Figura 1-4 muestra cómo convertir el ejemplo presentado en como un caso de prueba JUnit. Por último, podemos guardar el proyecto en nuestra máquina local. El proyecto resultante de este ejemplo está disponible en el repositorio GitHub de ejemplos.
Nota
El proyecto Selenium está portando Selenium IDE a Electron en el momento de escribir esto. Electron es un framework de código abierto basado en Chromium y Node.js que permite el desarrollo de aplicaciones de escritorio.
Ecosistema del selenio
Los ecosistemas de software son colecciones de elementos que interactúan con un mercado compartido sustentado por un fondo tecnológico común. En el caso de Selenium, su ecosistema incluye los proyectos centrales oficiales y otros proyectos, bibliotecas y actores relacionados. Esta sección revisa el ecosistema de Selenium, dividido en las siguientes categorías: enlaces de lenguaje, gestores de controladores, marcos, infraestructura del navegador y comunidad.
Enlaces lingüísticos
Como ya sabemos, el proyecto Selenium mantiene varios enlaces de lenguaje para Selenium WebDriver: Java, JavaScript, Python, Ruby y C#. No obstante, también están disponibles otros lenguajes. La Tabla 1-2 resume estos enlaces de lenguaje para Selenium WebDriver mantenidos por la comunidad.
Nombre | Lengua | Licencia | Mantenedor | Página web |
---|---|---|---|---|
hs-webdriver |
Haskell |
Cláusula BSD-3 |
Adam Curtis |
|
php-webdriver |
PHP |
MIT |
Facebook, comunidad |
|
RSelenio |
R |
AGPLv3 |
rOpenSci |
|
Selenio |
Ve a |
MIT |
Miki Tebeka |
|
Selenium-Remote-Driver |
Perl |
Apache 2.0 |
George S. Baugh |
|
webdriver.dart |
Dardo |
Apache 2.0 |
||
wd |
JavaScript |
Apache 2.0 |
Adán Cristiano |
Gestores de conductores
Los controladores son componentes obligatorios para controlar los navegadores web de forma nativa con Selenium WebDriver (véase la Figura 1-1). Por esta razón, antes de utilizar la API de Selenium WebDriver, necesitamos gestionar estos controladores. La gestión de controladores es el proceso de descargar, configurar y mantener el controlador adecuado para un navegador determinado. Los pasos habituales en el procedimiento de gestión de controladores son:
- 1. Descarga
-
Cada navegador tiene su propio controlador. Por ejemplo, utilizamos chromedriver para controlar Chrome o geckodriver para Firefox (ver Tabla 1-1). El controlador es un archivo binario específico de la plataforma. Por lo tanto, tenemos que descargar el controlador adecuado para un sistema operativo determinado (normalmente, Windows, macOS o Linux). Además, tenemos que tener en cuenta la versión del controlador, ya que una versión del controlador es compatible con una versión (o rango) determinada del navegador. Por ejemplo, para utilizar Chrome 91.x, necesitamos descargar chromedriver 91.0.4472.19. Normalmente encontramos la compatibilidad navegador-controlador en la documentación del controlador o en las notas de la versión.
- 2. Configura
-
Una vez que tengamos el controlador adecuado, tenemos que hacerlo disponible en nuestro script Selenium WebDriver.
- 3. Mantenimiento
-
Los navegadores web modernos (por ejemplo, Chrome, Firefox o Edge) se actualizan a sí mismos de forma automática y silenciosa, sin avisar al usuario. Por este motivo, y en lo que respecta a Selenium WebDriver, en necesitamos mantener a tiempo la compatibilidad entre la versión del navegador y la del controlador para estos navegadores denominados evergreen.
Como puedes ver, el proceso de mantenimiento del controlador puede llevar mucho tiempo. Además, puede causar problemas a los usuarios de Selenium WebDriver (por ejemplo, pruebas fallidas por incompatibilidad navegador-controlador tras una actualización automática del navegador). Por este motivo, los denominados gestores de controladores pretenden llevar a cabo el proceso de gestión de controladores de forma automatizada hasta cierto punto. En la Tabla 1-3 se resumen los gestores de controladores disponibles para las distintas vinculaciones lingüísticas.
Nombre | Lengua | Licencia | Mantenedor | Página web |
---|---|---|---|---|
WebDriverManager |
Java |
Apache 2.0 |
Boni García |
|
webdriver-manager |
JavaScript |
MIT |
||
webdriver-manager |
Python |
Apache 2.0 |
Serhii Pirohov |
|
WebDriverManager.Net |
C# |
MIT |
Aliaksandr Rasolka |
|
webdrivers |
Ruby |
MIT |
Tito Fortner |
Consejo
En este libro, recomiendo utilizar WebDriverManager porque automatiza todo el proceso de mantenimiento del controlador (es decir, descarga, configuración y mantenimiento). Consulta el Apéndice B para obtener más información sobre la gestión automatizada y manual de controladores .
Herramientas de localización
La API de Selenium WebDriver proporciona diferentes formas de localizar elementos web (consulta el Capítulo 3): por atributo (id, nombre o clase), por texto de enlace (completo o parcial), por nombre de etiqueta, por selector CSS (Hojas de estilo en cascada) o por lenguaje de rutas XML (XPath). Hay herramientas específicas que pueden ayudar a identificar y generar estos localizadores. La Tabla 1-4 muestra algunas de estas herramientas.
Nombre | Tipo | Licencia | Mantenedor | Página web |
---|---|---|---|---|
Chrome DevTools |
Herramienta de navegación incorporada |
Freeware propietario, basado en código abierto |
||
Herramientas para desarrolladores de Firefox |
Herramienta de navegación incorporada |
MPL 2.0 |
Mozilla |
|
Cropath |
Extensión del navegador |
Freeware |
AutonomIQ |
|
SelectoresHub |
Extensión del navegador |
Freeware |
Sanjay Kumar |
|
Constructor POM |
Extensión del navegador |
Freeware |
Corporación LogiGear |
Marcos
En ingeniería de software , un framework es un conjunto de bibliotecas y herramientas utilizadas como base conceptual y tecnológica y como soporte para el desarrollo de software. Selenium es la base de los frameworks que envuelven, mejoran o complementan sus características por defecto. La Tabla 1-5 contiene algunos de estos marcos y bibliotecas basados en Selenium.
Nombre | Lengua | Descripción | Licencia | Mantenedor | Página web |
---|---|---|---|---|---|
CodeceptJS |
JavaScript |
Marco de pruebas multibackend que modela las interacciones del navegador como pasos sencillos desde la perspectiva del usuario |
MIT |
Michael Bodnarchuk |
|
FluentSelenium |
Java |
API Fluent para Selenium WebDriver |
Apache 2.0 |
Paul Hammant |
|
FluentLenium |
Java |
Marco de automatización de sitios web y móviles para crear pruebas WebDriver legibles y reutilizables |
Apache 2.0 |
Equipo FluentLenium |
|
Healenium |
Java |
Biblioteca para mejorar la estabilidad de las pruebas Selenium utilizando algoritmos de aprendizaje automático para analizar elementos web y web móvil |
Apache 2.0 |
Anna Chernyshova y Dmitriy Gumeniuk |
|
Helio |
Python |
API de alto nivel basada en Selenium WebDriver |
MIT |
Michael Herrmann |
|
QAF (Marco de Automatización QMetry) |
Java |
Plataforma de automatización de pruebas para aplicaciones web y móviles |
MIT |
Chirag Jayswal |
|
Rayo |
Java |
Cliente Selenium WebDriver ligero para Java |
Apache 2.0 |
FluentLenium |
|
Nerodia |
Python |
Adaptación a Python de la gema Watir de Ruby |
MIT |
Lucas Tierney |
|
Marco Robot |
Python, Java, .NET y otros |
Marco genérico de automatización basado en casos de prueba legibles por humanos |
Apache 2.0 |
Fundación Robot Framework |
|
Equipo seleniuro |
Java |
API fluida y concisa para Selenium WebDriver |
MIT |
Equipo seleniuro |
|
SeleniumBase |
Python |
Marco de automatización del navegador basado en WebDriver y pytest |
MIT |
Michael Mintz |
|
Watir (Pruebas de aplicaciones web en Ruby) |
Ruby |
Librería Gem basada en WebDriver para automatizar navegadores web |
MIT |
Tito Fortner |
|
WebDriverIO |
JavaScript |
Marco de automatización de pruebas basado en WebDriver y Appium |
MIT |
Christian Bromann |
|
Vigilancia nocturna.js |
JavaScript |
Marco integrado de pruebas de extremo a extremo basado en el WebDriver del W3C |
MIT |
Andrei Rusu |
|
Applitools |
Java, JavaScript, C#, Ruby, PHP, Python |
Marco de automatización de pruebas para pruebas visuales de regresión de la interfaz de usuario y pruebas A/B. Proporciona SDK para Selenium, Appium y otros. |
Comercial |
Equipo Applitools |
|
Estudio Katalon |
Java, Groovy |
Plataforma de automatización de pruebas con Selenium WebDriver, Appium y proveedores en la nube |
Comercial |
Equipo Katalon |
|
TestProject |
Java, C#, Python |
Plataforma de automatización de pruebas para aplicaciones web y móviles basada en Selenium y Appium |
Comercial |
Equipo TestProject |
Infraestructura del navegador
Podemos utilizar Selenium WebDriver para controlar navegadores locales instalados en la máquina que ejecuta el script WebDriver. Además, Selenium WebDriver puede controlar navegadores remotos (es decir, los que se ejecutan en otros hosts). En este caso, podemos utilizar Selenium Grid para dar soporte a la infraestructura del navegador remoto. Sin embargo, esta infraestructura puede ser difícil de crear y mantener.
Alternativamente, nosotros podemos utilizar un proveedor en la nube para externalizar la responsabilidad de dar soporte a la infraestructura del navegador. En el ecosistema Selenium, un proveedor en la nube es una empresa o producto que suministra servicios gestionados para pruebas automatizadas. Estas empresas suelen ofrecer soluciones comerciales para pruebas web y móviles. Los usuarios de un proveedor en la nube solicitan navegadores a la carta de distintos tipos, versiones y sistemas operativos. Además, estos proveedores suelen ofrecer servicios adicionales para facilitar las actividades de pruebas y monitoreo, como el acceso a grabaciones de sesiones o capacidades de análisis, por nombrar algunos. Algunos de los proveedores en la nube más relevantes para Selenium en la actualidad son Sauce Labs, BrowserStack, LambdaTest, CrossBrowserTesting, Moon Cloud, TestingBot, Perfecto o Testinium.
Otra solución que podemos utilizar en para dar soporte a la infraestructura del navegador para Selenium es Docker. Docker es una tecnología de software de código abierto que permite a los usuarios empaquetar y ejecutar aplicaciones como contenedores ligeros y portátiles. La plataforma Docker tiene dos componentes principales: el motor Docker, una herramienta para crear y ejecutar contenedores, y el Docker Hub, un servicio en la nube para distribuir imágenes Docker. En el ámbito de Selenium, podemos utilizar Docker para empaquetar y ejecutar navegadores en contenedores. La Tabla 1-6 presenta un resumen de los proyectos relevantes que utilizan Docker en el ecosistema Selenium.
Nombre | Descripción | Licencia | Mantenedor | Página web |
---|---|---|---|---|
docker-selenium |
Imágenes Docker oficiales para Selenium Grid |
Apache 2.0 |
Proyecto Selenio |
|
Selenoide |
Implementación Golang ligera de Selenium Hub ejecutando navegadores en Docker (imágenes disponibles en Docker Hub) |
Apache 2.0 |
Aerokube |
|
Luna |
Clúster Selenium empresarial que utiliza Docker y Kubernetes |
Comercial |
Aerokube |
|
Calisto |
Implementación nativa de Kubernetes de código abierto de Selenium Grid |
MIT |
Aerokube |
Comunidad
Debido a su naturaleza colaborativa, el desarrollo de software necesita la organización y la interacción de muchos participantes. En el ámbito del código abierto, podemos medir el éxito de un proyecto por la relevancia de su comunidad. Selenium cuenta con el apoyo de una gran comunidad de participantes muy diversos en todo el mundo. La Tabla 1-7 presenta un resumen de varios recursos de Selenium agrupados en las siguientes categorías: documentación oficial, desarrollo, soporte y eventos.
Categoría | Descripción | Página web |
---|---|---|
Documentación oficial |
Guía del usuario |
|
Blog |
||
Wiki |
||
Ecosistema |
||
Desarrollo |
Código fuente |
|
Cuestiones |
||
Gobernanza |
||
Ayuda |
Grupo de usuarios |
|
Slack |
||
IRC |
||
StackOverflow |
||
Eventos |
Conferencia |
|
Reuniones |
Fundamentos de las pruebas de software
Software probar (o simplemente probar) consiste en la evaluación dinámica de una pieza de software, llamada Sistema Bajo Prueba (SUT ), mediante un conjunto finito de casos de prueba (o simplemente pruebas), dando un veredicto sobre ella. Probar implica la ejecución del SUT utilizando valores de entrada específicos para evaluar el resultado o comportamiento esperado.
A primera vista, distinguimos en dos categorías distintas de pruebas de software: manuales y automatizadas. Por un lado, en las pruebas manuales, una persona (normalmente un ingeniero de software o el usuario final) evalúa el SUT. Por otro lado, en las pruebas automatizadas, utilizamos herramientas de software específicas para desarrollar pruebas y controlar su ejecución contra el SUT. Las pruebas automatizadas permiten la detección temprana de defectos (normalmente llamados bugs) en el SUT, al tiempo que proporcionan un gran número de ventajas adicionales (por ejemplo, ahorro de costes, retroalimentación rápida, cobertura de las pruebas o reutilización, por nombrar algunas). Las pruebas manuales también pueden ser un enfoque valioso en algunos casos, por ejemplo, en las pruebas exploratorias (es decir, los probadores humanos investigan y evalúan libremente el SUT).
Nota
No existe una clasificación universal para las numerosas formas de pruebas presentadas en esta sección. Estos conceptos están sujetos a una evolución y un debate continuos, al igual que la ingeniería de software. Considéralo una propuesta que puede encajar en un gran número de proyectos.
Niveles de las pruebas
En función del tamaño del SUT, podemos definir distintos niveles de pruebas. Estos niveles definen varias categorías en las que los equipos de software dividen sus esfuerzos de prueba. En este libro, yo propongo una disposición apilada para representar los distintos niveles (véase la Figura 1-5). Los niveles inferiores de esta estructura representan las pruebas destinadas a verificar pequeñas piezas de software (llamadas unidades). A medida que ascendemos en la pila, encontramos otros niveles (por ejemplo, integración, sistema, etc.) en los que el SUT integra cada vez más componentes.
El nivel más bajo de esta pila es la prueba unitaria. En este nivel, evaluamos unidades individuales de software. Una unidad es un elemento observable concreto de comportamiento. Por ejemplo, las unidades suelen ser métodos o clases en la programación orientada a objetos y funciones en la programación funcional. Las pruebas unitarias pretenden verificar que cada unidad se comporta como se espera. Las pruebas unitarias automatizadas suelen ejecutarse muy rápido, ya que cada prueba ejecuta una pequeña cantidad de código de forma aislada. Para conseguir este aislamiento, podemos utilizar dobles de prueba, piezas de software que sustituyen a los componentes dependientes de una unidad determinada. Por ejemplo, un tipo popular de doble de prueba en la programación orientada a objetos es el objeto simulado. Un objeto simulado imita a un objeto real utilizando algún comportamiento programado.
El siguiente nivel de en la Figura 1-5 es la prueba de integración. En este nivel, se componen diferentes unidades para crear componentes compuestos. Las pruebas de integración pretenden evaluar la interacción entre las unidades implicadas y sacar a la luz los defectos de sus interfaces.
A continuación, en los niveles de prueba del sistema y de extremo a extremo (E2E), probamos el sistema de software en su conjunto. Necesitamos implementar el SUT y verificar sus características de alto nivel para llevar a cabo estos niveles. La diferencia entre las pruebas del sistema/de extremo a extremo y las de integración es que en las primeras participan todos los componentes del sistema y el usuario final (normalmente suplantado). En otras palabras, las pruebas de sistema y de extremo a extremo evalúan el SUT a través de la Interfaz de Usuario (UI). Esta IU puede ser gráfica (GUI) o no gráfica (por ejemplo, basada en texto u otros tipos).
La Figura 1-6 ilustra la diferencia entre las pruebas del sistema y las pruebas de extremo a extremo. Como puedes ver, por un lado, las pruebas de extremo a extremo abarcan el sistema de software y sus subsistemas dependientes (por ejemplo, la base de datos o los servicios externos). Por otro lado, las pruebas del sistema comprenden sólo el sistema de software, y estas dependencias externas se suelen simular.
Las pruebas de aceptación son el nivel superior de la pila presentada. En este nivel, el usuario final participa en el proceso de prueba. El objetivo de las pruebas de aceptación es decidir si el sistema de software cumple las expectativas del usuario final. Como puedes ver en la Figura 1-6, al igual que las pruebas de extremo a extremo, las pruebas de aceptación validan todo el sistema y sus dependencias. Por tanto, las pruebas de aceptación también utilizan la interfaz de usuario para llevar a cabo la validación del SUT.
Consejo
El propósito principal de Selenium WebDriver en es realizar pruebas de extremo a extremo. Sin embargo, podemos utilizar WebDriver para realizar pruebas del sistema al imitar las llamadas al backend realizadas por el sitio web que se está probando. Además, podemos utilizar Selenium WebDriver junto con una herramienta de Desarrollo Basado en el Comportamiento (BDD) para realizar pruebas de aceptación (consulta el Capítulo 9).
Tipos de pruebas
Según la estrategia de diseño de los casos de prueba, podemos aplicar distintos tipos de pruebas. Los dos principales tipos de pruebas son:
- Pruebas funcionales (también conocidas como pruebas de comportamiento o de caja cerrada)
-
Evalúa la conformidad de un software con el comportamiento esperado (es decir, sus requisitos funcionales).
- Pruebas estructurales (también conocidas como pruebas de caja clara)
-
Determina si la estructura del código del programa es defectuosa. Para ello, los probadores deben conocer la lógica interna de un programa informático.
La diferencia entre estos tipos de pruebas es que las pruebas funcionales se basan en la responsabilidad, mientras que las estructurales se basan en la implementación. Ambos tipos pueden realizarse en cualquier nivel de prueba (unidad, integración, sistema, extremo a extremo o aceptación). Sin embargo, las pruebas estructurales suelen realizarse a nivel unitario o de integración, ya que estos niveles permiten un control más directo del flujo de ejecución del código.
Advertencia
Las pruebasde caja negra y caja blanca son otros nombres para las pruebas funcionales y estructurales, respectivamente. Sin embargo, estas denominaciones no son recomendables, ya que la industria tecnológica está intentando adoptar términos más inclusivos y utilizar una terminología neutra en lugar de un lenguaje potencialmente perjudicial.
Hay diferentes tipos de pruebas funcionales. Por ejemplo:
- Pruebas de interfaz de usuario (conocidas como pruebas GUI cuando la interfaz de usuario es gráfica)
-
Evalúa si los elementos visuales de una aplicación cumplen la funcionalidad esperada. Ten en cuenta que las pruebas de interfaz de usuario son diferentes de las pruebas de sistema y de extremo a extremo, ya que las primeras prueban la interfaz en sí, y las segundas evalúan todo el sistema a través de la interfaz de usuario.
- Prueba negativa
-
Evalúa el SUT en condiciones inesperadas (por ejemplo, excepciones esperadas). Este término es la contrapartida de las pruebas funcionales habituales (a veces llamadas pruebas positivas), en las que evaluamos si el SUT se comporta como se espera (es decir, su camino feliz).
- Pruebas entre navegadores
-
Se trata de específico para aplicaciones web. Su objetivo es verificar la compatibilidad de los sitios web y las aplicaciones en distintos navegadores web (tipos, versiones o sistemas operativos).
Un tercer tipo de prueba miscelánea , la prueba no funcional, incluye estrategias de prueba que evalúan los atributos de calidad de un sistema de software (es decir, sus requisitos no funcionales). Los métodos habituales de pruebas no funcionales incluyen, entre otros:
- Pruebas de rendimiento
-
Evalúa diferentes métricas de los sistemas de software, como el tiempo de respuesta, la estabilidad, la fiabilidad o la escalabilidad. El objetivo de las pruebas de rendimiento no es encontrar fallos, sino los cuellos de botella del sistema. Hay dos subtipos comunes de pruebas de rendimiento:
- Pruebas de seguridad
-
Intenta evaluar las cuestiones de seguridad, como la confidencialidad (protección de la información revelada), la autenticación (garantizar la identidad del usuario) o la autorización (determinar los derechos y privilegios del usuario), entre otras.
- Pruebas de usabilidad
-
Evalúa lo fácil de usar que es una aplicación de software. Esta evaluación también se denomina prueba de experiencia del usuario (UX). Un subtipo de prueba de usabilidad es:
- Pruebas de accesibilidad
-
Evalúa en si un sistema es utilizable por personas con discapacidad.
Consejo
Utilizamos Selenium WebDriver principalmente para implementar pruebas funcionales (es decir, interactuar con la interfaz de usuario de una aplicación web para evaluar el comportamiento de la aplicación). Es poco probable que utilicemos WebDriver para implementar pruebas estructurales. Además, aunque no es su uso principal, podemos utilizar WebDriver para implementar pruebas no funcionales, por ejemplo, para pruebas de carga, seguridad, accesibilidad o localización (evaluación de configuraciones locales específicas) (consulta el Capítulo 9).
Metodologías de ensayo
El ciclo de vida del desarrollo de software es el conjunto de actividades, acciones y tareas necesarias para crear sistemas de software en ingeniería de software . El momento en que los ingenieros de software diseñan e implementan los casos de prueba en el ciclo de vida de desarrollo general depende del proceso de desarrollo específico (como iterativo, en cascada o ágil, por nombrar algunos). Dos de las metodologías de pruebas más relevantes son:
- Desarrollo dirigido por pruebas (TDD)
-
TDD es una metodología de en la que diseñamos e implementamos pruebas antes del diseño y la implementación reales del software. A principios del siglo XXI, el TDD se hizo popular con el auge de las metodologías ágiles de desarrollo de software, como la Programación Extrema (XP). En TDD, un desarrollador escribe primero una prueba automatizada (inicialmente fallida) para una función determinada. A continuación, crea un fragmento de código para superar esa prueba. Por último, el desarrollador refactoriza el código para lograr o mejorar la legibilidad y la mantenibilidad.
- Prueba de Último Desarrollo (TLD)
-
TLD es una metodología de en la que diseñamos e implementamos pruebas después de implementar el SUT. Esta práctica es típica en los procesos tradicionales de desarrollo de software, como el de cascada (secuencial), el incremental (multicascada), el espiral (multicascada orientada al riesgo) o el Proceso Racional Unificado (RUP).
Otra metodología de pruebas relevante es el Desarrollo Orientado al Comportamiento (BDD). BDD es una práctica de pruebas derivada de TDD, y en consecuencia, en BDD diseñamos pruebas en las primeras fases del ciclo de vida de desarrollo del software. Para ello, se producen conversaciones entre el usuario final y el equipo de desarrollo (normalmente con el jefe de proyecto, el gestor o los analistas). Estas conversaciones formalizan un entendimiento común del comportamiento deseado y del sistema de software. Como resultado, en creamos pruebas de aceptación en términos de uno o más escenarios siguiendo una estructura Dado-Cuando-Entonces:
- Dado
-
Contexto inicial al comienzo del escenario
- Cuando
-
Suceso que desencadena el escenario
- A continuación,
-
Resultado esperado
Consejo
TLD es una práctica común utilizada para implementar Selenium WebDriver. En otras palabras, los desarrolladores/testers no implementan una prueba WebDriver hasta que el SUT está disponible. Sin embargo, también son posibles otras metodologías. Por ejemplo, BDD es un enfoque habitual cuando se utiliza WebDriver con Cucumber (véase el Capítulo 9).
Estrechamente relacionado con el ámbito de las metodologías de prueba, encontramos el concepto de Integración Continua (IC) en . La IC es una práctica de desarrollo de software en la que los miembros de un proyecto de software construyen, prueban e integran su trabajo continuamente. Grady Booch acuñó por primera vez el término IC en 1991. Ahora es una estrategia popular para crear software.
Como muestra la Figura 1-7, la IC tiene tres etapas separadas. En primer lugar, utilizamos un repositorio de código fuente, un alojamiento para almacenar y compartir el código fuente de un proyecto de software. En solemos utilizar un sistema de control de versiones (VCS) para gestionar este repositorio. Un VCS es una herramienta que lleva un registro del código fuente, quién hizo cada cambio y cuándo (a veces llamado parche).
Git, inicialmente desarrollado por Linus Torvalds, es el VCS preferido en la actualidad. Otras alternativas son el sistema de versiones concurrentes (CVS) o Subversion (SVN). Además de Git, varias plataformas de alojamiento de código (como GitHub, GitLab o Bitbucket) ofrecen servicios de alojamiento de repositorios colaborativos en la nube para desarrollar, compartir y mantener software.
Los desarrolladores sincronizan una copia del repositorio local (o simplemente, repo) en sus entornos locales. Después, realizan el trabajo de codificación utilizando esa copia local, confirmando los nuevos cambios en el repositorio remoto (normalmente a diario). La idea básica de CI es que cada confirmación desencadena la compilación y prueba del software con los nuevos cambios. El conjunto de pruebas que se ejecuta en para comprobar que un parche no rompe la compilación se denomina prueba de regresión. Un conjunto de pruebas de regresión puede contener pruebas de distintos tipos, como unitarias, de integración, de extremo a extremo, etc.
Cuando el número de pruebas es demasiado grande para las pruebas de regresión, solemos elegir sólo una parte de las pruebas relevantes de todo el conjunto. Existen diferentes estrategias para seleccionar estas pruebas, por ejemplo, pruebas de humo (es decir, pruebas que garantizan la funcionalidad crítica) o pruebas de cordura (es decir, pruebas que evalúan la funcionalidad básica). Por último, podemos ejecutar el conjunto completo como una tarea programada (normalmente cada noche).
Necesitamos utilizar una infraestructura del lado del servidor, llamada servidor de compilación, para implantar una canalización CI. El servidor de compilación suele informar de un problema al desarrollador original cuando fallan las pruebas de regresión. La Tabla 1-8 ofrece un resumen de varios servidores de compilación.
Nombre | Descripción | Licencia | Mantenedor | Página web |
---|---|---|---|---|
Bambú |
Fácil uso con Jira (gestor de incidencias) y Bitbucket |
Comercial |
Atlassian |
|
Acciones de GitHub |
Servidor de compilación integrado en GitHub |
Gratis para repositorios públicos |
Microsoft |
|
GitLab CI/CD |
Servidor de compilación integrado en GitLab |
Gratis para repositorios públicos |
GitLab |
|
Jenkins |
Servidor de automatización de código abierto |
MIT |
Equipo Jenkins |
Consejo
Utilizo un repositorio de GitHub(https://github.com/bonigarcia/selenium-webdriver-java) para publicar y mantener los ejemplos de prueba presentados en este libro. GitHub Actions es el servidor de compilación de este repositorio (consulta el Capítulo 2).
Podemos ampliar un conducto de IC típico de de dos maneras (véase la Figura 1-8):
- Entrega continua (CD)
-
Después de la IC, el servidor de compilación despliega la versión en un entorno de preparación (es decir, una réplica de un entorno de producción con fines de prueba) y ejecuta las pruebas de aceptación automatizadas (si las hay).
- Implementación continua
-
El servidor de compilación despliega la versión de software en el entorno de producción como paso final.
Próximo a CI, ha cobrado fuerza el término DevOps (desarrollo y operaciones). DevOps es una metodología de software que promueve la comunicación y la colaboración entre los distintos equipos de un proyecto de software para desarrollar y entregar software de forma eficiente. Estos equipos incluyen desarrolladores, probadores, QA (control de calidad), operaciones (infraestructura), etc.
Herramientas de automatización de pruebas
Necesitamos utilizar algunas herramientas de para implementar, ejecutar y controlar las pruebas automatizadas con eficacia. Una de las categorías más relevantes para las herramientas de pruebas es el marco de pruebas unitarias. El marco original de la familia de pruebas unitarias (también conocido como xUnit) es SmalltalkUnit (o SUnit). SUnit es un marco de pruebas unitarias para el lenguaje Smalltalk creado por Kent Beck en 1999. Erich Gamma portó SUnit a Java, creando JUnit. Desde entonces, JUnit ha sido muy popular, inspirando otros marcos de pruebas unitarias . La Tabla 1-9 resume los marcos de pruebas unitarias más relevantes en distintos lenguajes.
Nombre | Lengua | Descripción | Licencia | Mantenedor | Página web |
---|---|---|---|---|---|
JUnit |
Java |
Implementación de referencia de la familia xUnit |
EPL |
Equipo JUnit |
|
TestNG |
Java |
Inspirado en JUnit y NUnit, con funciones adicionales |
Apache 2.0 |
Cedric Beust |
|
Moca |
JavaScript |
Marco de pruebas para Node.js y el navegador |
MIT |
Fundación OpenJS |
|
Jest |
JavaScript |
Centrado en la simplicidad con especial atención a las aplicaciones web |
MIT |
Facebiij |
|
Karma |
JavaScript |
Te permite ejecutar pruebas de JavaScript en navegadores web |
MIT |
Equipo Karma |
|
NUnit |
.net |
Marco de pruebas unitarias para todos los lenguajes .Net (C#, Visual Basic y F#) |
MIT |
Fundación .NET |
|
unittest |
Python |
Marco de pruebas unitarias incluido como biblioteca estándar a partir de Python 2.1 |
Licencia PSF |
Fundación del Software Python |
|
minitest |
Ruby |
Completo conjunto de utilidades de pruebas para Ruby |
MIT |
Brigada Rubí de Seattle |
Una importante característica común de la familia xUnit es la estructura de las pruebas, compuesta por cuatro fases (véase la Figura 1-9):
- Configurar
-
El caso de prueba inicializa el SUT para que muestre el comportamiento esperado.
- Ejercicio
-
El caso de prueba interactúa con el SUT. Como resultado, la prueba obtiene un resultado del SUT.
- Verifica
-
El caso de prueba decide si el resultado obtenido del SUT es el esperado. Para ello, la prueba contiene una o varias aserciones. Una aserción (o predicado) es una función de valor booleano que comprueba si una condición esperada es verdadera. La ejecución de las aserciones genera un veredicto de la prueba (normalmente, aprobado o suspenso).
- Desmontaje
Consejo
Podemos utilizar marcos de pruebas unitarias junto con otras bibliotecas o utilidades para implementar cualquier tipo de prueba. Por ejemplo, como se explica en el Capítulo 2, utilizamos JUnit y TestNG para incrustar la llamada a la API Selenium WebDriver, implementando pruebas de extremo a extremo para aplicaciones web.
Las etapas de configuración y desmontaje son opcionales en un caso de prueba unitaria. Aunque no es estrictamente obligatorio, verificar es muy recomendable. Aunque los marcos de pruebas unitarias incluyan capacidades para implementar aserciones, es habitual incorporar bibliotecas de aserciones de terceros. Estas bibliotecas pretenden mejorar la legibilidad del código de prueba proporcionando un rico conjunto de aserciones fluidas. Además, estas bibliotecas ofrecen mensajes de error mejorados para ayudar a los probadores a comprender la causa de un fallo. La Tabla 1-10 contiene un resumen de algunas de las bibliotecas de aserciones más relevantes de para Java.
Nombre | Descripción | Licencia | Mantenedor | Página web |
---|---|---|---|---|
AfirmaJ |
Biblioteca Java de aserciones fluidas |
Apache 2.0 |
Equipo AssertJ |
|
Hamcrest |
Biblioteca Java de comparadores para crear aserciones flexibles |
BSD |
Equipo Hamcrest |
|
Verdad |
Aserciones fluidas para Java y Android |
Apache 2.0 |
Como puedes ver en la Figura 1-9, el SUT suele poder consultar a otro componente, denominado Componente Dependiente (DOC). En algunos casos (por ejemplo, a nivel de pruebas unitarias o del sistema), es posible que queramos aislar el SUT del o de los DOC. Podemos encontrar en una gran variedad de bibliotecas simuladas para lograr este aislamiento.
La Tabla 1-11 muestra un resumen exhaustivo de algunas de estas bibliotecas simuladas para Java.
Nombre | Nivel | Descripción | Licencia | Mantenedor | Página web |
---|---|---|---|---|---|
EasyMock |
Unidad |
Permite simular objetos para pruebas unitarias utilizando anotaciones Java |
Apache |
Equipo EasyMock |
|
Mockito |
Unidad |
Biblioteca Java Mocking para la creación y verificación de simulacros |
MIT |
Equipo Mockito |
|
JMockit |
Integración |
Permite realizar pruebas de integración fuera del contenedor para aplicaciones basadas en Java EE y Spring |
Abre |
Equipo JMockit |
|
Servidor simulado |
Sistema |
Biblioteca de simulación para cualquier sistema integrado mediante HTTP o HTTPS con clientes Java |
Apache 2.0 |
James Bloom |
|
WireMock |
Sistema |
Herramienta para simular servicios basados en HTTP |
Apache 2.0 |
Tom Akehurst |
La última categoría de herramientas de pruebas que analizamos en esta sección es BDD, un proceso de desarrollo que crea pruebas de aceptación. Hay muchas alternativas para aplicar este enfoque. Por ejemplo, la Tabla 1-12 muestra un resumen condensado de marcos BDD relevantes.
Nombre | Lengua | Descripción | Licencia | Mantenedor | Página web |
---|---|---|---|---|---|
Pepino |
Ruby, Java, JavaScript, Python |
Marco de pruebas para crear pruebas de aceptación automatizadas siguiendo un enfoque BDD |
MIT |
Software SmartBear |
|
FitNesse |
Java |
Wiki colaborativo independiente y marco de pruebas de aceptación |
CPL |
Equipo FitNesse |
|
JBehave |
Java, Groovy, Kotlin, Ruby, Scala |
Marco BDD para todos los lenguajes JVM |
Cláusula BSD-3 |
Equipo JBehave |
|
Jazmín |
JavaScript |
Marco BDD para JavaScript |
MIT |
Equipo Jasmine |
|
Carpincho |
Ruby |
Marco de pruebas de aceptación basado en web que simula escenarios para historias de usuario |
MIT |
Thomas Walpole |
|
Serenidad TDC |
Java, Javascript |
Biblioteca de pruebas de aceptación automatizadas |
Apache 2.0 |
Equipo Serenity BDD |
Resumen y perspectivas
Selenium ha recorrido un largo camino desde su creación en 2004. Muchos profesionales de lo consideran la solución estándar de facto para desarrollar pruebas de extremo a extremo para aplicaciones web, y lo utilizan miles de proyectos en todo el mundo. En este capítulo, has visto los fundamentos del proyecto Selenium (formado por WebDriver, Grid e IDE). Además, Selenium cuenta con un rico ecosistema y una comunidad activa. WebDriver es el corazón del proyecto Selenium, y es una biblioteca que proporciona una API para controlar diferentes navegadores web (por ejemplo, Chrome, Firefox, Edge, etc.) mediante programación. La Tabla 1-13 contiene un amplio resumen de los usos primarios y secundarios de Selenium WebDriver en .
Primaria | Secundaria (otros usos) | |
---|---|---|
Propósito |
Pruebas automatizadas |
Web scraping, tareas de administración basadas en la web |
Nivel de prueba |
Pruebas de extremo a extremo |
Pruebas del sistema (simulando llamadas al backend) |
Tipo de prueba |
Pruebas funcionales (garantizar el comportamiento esperado) |
Pruebas no funcionales (por ejemplo, carga, seguridad, accesibilidad o localización) |
Metodología de ensayo |
TLD (realización de pruebas cuando el SUT está disponible) |
BDD (definición de escenarios de usuario en las primeras fases de desarrollo) |
En el siguiente capítulo, descubrirás cómo configurar un proyecto Java utilizando Maven o Gradle como herramientas de compilación. Este proyecto contendrá pruebas de extremo a extremo para aplicaciones web utilizando JUnit y TestNG como marcos de pruebas unitarias y llamadas a la API Selenium WebDriver. Además, aprenderás a controlar distintos navegadores web (por ejemplo, Chrome, Firefox o Edge) con un caso de prueba básico (la versión de Selenium WebDriver del clásico hola mundo).
Get Selenium WebDriver práctico con Java now with the O’Reilly learning platform.
O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.