4.5 · Tests automatizados con PHPUnit

Nivel 4 · Frameworks & API

4.5Tests automatizados con PHPUnit

Objetivo: Fiabilizar su código con tests automatizados (PHPUnit, aserciones, niveles) : confianza, no regresión, mejor diseño — lo que separa un prototipo de una aplicación profesional.
Tiempo estimado: 11 min · lectura autónoma · Si solo tienes 5 min: lee «Lo esencial en 30s» + el esquema.

Lo esencial en 30 segundos

  • Tests = código que prueba el código : PHPUnit (vía Composer), aserciones (assertEquals, assertTrue…) que fallan si lo real ≠ lo esperado.
  • 3 niveles : unitarios (función aislada), integración (con la base), funcionales (como un usuario) — ./vendor/bin/phpunit los lanza todos.
  • Reflejo de Riad : probar primero la lógica de negocio crítica, relanzar tras cada cambio — la no regresión que libera.

Minicaso seguido — Riad blinda sus precios antes de la promo

En vísperas de las promos, Riad teme que un descuento rompa sus precios en Constantine : escribe su primer test PHPUnit sobre prixTTC, añade los casos límite (cero, tasa nula, cesta vacía), y luego relanza toda la suite tras cada retoque. Cuando un colega modifica el cálculo, el test se pone en rojo ANTES de la puesta en línea. Último hito del hilo : del prototipo que « funciona » a la aplicación pro que demuestra.

Último episodio del caso 4.1-4.4 — Riad cierra el nivel : arquitecturar, equipar, exponer, fiabilizar.

1. PHPUnit y las aserciones

Probar a mano es fastidioso, incompleto y no repetible : escribimos código que PRUEBA el código, relanzable a voluntad. En PHP, la referencia es PHPUnit (instalado vía Composer, lanzado por ./vendor/bin/phpunit). Un test verifica que una entrada da la salida ESPERADA vía aserciones — assertEquals($attendu, $resultat), assertTrue(...), assertNull(...) — que fallan si la realidad difiere. Tests organizados en clases y métodos, ejecutados en masa con informe de pasados/fallidos. Tres niveles : unitarios (función/clase aislada), integración (varias partes, p. ej. con la base), funcionales/de extremo a extremo (como un usuario).

2. Los beneficios y el TDD

Los beneficios : CONFIANZA (sabemos, no creemos), NO REGRESIÓN — el mayor — (relanzar tras cada cambio avisa enseguida si un retoque rompe lo que funcionaba), DOCUMENTACIÓN (comportamiento esperado, ejecutable y al día), MEJOR DISEÑO (el código testeable está mejor dividido), detección TEMPRANA (en dev, no en prod). Laravel y Symfony integran PHPUnit con herramientas dedicadas (bases de test, peticiones HTTP simuladas). El TDD escribe los tests ANTES del código (el test define lo esperado, el código lo hace pasar) — disciplina que mejora el diseño. Riad empieza pequeño : lógica crítica primero, no 100 % de entrada.

Error frecuente de interpretación: « Probar es perder el tiempo : funciona, lo he verificado a mano ». No. La verificación manual cubre algunos casos, solo hoy — y cada futuro retoque puede romper silenciosamente lo que funcionaba. Los tests se relanzan en segundos y avisan enseguida : esa no regresión permite refactorizar sin miedo. « Funciona » sin tests es « funciona por ahora ».
El bucle de confianza PHPUnit Escribir → lanzar → modificar → relanzar Escribir Test : entrada →salida esperadaLanzar ./vendor/bin/phpunit,informeModificar Retoque orefactoringRelanzar Verde = noregresión probada
Escribir → lanzar → modificar → relanzar
Versión en texto del esquema (SEO / lectores de pantalla / traducción): 1) Riad escribe un test PHPUnit sobre su lógica crítica : entrada dada, salida esperada en aserción. 2) Lanza la suite y observa el informe. 3) Modifica su código con confianza. 4) Relanza : verde, nada roto — rojo, regresión atrapada antes de la producción. Lección : demostrar en lugar de creer.

🔎 Ejemplo concreto — 🔎 Ejemplo concreto — Primer test de precio TTC

El primer test de Riad, con las API reales de PHPUnit :

prixTTC(100, 0.20) → esperado 120.0 (assertEquals)
prixTTC(0, 0.20) → esperado 0 (caso límite)
Lanzar → ./vendor/bin/phpunit → OK (2 tests, 2 aserciones)
Retoque → relanzar → verde = nada roto

Lectura : una entrada, un esperado, una aserción — y luego el bucle.

Lección : los casos límite atrapan los bugs que la demo no ve.

Vocabulario de la sección

Tests automatizados / PHPUnit
Código que PRUEBA vuestro código (relanzable a voluntad) en lugar de verificar a mano. PHPUnit es el estándar PHP (vía Composer).

Ejemplo sencillo: Riad lanza ./vendor/bin/phpunit y obtiene su informe en segundos.

Lo que no es: una verificación manual única en el navegador.

Reflejo: todo comportamiento crítico merece su test.

Aserciones
Verificaciones del test : assertEquals(esperado, resultado), assertTrue, assertNull… — fallan si lo real ≠ lo esperado.

Ejemplo sencillo: Riad afirma assertEquals(120, prixTTC(100, 0.20)).

Lo que no es: un echo « parece bueno » sin comparación estricta.

Reflejo: esperado primero, real después, mensaje claro.

Niveles de tests
Unitarios (aislado), integración (varias partes, p. ej. con la base), funcionales/de extremo a extremo (como un usuario).

Ejemplo sencillo: Riad prueba prixTTC en unitario, el pedido con su base en integración.

Lo que no es: un solo gran test que mezcla todo.

