Nuno Maduro presentó Pest 5 en Laracon US 2026 y la versión salió a Packagist el 29 de julio. Reúne varios plugins que llevaban tiempo madurando durante el ciclo de Pest 4, y añade un motor nuevo que cambia bastante cuánto tarda tu suite mientras desarrollas.
Requisitos
Tres cosas que conviene comprobar antes de tocar el composer.json:
PHP 8.4 o superior
PHPUnit 13, sobre el que está construido Pest 5
Laravel 13.23 o superior, si usas
pest-plugin-laravel
El tercero es el que suele pillar por sorpresa. La versión 5 del plugin de Laravel declara laravel/framework: ^13.23.0, así que en un proyecto que siga en Laravel 12 no vas a poder instalar Pest 5 con el plugin aunque tengas PHP 8.4 en la máquina. Si tu aplicación está en Laravel 12, la actualización de Pest va después de la del framework, no antes.
Cumplidos los requisitos, subir desde Pest 4 es una línea:
"pestphp/pest": "^5.0",El resto de plugins mantenidos por Pest suben también a ^5.0.
El motor Tia
Tia son las siglas de Test Impact Analysis. La premisa: casi toda tu suite es irrelevante para cualquier cambio concreto. Tocas un modelo y la mayoría de los tests no pueden comportarse de otra manera que antes. Ejecutarlos todos es tiempo perdido.
Se activa con el flag --tia:
./vendor/bin/pest --parallel --tiaLa primera ejecución graba un grafo de qué tests dependen de qué ficheros, y para eso necesitas un driver de cobertura instalado: PCOV o Xdebug. Sin uno de los dos no hay grafo. A partir de ahí, cada ejecución mira qué has cambiado, corre solo los tests que tocaron esos ficheros y reproduce desde caché los resultados del resto.
Tests: 774 passed (2658 assertions, 7 affected, 2 uncached, 765 replayed)
Duration: 3.92sUna suite de Laravel que tardaba 10 minutos se reproduce en unos 4 segundos.
Reproducir no es saltarse trabajo
Cada test cacheado guarda todo lo que produjo, incluidas las líneas y ramas exactas que cubrió. Una ejecución reproducida reporta la misma cobertura que una completa, así que no pierdes fidelidad en los informes ni en los umbrales que tengas configurados.
El grafo entiende tu stack
La cadena de dependencias no se queda en los ficheros PHP. Cambias una migración y solo se reejecutan los tests que consultaron esa tabla. Editas un componente JS compartido y Pest recorre el grafo de módulos de Vite para localizar cada página de Inertia que lo importa. Una edición que solo toca comentarios, o un pase del formateador, no reejecuta nada.
Pest detecta Laravel, Symfony, Livewire, Inertia y los assets de navegador automáticamente vía Composer. No hay que configurar nada.
Tia no va en CI
Conviene dejarlo claro porque es fácil suponer lo contrario: el motor Tia está pensado para desarrollo local. La recomendación de la documentación es mantener --tia fuera del comando que ejecuta la suite en CI, porque la pipeline debe correr siempre la suite completa contra un checkout limpio.
La única excepción es un workflow dedicado que grabe la baseline una vez por cada merge a main, para que cada desarrollador se la descargue y empiece a reproducir desde el primer momento.
El plugin de agentes
Los agentes de programación escriben código con soltura y no tienen forma de comprobar si funciona. El plugin Agent les da un comando único para verificarlo contra tu aplicación.
composer require pestphp/pest-plugin-agent --devAñade la opción --agent, que ejecuta un snippet dentro de un test Pest completo, con tus factories, RefreshDatabase y los fakes de Laravel disponibles igual que en un feature test:
./vendor/bin/pest --agent='$user = \App\Models\User::factory()->create(); $this->actingAs($user)->get("/dashboard")->assertOk();'Con el plugin de Browser Testing instalado, el agente puede además manejar un navegador real y comprobar los efectos secundarios que provoca —enviar un formulario de contacto y verificar que el mail salió— en un único sondeo:
./vendor/bin/pest --agent='visit("/")->assertSee("Welcome");'Frente a las herramientas de agente que solo controlan el navegador, la diferencia está en el alcance: aquellas confirman que la interfaz se ve bien, pero no que el job se encolara, que el mail se enviara o que la fila se escribiera. El plugin corre dentro de tu suite real, así que una comprobación que pasa cubre el flujo entero.
Evals
Testear software que habla con un modelo de lenguaje no se parece a testear código normal. El mismo prompt puede devolver una respuesta distinta cada vez, y una aserción de igualdad rara vez sirve. El plugin Evals permite evaluar la calidad de la salida con la misma API expect() de siempre.
composer require pestphp/pest-plugin-evals --dev<?php
use App\Agents\CapitalCityAgent;
it('answers capital city questions correctly', function (): void {
expect(CapitalCityAgent::class)
->prompt('What is the capital of France?')
->toContain('Paris') // comprobación determinista
->toBeRelevant() // LLM como juez
->toBeSimilar('Paris, France'); // similitud semántica
});Como cada eval llama a un modelo real, se saltan en una ejecución normal. Tu suite sigue siendo rápida y gratis, sin llamadas a la API por defecto:
./vendor/bin/pest # evals saltados, sin llamadas
./vendor/bin/pest --evals # modelo real, todos los scorers activosHay más scorers disponibles: toBeSafe() comprueba que un agente resiste inyección de prompt, toBeFactual() mide exactitud factual, toFollowTrajectory() verifica que llamó a las herramientas correctas en el orden correcto, y repeat() muestrea el mismo prompt varias veces. También puedes escribir los tuyos.
Plugin de PHPStan
Una de las peticiones más repetidas de la comunidad. PHPStan no entiende la API funcional de Pest: ni it(), ni test(), ni expect(), ni el $this que hay dentro de los closures. El plugin se lo enseña.
composer require pestphp/pest-plugin-phpstan --dev
composer require phpstan/phpstan --devSi usas phpstan/extension-installer, el registro es automático. Si no, en tu phpstan.neon:
includes:
- vendor/pestphp/pest-plugin-phpstan/extension.neonA partir de ahí el tipo fluye por la cadena de expect(), incluidas las expectations de orden superior como expect($user)->name->toBe('Nuno'), y PHPStan empieza a señalar errores reales en los tests:
<?php
expect(10)->toStartWith('1'); // un int nunca puede satisfacer toStartWith()Además del tipado, el plugin añade reglas propias de Pest: closures de test estáticos, $this dentro de beforeAll(), descripciones duplicadas, referencias inválidas en throws() y covers().
Si ya analizas tu aplicación con PHPStan a nivel 8, esto es lo que faltaba para que la carpeta tests/ deje de quedarse fuera.
Refactorización con Rector
composer require pestphp/pest-plugin-rector --dev
composer require rector/rector --devEn tu rector.php:
<?php
use Pest\Rector\Set\PestSetList;
use Rector\Config\RectorConfig;
return RectorConfig::configure()
->withPaths([__DIR__ . '/tests'])
->withSets([
PestSetList::CODING_STYLE,
]);Con este set, decenas de reglas convierten aserciones crudas de PHP en matchers de Pest y encadenan expectations redundantes:
<?php
// antes
expect(count($array))->toBe(5);
expect(array_key_exists('id', $array))->toBeTrue();
// después
expect($array)->toHaveCount(5)
->toHaveKey('id');Puedes previsualizar los cambios con vendor/bin/rector process --dry-run antes de aplicarlos. Hay sets para estilo de código y para actualizaciones de versión mayor, 60 reglas en total.
Sharding balanceado por tiempo
Pest 4 introdujo el sharding: partir la suite en trozos que corren en paralelo en varias máquinas de CI. El reparto por número de tests tiene un problema conocido, y es que un shard puede acabar corriendo mucho más rato que los demás. Pest 5 reparte según el tiempo real de ejecución, de forma que todos terminen más o menos a la vez.
Genera los datos de tiempos una vez:
./vendor/bin/pest --update-shardsDespués commitea tests/.pest/shards.json. Cuando uses --shard y ese fichero exista, el balanceo por tiempo se aplica solo:
./vendor/bin/pest --shard=1/4Si añades ficheros nuevos antes de actualizar los tiempos, los tests siguen ejecutándose: los nuevos se reparten de forma uniforme mientras los conocidos mantienen el balanceo, y Pest te avisa de que refresques los datos.
Expectations nuevas
Ocho matchers para comprobaciones lo bastante frecuentes como para que escribirlas a mano acabe cansando:
<?php
expect('[email protected]')->toBeEmail();
expect('01ARZ3NDEKTSV4RRFFQ69G5FAV')->toBeUlid();
expect('192.168.1.1')->toBeIpAddress();
expect('00:1a:2b:3c:4d:5e')->toBeMacAddress();
expect('example.com')->toBeHostname();
expect('example.co.uk')->toBeDomain();
expect('Zm9vYmFy')->toBeBase64();
expect('deadbeef')->toBeHexadecimal();Todas se pueden negar con not.
Qué haría yo primero
Si vienes de Pest 4, ya estás en PHP 8.4 y en Laravel 13, este orden funciona bien:
Subir la versión en
composer.jsony comprobar que la suite pasa igualInstalar PCOV si no lo tienes y probar
--tiaen local unos días, solo en localMeter el plugin de PHPStan, que es el de menos fricción y el que más deuda descubre
Dejar Rector y el sharding para cuando lo anterior esté asentado
Los evals y el plugin de agentes esperan a que tengas algo que evaluar. Si no estás construyendo sobre modelos, no hay prisa.
Puntos clave
Pest 5 requiere PHP 8.4 y PHPUnit 13, y el plugin de Laravel exige Laravel 13.23 o superior
El motor Tia se activa con
--tia, necesita PCOV o Xdebug y está pensado para localLos tests reproducidos desde caché conservan la cobertura exacta
El plugin Agent da a los agentes de programación un comando para verificar cambios dentro de la suite real
Los evals combinan comprobaciones deterministas y scorers con IA, y se saltan salvo que pases
--evalsLos plugins de PHPStan, Rector, agentes y evals se instalan por separado como dependencias de desarrollo
Curso Laravel 12
Completo 2026
El único curso 100% actualizado que incluye Laravel 12, Livewire 3, Vue 3, React 19 e Inertia 2. Aprende con proyectos reales y las últimas funcionalidades.
star Incluido en cualquier suscripción