Selenium: Localización de elementos

Aprende a localizar elementos en el DOM con Selenium para pruebas de software de interfaz de usuario UI en aplicaciones web

Aprende Selenium GRATIS y certifícate

La localización de elementos web es una habilidad fundamental en Selenium que determina en gran medida el éxito de tus pruebas automatizadas. Para interactuar con un elemento en una página web (hacer clic en un botón, ingresar texto en un campo, verificar texto visible), primero debes identificarlo de manera única y precisa.

Selenium WebDriver proporciona múltiples estrategias de localización que permiten encontrar elementos en función de sus atributos, posición en el DOM, contenido de texto y relaciones con otros elementos. La elección del método de localización adecuado es crucial para crear pruebas robustas y mantenibles.

El primer paso para localizar elementos es comprender la estructura del DOM (Document Object Model), que representa la página web como una estructura jerárquica de nodos. Cada elemento HTML en la página es un nodo con atributos, propiedades y contenido que pueden utilizarse para su identificación.

La interfaz principal para localizar elementos en Selenium es la clase By, que encapsula las diferentes estrategias de localización disponibles:

import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeDriver;

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

public class EstrategiasLocalizacionTests {
    
    private WebDriver driver;
    
    @BeforeEach
    public void configurar() {
        driver = new ChromeDriver();
        driver.get("https://www.ejemplo.com/formulario");
    }
    
    @Test
    public void demostrarEstrategiasBasicas() {
        // Localizar por ID - la estrategia más eficiente
        WebElement campoUsuario = driver.findElement(By.id("username"));
        
        // Localizar por nombre - útil para campos de formulario
        WebElement campoCorreo = driver.findElement(By.name("email"));
        
        // Localizar por class name - útil para elementos con clases CSS
        WebElement botonCancelar = driver.findElement(By.className("btn-cancel"));
        
        // Verificar que los elementos fueron localizados correctamente
        assertTrue(campoUsuario.isDisplayed());
        assertTrue(campoCorreo.isDisplayed());
        assertTrue(botonCancelar.isDisplayed());
    }
    
    @AfterEach
    public void limpiar() {
        if (driver != null) {
            driver.quit();
        }
    }
}

El localizador más eficiente es generalmente By.id(), ya que los IDs deberían ser únicos en un documento HTML bien estructurado. Sin embargo, no todos los elementos tienen IDs, y en aplicaciones generadas dinámicamente, los IDs podrían cambiar entre sesiones.

Para enlaces y elementos de texto, Selenium ofrece localizadores específicos como linkText y partialLinkText, que son particularmente útiles para elementos <a>:

import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeDriver;

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

public class LocalizacionEnlacesTests {
    
    private WebDriver driver;
    
    @BeforeEach
    public void configurar() {
        driver = new ChromeDriver();
        driver.get("https://www.ejemplo.com/navegacion");
    }
    
    @Test
    public void localizarEnlaces() {
        // Localizar por texto exacto del enlace
        WebElement enlaceContacto = driver.findElement(By.linkText("Contacto"));
        enlaceContacto.click();
        
        // Verificar navegación a la página de contacto
        assertEquals("Página de Contacto", driver.getTitle());
        
        // Volver a la página de navegación
        driver.navigate().back();
        
        // Localizar por texto parcial del enlace
        WebElement enlacePolitica = driver.findElement(By.partialLinkText("Política de"));
        enlacePolitica.click();
        
        // Verificar navegación a la página de política
        assertEquals("Política de Privacidad", driver.getTitle());
    }
    
    @AfterEach
    public void limpiar() {
        if (driver != null) {
            driver.quit();
        }
    }
}

Los selectores CSS representan una estrategia de localización flexible que utiliza la misma sintaxis que las hojas de estilo CSS. Son más concisos que XPath y generalmente más rápidos:

import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeDriver;

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

public class SelectoresCSSTests {
    
    private WebDriver driver;
    
    @BeforeEach
    public void configurar() {
        driver = new ChromeDriver();
        driver.get("https://www.ejemplo.com/productos");
    }
    
