¿Por qué TDD se ha convertido en un estándar para los desarrolladores PHP?
Imagine: escribe código, lo ejecuta, ve un error, lo corrige — y así en un círculo. ¿Le suena familiar? Ahora imagine que primero escribe una prueba que fallará a propósito, luego el código mínimo para que pase, y solo después refactoriza. Esto es TDD en PHP — desarrollo guiado por pruebas, que transforma el caos en un sistema ordenado.
Muchos desarrolladores temen a TDD: «¡Esto ralentizará el desarrollo!», «No sé cómo probar código heredado», «PHPUnit es complicado». Pero en la práctica, TDD ahorra horas de depuración y hace que el código sea resistente a los cambios. En este artículo analizaremos TDD con ejemplos reales de PHP, mostraremos cómo funciona el ciclo «rojo-verde-refactorización» y daremos plantillas listas para implementar.
¿Qué es TDD y cómo funciona en PHP?
El desarrollo guiado por pruebas (Test-Driven Development) es una metodología donde las pruebas se escriben antes de la implementación. El ciclo principal es el siguiente:
- Rojo — escribimos una prueba que no pasa (esperamos un error).
- Verde — escribimos el código mínimo para que la prueba pase.
- Refactorización — mejoramos el código sin cambiar su comportamiento.
En PHP, para TDD se usa principalmente PHPUnit, un potente framework para pruebas unitarias. Pero TDD no se trata de herramientas, sino de disciplina. Veamos cómo funciona en la práctica.
Ejemplo 1: Probando una calculadora simple
Supongamos que necesitamos una función para sumar dos números. Sin TDD, escribiríamos:
function add($a, $b) { return $a + $b;}echo add(2, 3); // 5Con TDD, primero escribimos la prueba:
use PHPUnit\\Framework\\TestCase;
class CalculatorTest extends TestCase { public function testAdd() { $calculator = new Calculator(); $result = $calculator->add(2, 3); $this->assertEquals(5, $result); }}Ejecutamos — la prueba falla (rojo). Escribimos la implementación mínima:
class Calculator { public function add($a, $b) { return $a + $b; }}La prueba pasa (verde). No se necesita refactorización — el código es simple. Pero si quisiéramos agregar manejo de números negativos, primero escribiríamos una prueba para ese caso.
Ejemplo 2: TDD para trabajar con bases de datos
A menudo se dice: «TDD no es adecuado para bases de datos». Es un mito. Use mocks y bases de datos de prueba. Veamos un ejemplo con UserRepository:
class UserRepositoryTest extends TestCase { public function testFindUserById() { $pdoMock = $this->createMock(PDO::class); $stmtMock = $this->createMock(PDOStatement::class); $pdoMock->method('prepare') ->willReturn($stmtMock); $stmtMock->method('fetch') ->willReturn(['id' => 1, 'name' => 'Alex']); $repository = new UserRepository($pdoMock); $user = $repository->findById(1); $this->assertEquals('Alex', $user['name']); }}La prueba verifica que el repositorio llama correctamente a SQL y procesa el resultado. El código de implementación será mínimo: simplemente ejecutar la consulta y devolver los datos.
Herramientas populares para TDD en PHP
Para que TDD sea parte de su flujo de trabajo, necesita dominar algunas herramientas:
- PHPUnit — el framework principal para pruebas. Instalación:
composer require --dev phpunit/phpunit. - Mockery — biblioteca para crear mocks con una API flexible.
- Prophecy — alternativa a Mockery, a menudo usada con Symfony.
- PHPStan / Psalm — análisis estático que complementa TDD, encontrando errores antes de ejecutar las pruebas.
Para pruebas de integración, puede usar Laravel Dusk o Symfony Panther, pero para empezar, bas