Skip to main content

Pruebas funcionales y estructurales. Cómo comprobar que tu backend funciona por fuera y por dentro

Probar una aplicación web cuando “funciona” no es suficiente

Cuando desarrollas una aplicación web, no basta con que parezca que funciona en los casos normales. Es necesario comprobar que responde correctamente a las peticiones del usuario y, además, que su lógica interna no contiene caminos rotos que solo se manifiestan cuando la aplicación ya está en producción.

En este punto aparecen dos tipos de pruebas fundamentales: las pruebas funcionales y las pruebas estructurales. Ambas persiguen el mismo objetivo —evitar errores y comportamientos inesperados—, pero lo hacen desde puntos de vista distintos y complementarios.

Piensa en una máquina expendedora. Como usuario, introduces una moneda y esperas recibir un refresco. No te importa cómo funciona por dentro. Sin embargo, el técnico que la mantiene revisa cables, sensores y motores internos para asegurarse de que nada falle. Esa diferencia resume con precisión el contraste entre pruebas funcionales y pruebas estructurales.

Dos miradas sobre el mismo sistema

Las pruebas funcionales observan el sistema desde fuera. Analizan qué entra y qué sale, sin interesarse por la implementación interna. Las pruebas estructurales, en cambio, se centran en el interior del código y en cómo se recorren sus distintas rutas lógicas. En una aplicación web real, ambas miradas son necesarias para tener una visión completa del estado del sistema.

Pruebas funcionales (caja negra)

Las pruebas funcionales verifican que el sistema cumple los requisitos definidos sin mirar el código interno. Solo importa el comportamiento observable. En una aplicación web, esto implica enviar peticiones HTTP y comprobar respuestas, códigos de estado, mensajes de error y validaciones visibles.

Un ejemplo típico en un backend con Express es una ruta de autenticación. Si se envían credenciales correctas, debe concederse el acceso. Si son incorrectas, debe devolverse un error controlado. No interesa si internamente se usan sesiones, tokens o una base de datos concreta; lo único relevante es el resultado que recibe el cliente.

Es como usar un ascensor. Pulsas un botón y esperas llegar al piso correcto. No necesitas saber cómo funcionan los cables, el motor o el sistema de poleas. Mientras el ascensor haga lo esperado, el sistema cumple su función.

En desarrollo web, este tipo de pruebas garantiza que la experiencia del usuario es coherente, predecible y consistente, independientemente de cómo esté implementada la lógica interna.

Ejemplo funcional simplificado: Eldoria Chronicles

En Eldoria Chronicles, un sistema de login resume bien este enfoque.

Desde el punto de vista funcional, solo se evalúa el contrato externo del endpoint:

– Credenciales válidas producen acceso y datos del jugador.

– Credenciales inválidas producen un error genérico.

– Usuarios inexistentes reciben la misma respuesta de error por seguridad.

No importa si internamente se usa SQLite, JWT o cualquier otra técnica. La prueba se limita a comprobar que, dada una entrada concreta, la salida es la esperada.

El mismo principio se aplica a la interfaz: escribir datos, pulsar un botón y observar el resultado. Mensajes de error, redirecciones, estados de carga y bloqueos de acciones forman parte del comportamiento observable que debe verificarse.

  1. Enfoque funcional: Solo se evalúa el contrato externo (entrada → salida)
  2. Casos del endpoint:
    • Credenciales válidas → acceso + datos
    • Credenciales inválidas → error genérico
    • Usuario inexistente → mismo error (por seguridad)
  3. Independencia técnica: Lo interno (SQLite, JWT, etc.) es irrelevante para la prueba
  4. Extensión a interfaz: Mismo principio aplicado a UI con comportamientos observables verificables

Pruebas estructurales (caja blanca)

Las pruebas estructurales adoptan el punto de vista opuesto. Aquí sí se analiza el código interno. El objetivo es comprobar que todas las partes relevantes de la lógica se ejecutan correctamente: condiciones if y else, bucles, validaciones, valores límite y manejo de errores.

En un backend real, esto significa probar funciones que calculan valores, validan datos o interactúan con SQLite. Se busca evitar errores ocultos en ramas de código que rara vez se ejecutan, pero que pueden activarse con datos reales o situaciones excepcionales.

Ejemplo estructural ajustado: lógica de juego en Eldoria

En Eldoria Chronicles, una función de cálculo de daño es un ejemplo adecuado de prueba de caja blanca. No interesa solo el resultado final, sino cómo se llega a él.

Se prueban explícitamente los caminos internos:

– Cuando una condición se cumple y se aplica un modificador.