    @Test
    public void demostrarSelectoresCSS() {
        // Selector básico por ID
        WebElement producto = driver.findElement(By.cssSelector("#producto-destacado"));
        
        // Selector por clase
        WebElement precio = driver.findElement(By.cssSelector(".precio-oferta"));
        
        // Combinación de selectores
        WebElement botonComprar = driver.findElement(By.cssSelector("div.producto button.comprar"));
        
        // Selector de atributos
        WebElement enlaceExterno = driver.findElement(By.cssSelector("a[target='_blank']"));
        
        // Selectores de combinación
        WebElement primerLiHijo = driver.findElement(By.cssSelector("ul > li:first-child"));
        WebElement tercerElemento = driver.findElement(By.cssSelector("li:nth-child(3)"));
        
        // Verificar selectores
        assertTrue(producto.isDisplayed());
        assertTrue(precio.getText().contains("€"));
        assertEquals("Comprar ahora", botonComprar.getText());
        assertTrue(primerLiHijo.isDisplayed());
    }
    
    @AfterEach
    public void limpiar() {
        if (driver != null) {
            driver.quit();
        }
    }
}

XPath es otra estrategia de localización potente que permite navegar por la estructura XML/HTML del documento. Es especialmente útil para elementos difíciles de localizar con otros métodos:

import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeDriver;

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

public class XPathTests {
    
    private WebDriver driver;
    
    @BeforeEach
    public void configurar() {
        driver = new ChromeDriver();
        driver.get("https://www.ejemplo.com/tablas");
    }
    
    @Test
    public void demostrarXPath() {
        // XPath absoluto (evitar en pruebas reales por fragilidad)
        WebElement titulo = driver.findElement(By.xpath("/html/body/div/h1"));
        
        // XPath relativo
        WebElement tabla = driver.findElement(By.xpath("//table[@id='datos-usuarios']"));
        
        // Localizar por contenido de texto
        WebElement celdaJuan = driver.findElement(By.xpath("//td[text()='Juan García']"));
        
        // Localizar por atributo parcial
        WebElement enlace = driver.findElement(By.xpath("//a[contains(@href, 'perfil')]"));
        
        // Localizar por relaciones de parentesco
        WebElement padre = driver.findElement(By.xpath("//td[text()='Activo']/parent::tr"));
        WebElement hermano = driver.findElement(By.xpath("//th[text()='Nombre']/following-sibling::th"));
        
        // Localizar con funciones y operadores
        WebElement elementoOculto = driver.findElement(By.xpath("//div[not(@class='visible')]"));
        WebElement elementoConClasesMultiples = driver.findElement(
                By.xpath("//div[contains(@class, 'info') and contains(@class, 'destacado')]"));
        
        // Verificaciones
        assertEquals("Tabla de Usuarios", titulo.getText());
        assertTrue(tabla.isDisplayed());
        assertEquals("Juan García", celdaJuan.getText());
        assertEquals("Email", hermano.getText());
    }
    
    @AfterEach
    public void limpiar() {
        if (driver != null) {
            driver.quit();
        }
    }
}

Una diferencia crucial en WebDriver es la distinción entre los métodos findElement() y findElements(). El primero devuelve el primer elemento que coincide con el localizador, mientras que el segundo devuelve una lista de todos los elementos coincidentes:

import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeDriver;

import java.util.List;

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

public class FindElementVsFindElementsTests {
    
    private WebDriver driver;
    
    @BeforeEach
    public void configurar() {
        driver = new ChromeDriver();
        driver.get("https://www.ejemplo.com/lista");
    }
    
    @Test
    public void demostrarDiferencias() {
        // findElement devuelve el primer elemento que coincide
        WebElement primerElemento = driver.findElement(By.cssSelector(".item"));
        
        // findElem
Empezar curso de Selenium

Lecciones de este módulo de Selenium

Lecciones de programación del módulo Localización de elementos del curso de Selenium.