Lección 3 de 6 · 2 min
Page Object Model con pytest
Al terminar sabrás
11 min- Estructurar un framework con conftest, pages/ y tests separados
- Reemplazar setup/teardown por una fixture de driver con limpieza garantizada
- Escribir page objects que encapsulan comportamiento de negocio, no DOM
Construyes: Un flujo de dos páginas modelado con POM, con tests que se leen en lenguaje de negocio.
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).
Comprueba lo aprendido en el quiz y modela tu flujo en el reto.
Compruébalo
0/3Responde sin mirar atrás. Verás la explicación al instante.
1. ¿Cuál es la regla número uno de un POM sano?
2. ¿Cuántos asserts debería tener un page object?
3. Tu BasePage tiene 60 métodos utilitarios. ¿Qué indica eso?
Reto: modela un flujo con POM
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.