Los formularios son donde viven los bugs

Los formularios son la forma principal en que los usuarios interactúan con las aplicaciones web — login, registro, búsqueda, checkout, actualización de perfil, formularios de contacto. También son donde viven la mayoría de los bugs. Cada campo de formulario es un punto de entrada para datos inválidos, caracteres inesperados y casos límite.

Un tester de formularios exhaustivo no solo llena datos válidos y hace clic en enviar. Piensa en cada posible input que un usuario — o un atacante — podría proporcionar.

Anatomía de un formulario web

Un formulario típico incluye:

  • Inputs de texto: Nombres, emails, direcciones, texto libre
  • Selectores: Dropdowns, radio buttons, checkboxes
  • Inputs especiales: Date pickers, carga de archivos, color pickers, range sliders
  • Botones: Enviar, resetear, cancelar
  • Campos ocultos: Tokens CSRF, IDs de usuario, datos de tracking

Cada tipo de elemento tiene su propia clase de bugs y casos de prueba.

Validación del lado del cliente vs. del servidor

Validación del lado del cliente

Ocurre en el navegador usando atributos HTML y JavaScript. Proporciona feedback instantáneo pero puede evadirse.

Atributos de validación HTML:

<input type="email" required minlength="5" maxlength="255" pattern="[a-z@.]+">

Validación JavaScript:

if (password.length < 8) {
  showError('La contraseña debe tener al menos 8 caracteres');
  return false;
}

Validación del lado del servidor

Ocurre en el servidor después del envío del formulario. Esta es la frontera de seguridad — no puede ser evadida por el usuario.

Regla crítica de testing: Siempre prueba la validación del servidor evadiendo la validación del cliente. En la consola de DevTools:

document.querySelector('form').noValidate = true;
// O remover atributos 'required':
document.querySelectorAll('[required]').forEach(el => el.removeAttribute('required'));

Luego envía el formulario con datos inválidos. El servidor debe seguir rechazándolos.

Casos de prueba por tipo de campo

Campos de texto

Caso de pruebaInputResultado esperado
Campo requerido vacío(nada)Error de validación
Longitud mínima1 carácterAceptar o rechazar según spec
Longitud máximaMax + 1 caracteresRechazar o truncar
Caracteres especiales<script>alert('xss')</script>Sanitizado, sin ejecución de script
Caracteres Unicode名前 Ñoño ÜnïcödëAceptar si se soportan nombres internacionales
Espacios al inicio/finalJuanAceptar pero limpiar, o rechazar según spec
Solo espaciosRechazar (vacío después de limpiar)
Input muy largo10,000+ caracteresManejar correctamente, sin crash
SQL injection'; DROP TABLE users; --Manejado de forma segura
Entidades HTML&amp; &lt; &#39;Mostradas correctamente
EmojisJuan 🎉 PérezAceptar o rechazar consistentemente

Campos de email

Caso de pruebaInputEsperado
Email válidouser@example.comAceptar
Sin @userexample.comRechazar
Sin dominiouser@Rechazar
Sin parte local@example.comRechazar
Puntos doblesuser@example..comRechazar
Subdominiouser@mail.example.comAceptar
Plus addressinguser+tag@example.comAceptar
Email muy largo255+ caracteresSegún límite RFC

Campos de contraseña

Caso de pruebaInputEsperado
Longitud mínima7 chars (si min es 8)Rechazar con mensaje
Longitud máximaMuy largo (1000+ chars)Aceptar o aplicar máximo
Sin mayúsculapassword123!Según política
Sin númeroPassword!!!Según política
Contraseñas comunespassword123, 123456Rechazar si existe blocklist
Espacios en contraseñaMi Password 1!Aceptar (espacios son válidos)
Pegar deshabilitado?(Pegar desde portapapeles)Debería permitir pegar
Toggle mostrar/ocultar(Clic ícono ojo)Revela/oculta texto

Campos numéricos

Prueba los límites cuidadosamente: valor mínimo, valor máximo, min-1, max+1, cero, números negativos, decimales, caracteres no numéricos.

Testing de envío de formularios

Estados del botón de envío

  • Antes de interacción: Enviar debería estar habilitado (o deshabilitado si se requieren campos específicos)
  • Durante el envío: Botón deshabilitado para prevenir envío doble; mostrar indicador de carga
  • Después de éxito: Redirigir o mostrar mensaje de éxito
  • Después de fallo: Mostrar mensajes de error; preservar input del usuario; rehabilitar botón

