Hay un momento en la automatización de pruebas en el que te das cuenta de que tu código se está convirtiendo en un caos. Tests que se repiten, locators duplicados por todas partes, y cuando cambia algo en la interfaz tienes que tocar diez archivos distintos. Ahí es exactamente donde entra el Page Object Model.
Es el patrón de diseño más usado en automatización de pruebas y una vez que lo aplicas no hay vuelta atrás.
Qué es el Page Object Model
El Page Object Model, conocido como POM, es un patrón de diseño que consiste en crear una clase por cada página o componente de tu aplicación. Esa clase contiene todos los locators y las acciones que se pueden realizar en esa página.
Los tests no interactúan directamente con el navegador — interactúan con estas clases. Así, si algo cambia en la interfaz solo tienes que actualizar la clase correspondiente, no todos los tests que la usan.
Por qué usarlo
Sin POM, un test típico puede verse así:
python
def test_login(page):
page.goto("https://miweb.com/login")
page.fill("#email", "usuario@test.com")
page.fill("#password", "12345678")
page.click("#btn-login")
assert page.url == "https://miweb.com/dashboard"
Si tienes 20 tests que hacen login, ese código se repite 20 veces. Y si el id del campo de email cambia de #email a #input-email, tienes que cambiar los 20 tests.
Con POM:
python
def test_login(page):
login_page = LoginPage(page)
login_page.goto()
login_page.login("usuario@test.com", "12345678")
assert page.url == "https://miweb.com/dashboard"
```
El cambio del locator solo afecta a la clase `LoginPage`. Los tests no cambian.
---
### Cómo implementarlo con Playwright y Python
La estructura de carpetas recomendada es esta:
```
proyecto/
├── pages/
│ ├── login_page.py
│ └── dashboard_page.py
├── tests/
│ └── test_login.py
└── requirements.txt
Primero creas la clase de la página:
python
# pages/login_page.py
class LoginPage:
def __init__(self, page):
self.page = page
self.email_input = "#email"
self.password_input = "#password"
self.login_button = "#btn-login"
def goto(self):
self.page.goto("https://miweb.com/login")
def login(self, email, password):
self.page.fill(self.email_input, email)
self.page.fill(self.password_input, password)
self.page.click(self.login_button)
Luego usas la clase en tus tests:
python
# tests/test_login.py
from pages.login_page import LoginPage
def test_login_correcto(page):
login_page = LoginPage(page)
login_page.goto()
login_page.login("usuario@test.com", "12345678")
assert "dashboard" in page.url
def test_login_password_incorrecta(page):
login_page = LoginPage(page)
login_page.goto()
login_page.login("usuario@test.com", "wrongpassword")
assert "login" in page.url
Buenas prácticas al usar POM
Una clase por página o componente. No metas toda la aplicación en una sola clase.
Los locators siempre en la clase, nunca en los tests. Si el locator cambia, solo tocas un sitio.
Los métodos de la clase deben representar acciones del usuario, no pasos técnicos. En lugar de click_login_button(), mejor login(email, password).
No pongas assertions dentro de las clases. Las assertions van en los tests, no en las páginas.
POM en proyectos reales
En mis proyectos de GitHub tienes ejemplos reales de POM con Playwright y Python. Puedes ver cómo está estructurado el repositorio qa-suite-saucedemo, donde tengo 20 tests E2E organizados con este patrón y CI/CD con GitHub Actions.
Si necesitas implementar automatización con POM en tu proyecto, puedes ver mis servicios en fatimaqa.com.
