Calidad sin Humo
Guías / Recurso técnico

De QA manual a automatización — Parte 2: arquitectura y pipeline

2026.04.01
15 min de lectura
intermedio
De QA manual a automatización — Parte 2: arquitectura y pipeline

Si leíste la Parte 1 de esta guía, ya diste el primer paso. Tienes tests. Corren. Tu equipo lo sabe.

Pero ahora tienes 20, 30, 50 tests… y empezaste a notar algo:

  • El código se repite en todos lados
  • Cambiar un selector rompe 15 tests a la vez
  • No sabes cómo integrar tus tests al pipeline del equipo
  • Sientes que escribes tests, pero no diseñas una estrategia

Si te identificas con esto, estás exactamente donde necesitas estar para dar el siguiente salto.

Escribir tests te hace QA que automatiza. Organizar esos tests para que escalen te hace QA que piensa en arquitectura.

Arquitectura (POM) CI/CD (pipeline) Estrategia (qué automatizar)

1. Arquitectura: Page Object Model (y por qué tu código actual no escala)

Cuando tienes 5 tests, poner todo en un solo archivo funciona. Cuando tienes 50, es un desastre.

El problema se ve así:

El código que no escala
// test-1.spec.ts
await page.getByLabel("Email").fill("user@test.com");
await page.getByLabel("Contraseña").fill("Pass123");
await page.getByRole("button", { name: "Iniciar sesión" }).click();
// test-2.spec.ts — exactamente lo mismo
await page.getByLabel("Email").fill("user@test.com");
await page.getByLabel("Contraseña").fill("Pass123");
await page.getByRole("button", { name: "Iniciar sesión" }).click();
// test-3.spec.ts — y otra vez
await page.getByLabel("Email").fill("user@test.com");
await page.getByLabel("Contraseña").fill("Pass123");
await page.getByRole("button", { name: "Iniciar sesión" }).click();

El día que el equipo de frontend cambie “Iniciar sesión” por “Entrar”, tienes que modificar 30 archivos. Eso no es automatización. Es mantenimiento manual del código de automatización. Irónico, ¿no?

La solución: Page Object Model

POM no es un patrón complicado. Es sentido común organizado: agrupa los selectores y acciones de cada página en una clase. Así, si algo cambia en la UI, lo cambias en un solo lugar.

pages/login.page.ts
import type { Page, Locator } from "@playwright/test";
export class LoginPage {
private readonly emailInput: Locator;
private readonly passwordInput: Locator;
private readonly submitButton: Locator;
constructor(private readonly page: Page) {
this.emailInput = page.getByLabel("Email");
this.passwordInput = page.getByLabel("Contraseña");
this.submitButton = page.getByRole("button", { name: "Iniciar sesión" });
}
async goto() {
await this.page.goto("/login");
}
async login(email: string, password: string) {
await this.emailInput.fill(email);
await this.passwordInput.fill(password);
await this.submitButton.click();
}
}
tests/login.spec.ts — limpio, legible, mantenible
import { test, expect } from "@playwright/test";
import { LoginPage } from "../pages/login.page";
test("login exitoso redirige al dashboard", async ({ page }) => {
const loginPage = new LoginPage(page);
await loginPage.goto();
await loginPage.login("admin@empresa.com", "Password123");
await expect(page.getByRole("heading", { name: "Dashboard" })).toBeVisible();
});
test("login con credenciales inválidas muestra error", async ({ page }) => {
const loginPage = new LoginPage(page);
await loginPage.goto();
await loginPage.login("admin@empresa.com", "contraseña-incorrecta");
await expect(page.getByText("Credenciales inválidas")).toBeVisible();
});
Sin POM: cambio en la UI = editar 30 archivos
Con POM: cambio en la UI = editar 1 archivo

La estructura de carpetas que recomiendo

tests/
├── pages/ # Page Objects
│ ├── login.page.ts
│ ├── dashboard.page.ts
│ └── users.page.ts
├── fixtures/ # Fixtures personalizados
│ └── test-fixtures.ts
├── login.spec.ts # Tests por feature
├── dashboard.spec.ts
└── users.spec.ts
La regla de POM

Las assertions (los expect) van en los tests, no en los Page Objects. Los Page Objects son acciones y selectores. Los tests son las verificaciones. Si mezclas ambos, pierdes claridad sobre qué está validando cada test.

El siguiente nivel: fixtures personalizados

Cuando te canses de escribir const loginPage = new LoginPage(page) en cada test, Playwright te permite crear fixtures — objetos que se crean automáticamente antes de cada test y se destruyen después.

fixtures/test-fixtures.ts
import { test as base } from "@playwright/test";
import { LoginPage } from "../pages/login.page";
import { DashboardPage } from "../pages/dashboard.page";
type MyFixtures = {
loginPage: LoginPage;
dashboardPage: DashboardPage;
};
export const test = base.extend<MyFixtures>({
loginPage: async ({ page }, use) => {
const loginPage = new LoginPage(page);
await use(loginPage);
},
dashboardPage: async ({ page }, use) => {
const dashboardPage = new DashboardPage(page);
await use(dashboardPage);
},
});
export { expect } from "@playwright/test";
tests/login.spec.ts — con fixtures
import { test, expect } from "../fixtures/test-fixtures";
test("login exitoso redirige al dashboard", async ({ loginPage, page }) => {
await loginPage.goto();
await loginPage.login("admin@empresa.com", "Password123");
await expect(page.getByRole("heading", { name: "Dashboard" })).toBeVisible();
});

Cada test recibe su propia instancia del fixture. Aislamiento total. Sin estado compartido. Sin colisiones.


2. CI/CD: tus tests en el pipeline (donde realmente importan)

Un test que solo corre en tu máquina es un test a medias. El verdadero valor aparece cuando tus tests corren automáticamente cada vez que alguien hace push o abre un pull request.

