Pruebas basadas en propiedades en PHP: rompemos el código más rápido de lo que lo escribes

Entrenador de Python en Línea para Principiantes

Aprende Python fácilmente sin sobrecargarte de teoría. Resuelve tareas prácticas con verificación automática, recibe pistas y escribe código directamente en el navegador, sin instalar nada.

Start Course

Introducción: por qué tus pruebas mienten y tú les crees

\n\n

Imagina: 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?

\n\n

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.

\n\n

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\n

Una 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.

\n\n

Ejemplo de propiedad para una función de suma:

\n
    \n
  • Conmutatividad: a + b === b + a para 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
\n\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\n

En PHP, esta tecnología es especialmente útil debido al tipado dinámico: nunca sabes realmente qué tipo llegará a una función.

\n\n

Herramientas para pruebas basadas en propiedades en PHP

\n\n

La 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\n

Instalación mediante Composer:

\n
composer require --dev giorgiosironi/eris
\n\n

También será útil Faker para generar estructuras complejas (correos electrónicos, nombres, direcciones).

\n\n
composer require --dev fakerphp/faker
\n\n

Escribimos nuestra primera prueba basada en propiedades: rompemos la ordenación

\n\n

Supongamos 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".

\n\n
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\n

Ejecución

Blogs

Book Recommendations