smplx.
Arquitectura Shopify

Testing y QA para proyectos Shopify: Checklist [2026]

Claudio Gerlich··12 min

En nuestra Guía de Arquitectura Shopify cubrimos los fundamentos. Hoy: El último 10% del proyecto que a menudo causa el 90% de los problemas.

En smplx. hemos aprendido: Una tienda "casi terminada" no es lo mismo que una tienda "lista para lanzar". Testing y QA no son extras — son arquitectura.

Por qué el QA es crítico

Los números:

  • El 0,1% de los visitantes realiza una compra
  • Cada error en el checkout = pérdida directa de ingresos
  • El móvil es frágil (los tests de navegador no lo detectan)
  • Los errores de pago son una amenaza existencial

Realidad: No puedes testear todo manualmente. Necesitas una estrategia.

Qué necesitas testear

1. Flujo de checkout (Máxima prioridad)

Rutas críticas:

  • Añadir producto -> Carrito
  • Cambiar cantidades
  • Introducir cupón (válido, inválido, expirado)
  • Iniciar checkout
  • Seleccionar método de envío
  • Introducir pago
  • Mostrar confirmación de pedido
  • Recibir email

Escenarios:

  • Checkout normal con tarjeta de crédito
  • Checkout como invitado
  • Cliente con sesión iniciada
  • Pago exprés (Google Pay, Apple Pay)
  • Multi-divisa (si es relevante)
  • Desde diferentes países

Pagos de prueba:

Stripe Test Cards:
- 4242 4242 4242 4242 (Success)
- 4000 0000 0000 0002 (Decline)
- 4000 0025 0000 3155 (Requires 3D Secure)

Klarna Test:
- 4111 1111 1111 1111 (Success - Invoice)

2. Testing responsive y de navegadores

Dispositivos a testear:

  • Desktop (1920x1080, 1440x900, 1024x768)
  • Tablet (iPad, Samsung Tab)
  • Móvil (iPhone 12, iPhone SE, Samsung Galaxy)
  • Móvil antiguo (iPhone 8)

Navegadores a testear:

  • Chrome (última versión)
  • Safari (Mac + iOS)
  • Firefox (última versión)
  • Edge
  • Mobile Safari (iOS)
  • Chrome Mobile (Android)

Herramientas:

BrowserStack: https://www.browserstack.com
- Dispositivos reales en la nube
- Tests de screenshots automatizados

3. Testing de rendimiento (Web Vitals)

Testear con Lighthouse:

# Terminal
lighthouse https://shop.example.com --view

Objetivos:

  • LCP < 2,5s
  • INP < 100ms
  • CLS < 0,1
  • Puntuación general > 85

Medir con Web Vitals:

// En el tema o app headless
import { getCLS, getFID, getFCP, getLCP, getTTFB } from 'web-vitals';

function sendMetrics(metric) {
  // Enviar a analítica
  fetch('/api/metrics', {
    method: 'POST',
    body: JSON.stringify(metric)
  });
}

getCLS(sendMetrics);
getFID(sendMetrics);
getFCP(sendMetrics);
getLCP(sendMetrics);
getTTFB(sendMetrics);

4. Testing de SEO

Con axe DevTools (gratis):

# Extensión de Chrome para el navegador
# Verifica: Accesibilidad + SEO básico

Verificación manual:

  • H1 en cada página (exactamente uno)
  • Meta descriptions (todas las páginas)
  • Open Graph tags (compartir en redes sociales)
  • Datos estructurados (JSON-LD para productos)
  • Sitemap.xml existe
  • robots.txt no demasiado restrictivo

Ejemplo: Datos estructurados de producto

