Introducción: por qué tus pruebas mienten y tú les crees
\n\nImagina: escribiste 50 pruebas unitarias, cubriste todos los if-else, las ejecutaste en CI — todo verde. Una semana después, producción falla con el error "Division by zero". ¿Cómo? ¡Si las pruebas pasaban! ¿Te suena?
El problema de las pruebas unitarias clásicas (ejemplares, con números concretos) es que verifican lo que ya sabes. Tú eliges argumentos que, según tu criterio, llevarán a un error. Pero la mente del programador es predecible: todos escribimos testDivideByZero y nos olvidamos de testDivideByNegativeZero o testDivideByVeryLargeFloat.
Aquí entra en escena la prueba basada en propiedades en PHP — un método que no verifica escenarios concretos, sino que demuestra propiedades de tu código para miles de datos de entrada aleatorios. Hoy analizaremos cómo implementar este enfoque en tu proyecto PHP, utilizando Eris y PHPUnit. Aprenderás a encontrar errores que las pruebas normales pasan por alto y por qué esto no es magia, sino ingeniería.
\n\n¿Qué son las pruebas basadas en propiedades? (y por qué no son aleatorias)
\n\nUna prueba unitaria típica se ve así: assert(2 + 2 === 4). Verificas una afirmación concreta. La prueba basada en propiedades (PBT) funciona de otra manera: formulas una propiedad — una afirmación que debe ser verdadera para cualquier dato de entrada válido.
Ejemplo de propiedad para una función de suma:
\n- \n
- Conmutatividad:
a + b === b + apara cualquier número. \n - Idempotencia: aplicar la función repetidamente no cambia el resultado. \n
- Invariancia: el resultado siempre es positivo (si esa es la propiedad). \n
PBT genera cientos de valores aleatorios (incluyendo límites, cero, negativos, NaN) y verifica que la propiedad no se rompa. Si se encuentra un contraejemplo, la prueba falla con los datos de entrada específicos que causaron el error. No obtienes solo "la prueba falló", sino un error reproducible.
\n\nEn PHP, esta tecnología es especialmente útil debido al tipado dinámico: nunca sabes realmente qué tipo llegará a una función.
\n\nHerramientas para pruebas basadas en propiedades en PHP
\n\nLa herramienta principal es la biblioteca Eris (github.com/giorgiosironi/eris). Se integra con PHPUnit y proporciona generadores de datos aleatorios. Una alternativa son las capacidades integradas de PHPUnit 10+ (pero aún son inmaduras). Usaremos Eris, ya que es una herramienta madura y bien documentada.
\n\nInstalación mediante Composer:
\ncomposer require --dev giorgiosironi/eris\n\nTambién será útil Faker para generar estructuras complejas (correos electrónicos, nombres, direcciones).
\n\ncomposer require --dev fakerphp/faker\n\nEscribimos nuestra primera prueba basada en propiedades: rompemos la ordenación
\n\nSupongamos que tenemos una función sortArray() que utiliza quicksort. Escribamos una propiedad: "el array después de ordenar no debe contener elementos menores que el anterior".
use Eris\\TestTrait;\nuse Eris\\Generator\\IntegerGenerator;\nuse PHPUnit\\Framework\\TestCase;\n\nclass SortTest extends TestCase\n{\n use TestTrait;\n\n public function testSortedArrayProperty(): void\n {\n $this->forAll(\n Generator\\seq(Generator\\int())\n )->then(function (array $input) {\n $sorted = sortArray($input);\n for ($i = 0; $i < count($sorted) - 1; $i++) {\n $this->assertLessThanOrEqual(\n $sorted[$i + 1],\n $sorted[$i],\n "El array no está ordenado: " . json_encode($sorted)\n );\n }\n });\n }\n}\n\n\nEjecución