Lección 3 de 6 · 2 min
Page Object Model con pytest
La estructura del framework
tests/
conftest.py # fixtures compartidas
pages/
base_page.py
booking_page.py
confirmation_page.py
test_reservas.py
pytest.ini
La fixture que reemplaza al setup/teardown
# conftest.py
import pytest
from selenium import webdriver
@pytest.fixture
def driver():
options = webdriver.ChromeOptions()
options.add_argument("--headless=new")
driver = webdriver.Chrome(options=options)
driver.set_window_size(1440, 900)
yield driver
driver.quit() # corre siempre, incluso si el test falla
Adiós al finally: driver.quit() de la lección 1: la fixture garantiza la limpieza y cada test recibe un navegador fresco.
Page objects que encapsulan comportamiento
La regla: el test habla en lenguaje de negocio, el page object traduce a Selenium.
# pages/booking_page.py
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
class BookingPage:
URL = "https://ejemplo.cl/reservas"
SERVICIO = (By.CSS_SELECTOR, "[data-test='servicio']")
HORA = (By.CSS_SELECTOR, "[data-test='hora']")
CONFIRMAR = (By.CSS_SELECTOR, "[data-test='confirmar']")
def __init__(self, driver):
self.driver = driver
self.wait = WebDriverWait(driver, 10)
def open(self):
self.driver.get(self.URL)
return self
def reservar(self, servicio: str, hora: str):
self.wait.until(EC.element_to_be_clickable(self.SERVICIO)).send_keys(servicio)
self.wait.until(EC.element_to_be_clickable(self.HORA)).send_keys(hora)
self.wait.until(EC.element_to_be_clickable(self.CONFIRMAR)).click()
from pages.confirmation_page import ConfirmationPage
return ConfirmationPage(self.driver)
# test_reservas.py
from pages.booking_page import BookingPage
def test_reserva_exitosa(driver):
confirmacion = BookingPage(driver).open().reservar("Corte", "15:30")
assert "reservada" in confirmacion.mensaje().lower()
Las 3 reglas del POM sano
- Ningún
By.en los tests. Si un selector cambia, tocas un archivo, no cuarenta. - Los métodos devuelven page objects — la navegación queda tipada y encadenable.
- Cero asserts en los page objects. El page object informa, el test juzga. (Excepción aceptada: asserts de "estoy en la página correcta" al construir.)
El anti-patrón: el God Page Object
Un BasePage con 60 métodos utilitarios es tan mantenible como el DOM crudo. Si un page object supera ~10 métodos públicos, probablemente esconde dos páginas (o un componente reutilizable, como un date-picker, que merece su propia clase).
Ejercicio
Modela como page objects un flujo de dos páginas de cualquier sitio público (búsqueda → resultados). El test final debe leerse en una línea de negocio, sin ningún selector visible.