Envío doble

Haz clic en el botón de enviar rápidamente múltiples veces. ¿El formulario:

  • ¿Envía solo una vez? (Correcto)
  • ¿Envía múltiples veces, creando registros duplicados? (Bug)
  • ¿Muestra un estado de carga que previene re-clic? (Buena UX)

Testing avanzado de formularios

Orden de tabulación y navegación por teclado

  1. Haz clic en el primer campo y presiona Tab repetidamente
  2. Verifica que el focus se mueva por los campos en orden lógico
  3. Verifica que puedas enviar el formulario usando Enter
  4. Verifica que los dropdowns se puedan navegar con flechas
  5. Verifica que los checkboxes se alternen con Espacio
  6. Verifica que los radio buttons cambien con flechas

Testing de autofill

Los navegadores auto-completan formularios con datos guardados. Prueba:

  • ¿El formulario acepta valores autocompletados correctamente?
  • ¿Los nombres de campos son suficientemente semánticos para que el navegador autocomplete apropiadamente?
  • ¿El autofill dispara validación del lado del cliente?
  • ¿El formulario se rompe si autofill provee valores inesperados?

Calidad de mensajes de error

Buenos mensajes de error son:

  • Específicos: “El email debe incluir un símbolo @” no “Input inválido”
  • Ubicados cerca del campo: Errores inline, no solo una lista arriba
  • Persistentes: Permanecen visibles hasta que el error se corrige
  • Accesibles: Los lectores de pantalla pueden anunciarlos (usar aria-describedby)
  • Sin culpar: “Por favor ingresa un email válido” no “Ingresaste un email inválido”

Testing de formularios multi-paso

Formularios tipo wizard con múltiples pasos necesitan testing adicional:

  • ¿Puedes navegar a pasos anteriores sin perder datos?
  • ¿La validación ocurre por paso o solo al final?
  • ¿Qué pasa si refrescas a mitad del wizard?
  • Si abres la URL en una nueva pestaña, ¿empieza desde el paso 1 o recuerda el progreso?

Ejercicio: Auditoría completa de formulario

Encuentra un formulario de registro o checkout y pruébalo:

  1. Campos requeridos: Envía el formulario con cada campo requerido vacío, uno a la vez
  2. Valores límite: Prueba longitudes mínimas y máximas para cada campo de texto
  3. Caracteres especiales: Ingresa <script>alert(1)</script> en cada campo
  4. SQL injection: Ingresa ' OR 1=1 -- en cada campo
  5. Validación del servidor: Evade validación del cliente en DevTools y reenvía
  6. Envío doble: Haz clic en enviar 5 veces rápidamente
  7. Orden de tabulación: Navega todo el formulario solo con teclado
  8. Mensajes de error: Dispara cada error de validación y documenta la calidad del mensaje
  9. Autofill: Deja que el navegador autocomplete y verifica corrección
  10. Botón atrás: Envía exitosamente, luego presiona atrás en el navegador
CampoTestResultado¿Bug?
EmailSQL injection ' OR 1=1 --Servidor retorna error 500Sí - Crítico
Nombre1000 caracteresAceptado, pero rompe layout del perfilSí - Medio
ContraseñaPegar deshabilitadoNo se puede pegar contraseñaSí - Problema UX
TodosEnvío dobleDos cuentas creadasSí - Crítico

Tips profesionales

Tip 1: Prueba el envío de formularios con throttling de red. Las conexiones lentas exponen bugs de timing como envío doble.

Tip 2: Verifica lo que el servidor realmente recibe. En la pestaña Network, inspecciona el payload del request — los datos enviados podrían diferir de lo mostrado.

Tip 3: Prueba los indicadores de campos requeridos. Si un campo muestra un asterisco rojo (*), debe realmente ser requerido.

Puntos clave

  • Los formularios son el área de mayor densidad de bugs en aplicaciones web
  • Siempre prueba validación del cliente y del servidor de forma independiente
  • Valores límite, caracteres especiales y campos vacíos son donde se ocultan la mayoría de los bugs
  • La prevención de envío doble debe probarse en cada formulario
  • La navegación por teclado y orden de tabulación afectan usabilidad y accesibilidad
  • Los mensajes de error deben ser específicos, bien posicionados y accesibles
  • Evadir validación del cliente para probar la del servidor es una técnica crítica de testing de seguridad