https://d226lax1qjow5r.cloudfront.net/blog/blogposts/converting-your-test-suite-to-pest/shifting-to-pest.png

Conversión del conjunto de pruebas a PEST

Publicado el December 16, 2021

Tiempo de lectura: 10 minutos

Cambiar la forma en que escribo código a través de Test-Driven Development francamente cambió mis habilidades como programador. De repente podía escribir servicios y funcionalidades con confianza - es un misterio para mí por qué tantas empresas todavía "No tienen tiempo para hacer pruebas" durante mucho tiempo, PHPUnit ha sido la herramienta de-facto de elección cuando se escribe TDD PHP.

Recientemente ha surgido un nuevo proyecto que podría cambiar esta situación. Existe buena documentación y una comunidad de encuentros que se está construyendo a su alrededor y que se muestra como una opción atractiva para los desarrolladores. Me refiero, por supuesto, a PEST, así que pensé en darle una vuelta por nuestra cuenta. SDK PHP de Vonage.

La Suite Actual

Nuestro SDK PHP de Vonage ha recibido un mantenimiento exhaustivo a lo largo de los años y, como tal, contiene un conjunto de pruebas completo. Aunque su alcance no es de "nivel empresarial", no deja de ser un ejercicio útil para probar PEST.

La suite actual en esta rama tiene 831 pruebas aprobadas que ejecutan 4039 aserciones. Hay 9 pruebas omitidas y 15 incompletas. El tiempo total de ejecución es de 13:54 en PHP8.

Screenshot of total tests showing 9 skipped and 15 incomplete tests.Screenshot of total tests showing 9 skipped and 15 incomplete tests.

Para que conste, se ejecuta bastante decentemente y una de esas pruebas es en realidad una prueba de tiempo de espera que aumenta el tiempo. El objetivo aquí no es mejorar realmente el corredor, sino cambiarlo para ver qué pasa. Nuestro primer puerto de escala es instalar PEST y ejecutarlo. Una de las características más importantes de PEST es que es completamente compatible con PHPUnity por lo tanto se puede utilizar indistintamente de la sintaxis que se esté utilizando. Esto nos permite instalar PEST, ejecutarlo para ver los resultados y potencialmente probar e implementar el reciente pruebas paralelas de pruebas paralelas.

Para instalar PEST, ejecuto lo siguiente en la línea de comandos:

composer require pestphp/pest

Parece engañosamente fácil que un comando de Composer después, puedo ejecutar PEST. Vale la pena señalar, sin embargo, que este repositorio en el que se ejecutará ya tiene requisitos - uno de estos requisitos es una versión mínima de PHP de 7.3. PEST ya tiene una versión mínima requerida de PHP para ser 7.3 y superior, por lo que no hay retoques necesarios para ponerse al día.

Es hora de ejecutar PEST y ver qué pasa:

./vendor/bin/pest

Lo primero que notará es que PEST utiliza un formato de salida similar al de --testdox para formatear la salida de PHPUnit. Su salida es bastante agradable:

Test screenshot, showing a time of 13.21 seconds.Test screenshot, showing a time of 13.21 seconds.

Hmm, así que 13,28 segundos ¿eh? Bueno, en realidad es más rápido sólo con el corredor. ¿Y si intentamos usar la función paralela de PEST? Viene como un paquete separado, así que vamos a conseguirlo:

composer require pestphp/pest-plugin-parallel

Y ahora a ejecutarlo:

./vendor/bin/pest -parallel

Y... oh. Bueno, parece que nuestra suerte se ha acabado:

Screenshot of a PHP bug.Screenshot of a PHP bug.

Una rápida búsqueda en Google revela que tenemos un error en el propio PHP para esto, como se documenta en el registro de problemas de PHPUnit:

https://github.com/sebastianbergmann/phpunit/issues/4305

Supongo que es el precio que pagamos por estar un poco a la última.

Photo of frustrated person looking at their laptop screen.Photo of frustrated person looking at their laptop screen.

Sintaxis PHPUnit vs. PEST

He estado jugando con el ejecutor de pruebas, pero no he mostrado el código o explicado cuál es el propósito real de PEST.

Miembro del núcleo de Laravel Nuno Madro creó PEST como un nuevo marco de trabajo basado en la sintaxis de la plataforma Jest de Javascript. Está muy en consonancia con la tendencia actual de PHP (y especialmente Laravel) para pasar a más basado en el cierre, la sintaxis funcional similar a la forma en Javascript está escrito. Esto tiene sentido lógico entonces, que sus pruebas de PHP backend para su aplicación web de pila completa se escriben en una sintaxis similar a sus pruebas frontales. He aquí un ejemplo de "antes y después" del SDK PHP de Vonage:

class NumberTest extends VonageTestCase  
{  

 /**  
 * @var Number;  
 */
 protected $number;  
  
 public function setUp(): void  
 {  
	$this->number = new Number('14843331212');  
 }  
 