<script type="application/ld+json">
{
  "@context": "https://schema.org",
  "@type": "Product",
  "name": "{{ product.title }}",
  "description": "{{ product.description }}",
  "image": "{{ product.featured_image | image_url: width: 800 }}",
  "brand": {
    "@type": "Brand",
    "name": "{{ shop.name }}"
  },
  "offers": {
    "@type": "Offer",
    "price": "{{ product.selected_or_first_available_variant.price | divided_by: 100 }}",
    "priceCurrency": "{{ shop.currency }}",
    "availability": "https://schema.org/{% if product.selected_or_first_available_variant.available %}InStock{% else %}OutOfStock{% endif %}"
  },
  "aggregateRating": {
    "@type": "AggregateRating",
    "ratingValue": "{{ product.metafields.reviews.rating.value | default: 5 }}",
    "reviewCount": "{{ product.metafields.reviews.count.value | default: 0 }}"
  }
}
</script>

5. Testing de accesibilidad

Herramientas:

  • axe DevTools (extensión Chrome)
  • WAVE (WebAIM)
  • Auditoría de accesibilidad de Lighthouse

Verificaciones críticas:

  • Todas las imágenes tienen texto alternativo
  • El contraste de color es suficiente
  • La navegación por teclado funciona (tab a través de enlaces)
  • Las etiquetas de formulario son correctas (no solo placeholders)
  • Etiquetas ARIA donde sean necesarias

Ejemplo: Formulario accesible

<!-- INCORRECTO -->
<input type="email" placeholder="Email">

<!-- CORRECTO -->
<label for="email">Email</label>
<input type="email" id="email" name="email" required>

6. Cumplimiento de pagos e impuestos

Testear:

  • Cálculos de envío (correctos por país)
  • Cálculos de impuestos (IVA, sales tax)
  • Conversiones de moneda (si es multi-divisa)
  • Métodos de pago disponibles (por país)
  • Validación de direcciones funciona

Ejemplo: Cálculo de envío

// Shopify GraphQL
query CalculateShipping {
  cart(cartId: "...") {
    estimatedCost {
      shippingEstimate {
        amount
      }
      totalTaxEstimate {
        amount
      }
      subtotalAmount {
        amount
      }
      totalAmount {
        amount
      }
    }
  }
}

7. Testing de pagos móviles

Importante: ¡Apple Pay y Google Pay solo funcionan en dispositivos reales!

Configuración:

  • Apple Pay en dispositivo de prueba
  • Google Pay en Android

Testear con dispositivos reales:

Stripe Test Card para Apple Pay:
- Card Number: 4242 4242 4242 4242
- Exp: 12/26
- CVC: 123

Herramientas y configuraciones de testing

Testing automatizado: End-to-End

Con Playwright (recomendado):

// test.spec.js
import { test, expect } from '@playwright/test';