Si nunca configuraste CI/CD, esto te va a parecer intimidante. Pero te prometo que es más simple de lo que crees.

GitHub Actions: tu primer pipeline

Crea este archivo en tu repositorio y tus tests correrán automáticamente en cada push:

.github/workflows/playwright.yml
name: Playwright Tests
on:
push:
branches: [main, develop]
pull_request:
branches: [main]
jobs:
test:
timeout-minutes: 60
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5
- uses: actions/setup-node@v6
with:
node-version: lts/*
- name: Install dependencies
run: npm ci
- name: Install Playwright Browsers
run: npx playwright install --with-deps
- name: Run Playwright tests
run: npx playwright test
- uses: actions/upload-artifact@v5
if: ${{ !cancelled() }}
with:
name: playwright-report
path: playwright-report/
retention-days: 30

Eso es todo. En serio. Copia este archivo, haz push, y tus tests corren en la nube.

¿Qué hace cada línea?
LíneaQué hace
on: push/pull_requestCuándo se ejecuta el pipeline (en cada push a main/develop, en cada PR)
runs-on: ubuntu-latestUsa un servidor Linux gratuito de GitHub
actions/checkoutDescarga tu código del repositorio
actions/setup-nodeInstala Node.js
npm ciInstala dependencias de forma determinística (mejor que npm install en CI)
playwright install --with-depsDescarga los navegadores + dependencias del sistema operativo
npx playwright testCorre todos tus tests
upload-artifactGuarda el reporte HTML para que puedas descargarlo después
if: !cancelled()Sube el reporte incluso si los tests fallan (clave para debugging)

Qué cambia cuando tus tests corren en CI

Automático Cada push dispara los tests
Visible Todo el equipo ve los resultados
Bloqueante No se mergea si los tests fallan
Confiable Misma máquina, mismo entorno

De repente, tus tests no son “algo que tú corres”. Son parte del proceso de desarrollo. El developer no puede mergear su PR si tus tests fallan. Eso cambia la conversación completamente: ya no es QA peleando por calidad — es la calidad integrada en el flujo.

La IA te ayuda con CI/CD

Si el pipeline falla y no entiendes el log, pégale el error a la IA. Los errores de CI son repetitivos y bien documentados — es uno de los casos donde la IA brilla. También puedes pedirle que te genere el archivo YAML para tu setup específico.


3. Estrategia: qué automatizar y qué dejar manual

Esta es la pregunta que separa a un QA que escribe tests de un QA Automation Engineer: no automatices todo. Automatiza lo correcto.

La pirámide que sí funciona

No la pirámide teórica de los libros. La pirámide práctica de lo que realmente necesitas:

NivelQué automatizarCuántos testsVelocidad
Smoke testsLos 5-10 flujos críticos que si fallan, el negocio se para5-10Deben correr en menos de 5 min
RegressionFlujos que ya tuvieron bugs en producción20-50Corren en cada PR
Happy pathsFlujos principales completos10-30Corren en cada merge a main

Lo que NO debes automatizar

Flujos que cambian cada sprint — vas a gastar más tiempo manteniendo el test que lo que ahorras
UX y usabilidad — ningún test automatizado detecta que un botón 'se siente raro'
Exploración — los mejores bugs se encuentran haciendo cosas que no estaban en el plan
Flujos con UI inestable — si el frontend cambia cada semana, automatizar es mantener

La pregunta mágica

Antes de automatizar cualquier test, pregúntate:

¿Cuántas veces voy a ejecutar este test manualmente en los próximos 6 meses? Si la respuesta es menos de 10, probablemente no vale la pena automatizarlo.

Cómo priorizo yo

Mi proceso real para decidir qué automatizar primero:

  1. Reviso los bugs de los últimos 3 meses — si un flujo tuvo bugs en producción, se automatiza
  2. Identifico los tests que más duelen hacer a mano — los que toman más de 15 minutos manuales
  3. Pregunto al equipo — “¿qué flujo les da más miedo tocar?” Ese es el candidato número uno
  4. Descarto lo inestable — si la UI cambia cada sprint, lo dejo para después

El resultado no es “automatizar todo”. Es una lista priorizada de flujos donde la automatización ahorra tiempo real y reduce riesgo real.

Si quieres ir más profundo en métricas para medir si tu automatización realmente aporta, cuidado con la métrica más mentirosa en QA — el coverage no te dice lo que crees.


La hoja de ruta: meses 3-9

MesObjetivoHabilidad clave
3-4Refactoriza tu suite a Page Object ModelPOM, organización de código
5Crea fixtures personalizados para setup/teardowntest.extend, reutilización
6Implementa data-driven testing (mismos tests, diferentes datos)Parametrización
7Configura CI/CD con GitHub ActionsYAML, pipelines, artifacts
8Define qué automatizar y qué dejar manualEstrategia, pirámide de tests
9Documenta tu framework para que otro QA pueda usarloREADME, convenciones
No es lineal

Este plan es una guía, no una obligación. Algunos meses avanzarás rápido, otros te trabarás. Lo importante es no dejar de avanzar. Y recuerda: la IA te desbloquea cuando te trabas — úsala como tu par de programación constante.


¿Y después?

Ya tienes arquitectura. Ya tienes pipeline. Ya tienes estrategia. Pero un QA Automation Engineer completo necesita dominar más: testing de APIs, visual regression, hybrid testing — y saber cómo posicionarse profesionalmente.

Eso es exactamente lo que cubro en la Parte 3: el salto a QA Automation Engineer.

Sigue con la Parte 3

APIs, visual regression, hybrid testing — y cómo posicionarte como QA Automation Engineer con CV, LinkedIn y entrevistas. Leer la Parte 3 →