– Cuando esa condición no se cumple.

– Cuando el resultado cae por debajo de un mínimo permitido.

Cada caso fuerza una ruta distinta del código y confirma que la lógica responde correctamente en situaciones normales y límite.

Aquí la metáfora cambia: no basta con saber que el coche arranca. Es necesario abrir el capó y comprobar que cada pieza funciona por separado y en conjunto.

  1. Enfoque de caja blanca: Se prueba el proceso interno, no solo el resultado
  2. Caminos lógicos específicos:
    • Ruta A: Cuando se aplica un modificador (condición cumplida)
    • Ruta B: Cálculo normal (condición no cumplida)
    • Ruta C: Ajuste por mínimo (resultado bajo límite)
    • Ruta D: Resultado válido (dentro de límites)
  3. Verificación exhaustiva:
    • Lógica de condiciones
    • Aplicación de modificadores
    • Validación de límites
    • Casos normales y límite
  4. Contraste claro con el enfoque de caja negra del endpoint anterior, donde solo importaba el contrato externo, no la implementación interna.

Bucles, límites y casos extremos

Las pruebas estructurales también son esenciales para validar bucles y condiciones repetitivas. Sistemas como la ganancia de experiencia o la subida de nivel suelen contener bucles que pueden ejecutarse cero, una o múltiples veces.

Probar estos escenarios permite verificar:

– Qué ocurre cuando el bucle se ejecuta una sola vez.

– Qué ocurre cuando se ejecuta varias veces seguidas.

– Qué sucede al alcanzar límites máximos definidos por el sistema.

Este tipo de pruebas evita errores clásicos como bucles infinitos, desbordamientos de valores o estados incoherentes del personaje.

  1. Enfoque en bucles: Pruebas estructurales específicas para iteraciones
  2. Tres casos principales:
    • Ejecución única (caso base)
    • Ejecuciones múltiples (caso normal)
    • Límites del sistema (casos de borde)
  3. Escenarios específicos:
    • 0 iteraciones (entrada inválida)
    • 1 iteración (caso simple)
    • N iteraciones (funcionamiento normal)
    • Límite máximo (comportamiento en frontera)
  4. Errores que se previenen:
    • Bucles infinitos
    • Desbordamientos
    • Estados incoherentes
    • Pérdida de progreso
  5. Objetivos de validación:
    • Condiciones correctas
    • Acumulaciones precisas
    • Límites respetados
    • Estados válidos
  6. Resultado final: Sistema robusto y predecible para el jugador

Validaciones y cobertura del código

Otro uso clave de la caja blanca es garantizar que todas las validaciones se ejecutan correctamente. Funciones que validan la creación de un personaje, por ejemplo, deben cubrir nombres vacíos, longitudes incorrectas, valores fuera de rango y casos válidos.

El objetivo no es repetir pruebas redundantes, sino asegurar que cada condición lógica ha sido evaluada al menos una vez. De este modo, se obtiene una cobertura real del código, no solo de los casos habituales.

Cuando una rama nunca se ejecuta en pruebas, queda como un punto ciego potencialmente peligroso.

Caja negra y caja blanca trabajando juntas

Las pruebas funcionales garantizan que el contrato externo del sistema se cumple: rutas, respuestas HTTP y comportamientos visibles para el usuario. Las pruebas estructurales garantizan que la lógica interna es sólida y no depende de la casualidad.

En backend, lo habitual es usar caja negra para validar endpoints completos y caja blanca para asegurar que la lógica de negocio responde correctamente en todos sus caminos posibles. Utilizar solo una de ellas deja huecos importantes en la calidad del sistema.

Dos reglas complementarias

Regla de la caja negra: no necesito ver el motor para saber si el coche arranca cuando giro la llave.

Regla de la caja blanca: necesito ver el motor para comprobar que cada pieza funciona antes de salir a la carretera.

Aplicadas a Eldoria Chronicles, estas reglas se traducen en algo simple: como tester, basta con comprobar que atacar reduce la vida, comprar gasta oro y el login concede acceso. Como desarrollador, es imprescindible asegurarse de que cada if, cada bucle y cada condición límite se comportan correctamente.

Pruebas como garantía de calidad real

El resultado de combinar ambos enfoques son pruebas que pueden ejecutar tanto perfiles técnicos como no técnicos, y al mismo tiempo pruebas profundas que garantizan que todos los caminos del código funcionan, no solo los casos normales.

Este equilibrio es lo que convierte las pruebas en una herramienta educativa y profesional, y no en un simple trámite añadido al final del desarrollo.