Que Es Selenium WebDriver?
Selenium WebDriver es la herramienta de automatizacion de navegadores mas establecida, utilizada por millones de testers. Proporciona una interfaz de programacion para controlar navegadores web a traves del protocolo W3C WebDriver.
Arquitectura de Selenium
Codigo de Test (Java/Python/JS/C#)
↓
API WebDriver
↓
Driver del Navegador (ChromeDriver, GeckoDriver)
↓
Navegador (Chrome, Firefox, Safari, Edge)
Tu codigo llama a la API WebDriver, que envia comandos al driver especifico del navegador, que controla el navegador real.
Configuracion de Selenium
JavaScript (WebdriverIO)
npm init -y
npm install webdriverio @wdio/cli @wdio/mocha-framework
npx wdio config
Python
pip install selenium pytest
Escribiendo tu Primer Test
JavaScript (WebdriverIO)
describe('Pagina de Login', () => {
it('deberia hacer login con credenciales validas', async () => {
await browser.url('/login');
await $('#email').setValue('admin@test.com');
await $('#password').setValue('secret123');
await $('button[type="submit"]').click();
await expect(browser).toHaveUrl('/dashboard');
await expect($('.welcome')).toHaveText('Welcome, Admin');
});
});
Python
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
def test_valid_login():
driver = webdriver.Chrome()
driver.get("https://app.example.com/login")
driver.find_element(By.ID, "email").send_keys("admin@test.com")
driver.find_element(By.ID, "password").send_keys("secret123")
driver.find_element(By.CSS_SELECTOR, "button[type='submit']").click()
wait = WebDriverWait(driver, 10)
wait.until(EC.url_contains("/dashboard"))
welcome = driver.find_element(By.CLASS_NAME, "welcome").text
assert welcome == "Welcome, Admin"
driver.quit()
Estrategias de Localizacion
| Estrategia | Ejemplo | Confiabilidad |
|---|---|---|
By.id | By.id("email") | Alta (si es unico) |
By.css | By.css("[data-testid='email']") | Alta |
By.xpath | By.xpath("//input[@name='email']") | Media |
By.name | By.name("email") | Media |
By.className | By.className("input-email") | Baja |
Mejores Practicas de Localizadores
- Preferir atributos data-testid:
[data-testid="login-submit"] - Usar selectores CSS sobre XPath cuando sea posible — son mas rapidos
- Evitar XPath absoluto:
/html/body/div[3]/form/input[2]se rompe facilmente - Evitar clases de estilo:
.btn-primarypuede cambiar en redisenos - Usar XPath relativo cuando sea necesario:
//button[contains(text(), 'Submit')]
Waits
Wait Implicito
driver.implicitly_wait(10)
Establece un timeout global para todas las busquedas de elementos. Simple pero puede enmascarar problemas de timing.
Wait Explicito (Recomendado)
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
wait = WebDriverWait(driver, 10)
# Esperar a que el elemento sea visible
element = wait.until(EC.visibility_of_element_located((By.ID, "dashboard")))
# Esperar a que sea clickeable
wait.until(EC.element_to_be_clickable((By.ID, "submit")))
# Esperar a que aparezca texto
wait.until(EC.text_to_be_present_in_element((By.CLASS_NAME, "status"), "Complete"))
# Esperar cambio de URL
wait.until(EC.url_contains("/dashboard"))
Interacciones Avanzadas
API de Actions
from selenium.webdriver import ActionChains
actions = ActionChains(driver)
# Hover sobre elemento
actions.move_to_element(menu_item).perform()
# Drag and drop
actions.drag_and_drop(source, target).perform()
# Click derecho
actions.context_click(element).perform()
# Doble click
actions.double_click(element).perform()
Manejo de Dropdowns
from selenium.webdriver.support.ui import Select
dropdown = Select(driver.find_element(By.ID, "country"))
dropdown.select_by_visible_text("Mexico")
dropdown.select_by_value("MX")
dropdown.select_by_index(5)
Manejo de Alerts
alert = driver.switch_to.alert
alert_text = alert.text
alert.accept() # Click OK
alert.dismiss() # Click Cancel
alert.send_keys("texto de entrada")
Manejo de Frames y Ventanas
# Cambiar a iframe
driver.switch_to.frame("frame-name")
driver.switch_to.default_content() # Volver a pagina principal
# Manejar nueva ventana/tab
original_window = driver.current_window_handle
# ... accion que abre nueva ventana
for handle in driver.window_handles:
if handle != original_window:
driver.switch_to.window(handle)
break
Screenshots
driver.save_screenshot("screenshots/test-failure.png")
Ejecucion de JavaScript
driver.execute_script("window.scrollTo(0, document.body.scrollHeight)")
driver.execute_script("arguments[0].click()", hidden_button)
title = driver.execute_script("return document.title")
Mejores Practicas de Selenium
- Siempre usa waits explicitos — nunca Thread.sleep()
- Cierra el driver en teardown — prevenir procesos zombie del navegador
- Usa Page Object Model — separar logica de test de detalles de pagina
- Prefiere selectores CSS — mas rapidos y legibles que XPath
- Ejecuta en modo headless para CI —
options.add_argument("--headless") - Establece timeouts razonables — 10-30 segundos para waits explicitos
- Maneja excepciones de stale element — relocaliza elementos cuando el DOM cambia
Ejercicio: Construye un Suite de Tests con Selenium
Crea un suite de tests Selenium:
- Configura un proyecto con Selenium + tu lenguaje preferido
- Escribe una clase BasePage con metodos comunes
- Crea page objects para Login, Dashboard y Settings
- Escribe 5 test cases cubriendo login, navegacion, envio de formulario, seleccion de dropdown y logout
- Agrega waits explicitos para todos los elementos dinamicos
- Ejecuta tests en modo con y sin interfaz grafica
Puntos Clave
- Selenium WebDriver controla navegadores via protocolo W3C WebDriver
- Usa waits explicitos (WebDriverWait) en vez de Thread.sleep()
- Selectores CSS y data-testid son las mejores estrategias de localizacion
- La API Actions maneja interacciones complejas (hover, drag, teclado)
- Siempre usa Page Object Model para codigo mantenible
- Selenium soporta Java, Python, JavaScript, C#, Ruby y Kotlin