Reflejo: pirámide : muchos unitarios, pocos de extremo a extremo.

Beneficios de los tests
Confianza, NO REGRESIÓN (detectar lo que un cambio rompe), documentación, mejor diseño, detección temprana.

Ejemplo sencillo: La suite de Riad atrapa un descuento roto antes de la promo.

Lo que no es: descubrir la rotura por un ticket de cliente en producción.

Reflejo: suite verde exigida antes de cada entrega.

TDD (Test-Driven Development)
Escribir los tests ANTES del código (el test define lo esperado, el código lo hace pasar) ; disciplina que mejora el diseño.

Ejemplo sencillo: Riad escribe el test de descuento antes de la función, luego programa hasta el verde.

Lo que no es: programar al azar y luego probar para « validar » después.

Reflejo: rojo → verde → refactor : el ciclo TDD.

En la práctica — En la práctica — Fiabilizar su código con tests

  1. Instalad PHPUnit (vía Composer) y escribid un primer test unitario de una función (entrada → esperado, assertEquals…).
  2. Lanzad con ./vendor/bin/phpunit, leed el informe ; añadid casos límite y entradas inválidas.
  3. Escribid un test de integración (funcionalidad + base) ; con framework, usad las herramientas de test integradas.
  4. Relanzad tras cada cambio (no regresión) y probad el TDD (test ANTES del código).
Fiabilizáis vuestro código con tests automatizados (PHPUnit, aserciones, niveles) : confianza, no regresión, mejor diseño — el nivel pro.

Guion listo para decir — anunciar la suite verde (30 s)

« Soy Riad : nuestros cálculos críticos están cubiertos por PHPUnit — unitarios, casos límite e integración base. Cada retoque relanza la suite : verde, entregamos ; rojo, corregimos antes de la prod. »

Para decir antes de cada entrega ; mostrad la suite verde.

Modelo copiar-pegar — test PHPUnit (código probado)

assertEquals(120.0, prixTTC(100, 0.20));
    }
    public function testCasLimites(): void {
        $this->assertEquals(0.0, prixTTC(0, 0.20));
        $this->assertEquals(100.0, prixTTC(100, 0.0));
        $this->assertTrue(prixTTC(50, 0.20) > 50);
    }
}
// Lanzar : ./vendor/bin/phpunit PrixTest.php

Primer paso

Un solo test sobre el cálculo crítico : valor inmediato, hábito instalado.

Lógica de riesgo

Como Riad : cálculos, reglas de negocio, casos límite e inválidos — donde los bugs cuestan caros.

Con framework

Bases de test y peticiones HTTP simuladas de Laravel/Symfony para la integración.

Equipo que crece

Suite verde exigida antes de merge : la no regresión se vuelve un ritual colectivo.

Prudencia: Los tests prueban lo probado, no todo : nunca exponer secretos en los tests (fixtures ficticias, .env.testing fuera de Git) y mantener los datos personales fuera de los juegos de test. Contenido pedagógico, ejemplos con datos ficticios.

✓ Buenas prácticas

  • Probar la lógica crítica con prioridad.
  • Relanzar tras cada cambio.
  • Probar el TDD en una pequeña función.

✗ Errores frecuentes

  • Creer que « funciona » dispensa de probar.
  • Apuntar al 100 % de cobertura de entrada.
  • Solo probar a mano, una vez.

Puntos clave

  • TESTS AUTOMATIZADOS (PHPUnit, estándar PHP) : código que PRUEBA el código. ASERCIONES (assertEquals…) si lo real ≠ lo esperado.
  • NIVELES : UNITARIOS (aislado), INTEGRACIÓN (con base), FUNCIONALES (como un usuario).
  • BENEFICIOS : CONFIANZA, NO REGRESIÓN (relanzar tras cada cambio — el mayor), documentación, DISEÑO.
  • Los frameworks integran PHPUnit. TDD = tests ANTES del código. INDISPENSABLE en prod — separa prototipo y app PRO.

Desafío 48h — aplicad mañana

Escribid 2 tests PHPUnit sobre vuestra función más crítica (1 caso normal + 1 caso límite) y relanzad tras 1 retoque.

Lista de salida de la sección
  • Puedo explicar PHPUnit, aserciones, niveles.
  • Sé lanzar la suite y leer el informe.
  • Tengo 2 tests verdes sobre mi lógica crítica.
Autoevaluación 1-5 : ¿mi lógica crítica está cubierta?¿he relanzado la suite tras mi último retoque?

Preguntas frecuentes

Los tests parecen una pérdida de tiempo cuando « ya funciona » : ¿por qué probar?

Porque « funciona » solo vale para los casos verificados a mano, hoy. Mañana, cada cambio arriesga una regresión silenciosa — sin tests, habría que re-verificar todo a mano, lo que nunca hacemos. Los tests aportan confianza (sabemos), no regresión (aviso inmediato), documentación viva del comportamiento, mejor diseño (lo testeable está mejor dividido) y detección temprana — infinitamente más barata que en producción.

¿Cómo empezar sin verse superado — qué probar con prioridad?

Progresivo, no 100 % de entrada : lógica de negocio crítica (cálculos, reglas — donde un bug cuesta caro), código complejo/de riesgo o que se rompe a menudo, casos límite y entradas inválidas (cero, extremos, vacíos — donde se esconden los bugs), código reutilizado (un bug se propaga por todas partes). Menos prioritario al inicio : trivial (getters), presentación pura. Método : Arrange-Act-Assert — preparar, actuar, verificar.

Comprueba tu comprensión

¿Cuál es el beneficio principal de los tests automatizados?

Recursos adicionales (opcional, para ir más allá)

Examen del nivel 4Preguntas inéditas y más difíciles para validar tus conocimientos