test('Flujo completo de checkout', async ({ page }) => {
  // 1. Ir a la tienda
  await page.goto('https://shop.example.com');

  // 2. Hacer clic en producto
  await page.click('[data-test="product-card"]');
  expect(page).toHaveURL(/\/products\//);

  // 3. Añadir al carrito
  await page.click('button:has-text("Add to cart")');
  await page.waitForURL('**/cart');

  // 4. Iniciar checkout
  await page.click('button:has-text("Checkout")');
  await page.waitForURL('**/checkout');

  // 5. Introducir email
  await page.fill('input[type="email"]', 'test@example.com');

  // 6. Dirección de envío
  await page.fill('input[placeholder="First name"]', 'Test');
  await page.fill('input[placeholder="Last name"]', 'User');
  await page.fill('input[placeholder="Address"]', '123 Main St');

  // 7. Seleccionar método de envío
  await page.click('text=Standard Shipping');

  // 8. Pago
  // El manejo del iFrame de Stripe es complejo
  // Pero el checkout gestionado por Shopify lo facilita

  // 9. Confirmación de pedido
  expect(page).toContain('Order #');
});

test('El cupón se aplica', async ({ page }) => {
  await page.goto('https://shop.example.com/cart');
  await page.fill('input[placeholder="Discount code"]', 'SAVE10');
  await page.click('button:has-text("Apply")');

  // El precio debería actualizarse
  await page.waitForSelector('text=Subtotal');
  const originalPrice = await page.locator('text=Subtotal').evaluate(el => el.textContent);
  expect(originalPrice).toContain('$');
});

Ejecutar:

npx playwright test
# O con interfaz gráfica
npx playwright test --ui

Testing de rendimiento: Lighthouse CI

// lighthouserc.json
{
  "ci": {
    "collect": {
      "url": [
        "https://shop.example.com",
        "https://shop.example.com/products",
        "https://shop.example.com/collections"
      ],
      "numberOfRuns": 3
    },
    "assert": {
      "preset": "lighthouse:recommended",
      "assertions": {
        "largest-contentful-paint": ["error", { "maxNumericValue": 2500 }],
        "cumulative-layout-shift": ["error", { "maxNumericValue": 0.1 }],
        "first-input-delay": ["error", { "maxNumericValue": 100 }]
      }
    }
  }
}
lhci autorun

Checklist pre-lanzamiento

72 horas antes del lanzamiento

Funcionalidad:

  • Todos los productos visibles + imágenes cargan
  • Las variantes funcionan (todas las opciones)
  • Inventario correcto (no es posible sobrevender)
  • Todos los métodos de pago activos
  • Todos los métodos de envío testeados
  • Todos los cupones/descuentos testeados
  • Las confirmaciones por email funcionan

Rendimiento:

  • Lighthouse Score > 85
  • LCP < 2,5s (móvil)
  • Sin imágenes rotas
  • Sin errores 404

SEO:

  • Sitemap.xml enviado a Google
  • Meta descriptions en todas las páginas
  • Robots.txt no demasiado restrictivo
  • Datos estructurados ok (rich snippets)

Seguridad:

  • HTTPS en todas partes
  • Cabeceras CSP configuradas
  • Protección XSS
  • Protección CSRF (predeterminado de Shopify)

Legal:

  • Política de privacidad actualizada
  • Términos y condiciones ok
  • Política de devoluciones clara
  • Aviso legal (RGPD)

24 horas antes del lanzamiento

  • Copia de seguridad de la base de datos
  • Monitoreo configurado (analítica, seguimiento de errores)
  • Plan de respuesta a incidentes (quién hace qué si hay un problema)
  • Sistema de soporte online (email, chat)
  • Campaña de marketing preparada (no iniciar el día del lanzamiento)

Después del lanzamiento (monitoreo 24-48h)

  • Tasas de error monitoreadas
  • Tasa de éxito de pagos > 95%
  • Tiempos de carga de página ok
  • Tickets de soporte al cliente escaneados (revelan patrones)
  • Tasa de conversión normal (sin anomalías)

Monitoreo post-lanzamiento

Real User Monitoring (RUM)

// En el tema o app
// Enviar métricas al servicio de monitoreo

window.addEventListener('error', (event) => {
  fetch('/api/errors', {
    method: 'POST',
    body: JSON.stringify({
      message: event.message,
      stack: event.error?.stack,
      url: window.location.href,
      timestamp: new Date()
    })
  });
});

// Rechazos de Promise no manejados
window.addEventListener('unhandledrejection', (event) => {
  fetch('/api/errors', {
    method: 'POST',
    body: JSON.stringify({
      message: 'Unhandled Promise Rejection',
      error: event.reason,
      timestamp: new Date()
    })
  });
});

Métricas clave a vigilar

Dashboard con:

  • Tasa de conversión (Visitas -> Compras)
  • Tasa de abandono del carrito
  • Valor medio del pedido
  • Tasa de éxito de pagos
  • Tiempo de carga de página (usuarios reales)
  • Tasa de errores (frontend + backend)
  • Tickets de soporte al cliente

Herramientas:

  • Google Analytics 4 (gratis)
  • Shopify Admin Reports
  • Sentry (seguimiento de errores)
  • Databox (dashboard de KPIs)

Respuesta a incidentes

Cuando ocurre un problema:

1. Detectar (Alerta de monitoreo)
   └─ Severidad: Crítica/Alta/Media/Baja

2. Confirmar (El equipo es notificado)
   └─ Persona de guardia: [Nombre]

3. Evaluar
   └─ Impacto: ¿Pérdida de ingresos? ¿UX rota? ¿API caída?

4. Mitigar (¡Rápido!)
   └─ ¿Rollback del tema?
   └─ ¿Desactivar app?
   └─ ¿Modo mantenimiento?

5. Corregir (causa raíz)
   └─ Debug del código
   └─ Deploy de la corrección

6. Monitorear (24h después de la corrección)
   └─ ¿Tasa de errores sigue bien?
   └─ ¿Rendimiento normal?

7. Postmortem (día siguiente)
   └─ ¿Por qué ocurrió?
   └─ ¿Cómo lo prevenimos en el futuro?

Testing para diferentes arquitecturas Shopify

Tienda basada en tema (Liquid)

Enfoque:

  • Rendimiento del tema
  • Errores de plantillas Liquid
  • Conflictos CSS/JS
  • Compatibilidad de navegadores

Herramientas:

  • Lighthouse
  • BrowserStack
  • Chrome DevTools

Tienda headless (Next.js/Remix)

Enfoque:

  • Manejo de errores de API
  • Rate limits de la Storefront API
  • Rendimiento SSR/SSG
  • Frescura de datos

Herramientas:

  • Jest (tests unitarios)
  • Playwright (tests E2E)
  • K6 (tests de carga)
// Ejemplo Jest
describe('Product Page', () => {
  it('should fetch product data from Storefront API', async () => {
    const response = await fetchProduct('123');
    expect(response).toHaveProperty('id');
    expect(response).toHaveProperty('title');
  });

  it('should handle API errors gracefully', async () => {
    const response = await fetchProduct('invalid');
    expect(response).toBeNull();
  });
});

Ecosistema multi-app

Enfoque:

  • Comunicación entre apps (cuando las apps interactúan)
  • Manejo de webhooks
  • Rate limits de API
  • Consistencia de datos

Herramientas:

  • Monitoreo de API (Postman, Insomnia)
  • Testing de webhooks (webhook.cool)
  • Testing de carga (Apache JMeter)

Checklist de QA (copiable)

# Checklist de QA pre-lanzamiento

## Testing funcional
- [ ] La página de inicio carga
- [ ] Las páginas de producto cargan con imágenes
- [ ] Las variantes funcionan (todas las opciones)
- [ ] Añadir al carrito funciona
- [ ] El carrito muestra totales correctos
- [ ] El flujo de checkout se completa
- [ ] El pago se procesa correctamente
- [ ] Se envía email de confirmación de pedido
- [ ] Se crea la cuenta del cliente (si aplica)

## Diseño responsive
- [ ] Móvil (320px) se ve bien
- [ ] Tablet (768px) se ve bien
- [ ] Desktop (1920px) se ve bien
- [ ] Los objetivos táctiles son al menos 44x44px
- [ ] Sin scroll horizontal
- [ ] Las imágenes escalan correctamente

## Rendimiento
- [ ] Lighthouse Score > 85
- [ ] LCP < 2,5s
- [ ] FID < 100ms
- [ ] CLS < 0,1
- [ ] Tamaño de página < 5MB

## SEO
- [ ] Meta descriptions configuradas
- [ ] Etiquetas H1 correctas
- [ ] Open Graph tags
- [ ] Datos estructurados válidos
- [ ] Sitemap enviado

## Seguridad
- [ ] HTTPS en todas partes
- [ ] Sin errores en consola
- [ ] Datos de pago seguros
- [ ] PII protegida

## Navegadores
- [ ] Chrome (último)
- [ ] Safari (Mac + iOS)
- [ ] Firefox (último)
- [ ] Edge (último)

## Pagos
- [ ] Tarjeta de prueba funciona
- [ ] Tarjeta inválida rechazada
- [ ] Impuestos calculados
- [ ] Envío calculado
- [ ] Cupones funcionan

Sobre el autor

Claudio Gerlich es Technical Architect en smplx. y está especializado en Shopify desde 2020. Con docenas de lanzamientos, hemos aprendido: El 90% de los problemas de lanzamiento son prevenibles con una buena estrategia de QA.

QA no es "testear de forma aburrida". Es evitar riesgos. Es proteger ingresos.

smplx. es Shopify Technical Partner (desde 2020) con sede en Muensterland, NRW.