 public function testNumberConstructor(): void  
 {   
	$this->assertEquals('14843331212', $this->number->getNumber());  
 }

Estamos utilizando un par de patrones comunes aquí - el método mágico setUp() se ejecuta antes de que se ejecuten las pruebas, y luego usamos assertEquals() que es una clase de ayuda de PHPUnit TestCase (en nuestro ejemplo VonageTestCase extiende de ella más arriba).

Ahora, para mostrarle la misma prueba, pero escrita en sintaxis PEST:

use Vonage\Numbers\Number;  
  
beforeEach(function () {  
   $this->number = new Number();  
});  
  
test('number constructor', function () {  
   expect($this->number->getNumber())->toEqual('14843331212');  
});

Este es un buen ejemplo de donde el ecosistema PHP está, en general, mirando hacia Javascript para nuevas ideas - como se puede ver, la sintaxis PEST es muy similar a JEST. También muestra uno de los valores fundamentales de PEST, que es tener un encadenamiento de métodos más fluido en la API para escribir menos código, que es un enfoque muy similar a Laravel en filosofía. Ahora tenemos una orden superior beforeEach() con un cierre en su interior que se ejecutará antes de cada prueba, y ahora las clásicas estructuras de funciones PHP de PHPUnit se han sustituido por una sintaxis de estilo más funcional. Este ejemplo también muestra cómo la API de expectativas está diseñada para encadenar aserciones de una forma legible por humanos con nombres de métodos como expect(true)->toBe(value) o expect($variable)->toBeArray().

Vale, ¿entonces automatización?

Voy a ser honesto aquí, esto no salió como yo quería. Sin embargo, les mostraré por qué.

Me llamó la atención desde Twitter que en realidad podría ser posible utilizar una herramienta para convertir automáticamente su suite PHPUnit a PEST, independientemente de si el código está en Laravel o no. Así que me dirigí a Convertidor de PEST y un repositorio y una rama para probarlo. Cuando se ejecuta, Shift creará una nueva rama de la base que usted proporciona y crear paso lógico se compromete a moverse a través de la sintaxis. Una de las cosas que había que hacer primero era cambiar la carpeta test/ por tests/ para que el convertidor sepa dónde buscar sus pruebas.

Sin embargo, al ejecutar PEST después de la conversión:

Screenshot showing PestxceptionsestCaseClarrOrTrailNotFound.Screenshot showing Pest\Exceptions\TestCaseClarrOrTrailNotFound.

Hmm. Así que no ha sido un camino de rosas. Vale la pena señalar que no tenía ni idea de qué esperar por un par de razones:

  • El SDK PHP de Vonage es independiente del marco de trabajo

  • Depende del Prophesize biblioteca

  • Se utilizan varios rasgos de PHP que hacen que el conjunto de pruebas sea ligeramente más complejo

En lugar de utilizar la composición tradicional, PEST tiene un patrón de configuración diferente. PEST tiene un pest.php que permite especificar funciones de ayuda, rasgos y métodos comunes como RefreshDatabase. También puedes especificar a qué carpetas quieres que se apliquen las clases, como por ejemplo

uses(\VonageTest\HTTPTestTrait::class)->in('Secrets');

La razón por la que el convertidor PEST no puede resolver estos es una serie de casos extremos. Una cosa señalada por Laravel Shift's Jason McCreary en nuestras conversaciones de soporte es que algunas pruebas establecen un contenedor de Applications en $this->applo que entra en conflicto con la infraestructura de aplicaciones de Laravel (ya que no sabe si tienes una aplicación Laravel o no).

Conclusiones

OK, así que mientras que el convertidor de PEST encontró difícil automatizar mover las pruebas a través, me lleva a dos conclusiones:

  • Laravel Shift, los creadores del convertidor de plagas ya están mirando los casos de borde en nuestra biblioteca que he utilizado y trabajando en la forma de manejarlos, pero lo más importante

  • No ejecute el conversor si su conjunto de pruebas es complejo o está sobredimensionado.

Como con todo, existen riesgos al emprender una refactorización importante mediante la automatización. En nuestro caso, el riesgo era que estamos tratando con una biblioteca PHP sin marco. Sin embargo, Shift trabaja en la actualización a través de una rama de destino, a continuación, la creación de la rama de Shift fuera de él para minimizar el riesgo. Si no se ejecuta, ¡no la fusione! También tiene la opción de utilizar la herramienta Cambio humano que, inevitablemente, dará como resultado una suite totalmente convertida.

Lo que te aconsejo es que si tienes una aplicación Symfony o Laravel, este conversor está absolutamente diseñado pensando en estos casos, por lo que el Shift será bastante sólido.

¿Debería adoptar PEST? Como siempre, eso depende de usted. Si desea mantenerse a la vanguardia de las cosas que están cambiando en PHP, entonces esta es sin duda una opción atractiva. Tenga en cuenta, sin embargo, que la forma en que PEST estructura su sintaxis está naturalmente en línea con el enfoque de Laravel a los flujos de API, por lo que tiene el potencial de confundir a sus desarrolladores si utiliza algo más popular como Symfony, CakePHP o Drupal.

Compartir:

https://a.storyblok.com/f/270183/400x385/12b3020c69/james-seconde.png
James SecondePromotor senior de desarrollo PHP

Actor de formación con una disertación sobre la comedia, llegué al desarrollo de PHP a través de la escena de las reuniones. Puedes encontrarme hablando y escribiendo sobre tecnología, o tocando/comprando discos raros de mi colección de vinilos.