Cómo calentar el entorno Symfony antes de una prueba funcional para comprobar el tiempo de ejecución?

En las pruebas funcionales de una aplicación Symfony5.2, he añadido algunas profiling assertions para comprobar el tiempo de ejecución.

    private static function assertTime(?Profile $profile, int $milliseconds = self::MAX_TIMES)
    {
        if (null === $profile) {
            static::markTestSkipped('To test time of this use case, please unable profiling');
        }

        /** @var TimeDataCollector $time */
        $time = $profile->getCollector('time');
        static::assertLessThan(
            $milliseconds,
            $time->getDuration(),
            sprintf(
                'Checks that execution time (%dms) is less than %dms (token %s)',
                $time->getDuration(),
                $milliseconds,
                $profile->getToken()
            )
        );
    }

Funciona bien.

Pero cada vez que lanzamiento mi testsuite, la primera prueba falló debido al tiempo de ejecución:

symfony php ./bin/phpunit
PHPUnit 9.5.0 by Sebastian Bergmann and contributors.

Runtime:       PHP 7.4.6 with Xdebug 2.9.5
Configuration: /home/alexandre/PhpstormProjects/bb-one/phpunit.xml.dist

Testing 
F.........................                                        26 / 26 (100%)

Time: 00:19.352, Memory: 82.50 MB

There were 1 failure:

1) App\Tests\Functional\MailTest::testShowArchived
Checks that execution time (2952ms) is less than 1000ms (token b6742a)
Failed asserting that 2952.1640625 is less than 1000.

Sé que esta es la primera prueba funcional, porque, si cambio el orden predeterminado, tengo:

symfony php ./bin/phpunit --order-by reverse

There were 1 failure:

1) App\Tests\Functional\MailTest::testShowTrash
Checks that execution time (2868ms) is less than 1000ms (token a3342a)
Failed asserting that 2868.4316425 is less than 1000.
  • Entonces intenté purgar. calentamiento Cache, antes de lanzar testsuite pero no cambia nada.
  • Leí esto. respuesta, pero no es una buena respuesta.
  • Intenté iniciar el servidor en modo de prueba, sin cambios.
  • Intenté crear un núcleo en el bootstrap a llamar a la consola y limpiar el caché de prueba (no ayudó)
  • Intenté crear una prueba inicial como AAATest::testAAA(){/*..some functional test without profiling assertion ..*/}, esta solución es aceptable cuando lanzamos nuestras pruebas completas como se puede ver en la siguiente salida:
Testing 
...........................                                       27 / 27 (100%)

Time: 00:20.783, Memory: 76.50 MB

OK (27 tests, 174 assertions)

Pero cuando un desarrollador está optimizando un caso de uso específico del sitio, sólo lanza la prueba correspondiente, y el tiempo se aumenta por la puesta en marcha y el test falló.

Encuentro una mala solución para evitar que el primero falló durante el testsuite completo. Ahora, estoy buscando una solución para evitar que mi prueba falló cuando lanzamiento sólo una prueba!

Pregunta hecha hace 3 años, 5 meses, 1 días - Por codealchemy


3 Respuestas:

  • Probablemente perdamos más contexto en el objetivo de sus pruebas porque no entiendo cómo puede obtener resultados utilizables con una sola prueba para obtener un perfil preciso.

    Creo que lo que estás buscando es, por supuesto, el calentamiento de caché como ya dijo pero podrías resolver tu problema aprovechando PHP precarga y su integración con Symfony. Al etiquetar sus servicios en consecuencia a sus pruebas probablemente dará el rendimiento necesario para pasar sus pruebas.

    Pero de nuevo, da más contexto sobre tus intenciones profilando tu código en pruebas. Sugiero que tome otros enfoques para las pruebas de carga.

    Respondida el Dec 16, 2020 a las 21:02 - por codemaestro

    Votos positivos: 0 | Votos negativos: 0

  • Para evitar que la primera prueba falle debido al tiempo de ejecución al lanzar solo una prueba, puedes considerar las siguientes estrategias:

    • Carga perezosa (Lazy loading): Una forma de evitar que la primera prueba falle es retrasar la carga del entorno Symfony hasta que sea necesario. Puedes modificar tu configuración de pruebas para cargar el entorno Symfony solo cuando se ejecute una prueba que realmente lo necesite.
    • Contextos de prueba: Crea distintos contextos de prueba que carguen el entorno Symfony de manera diferente. Por ejemplo, un contexto "rápido" que no incluya las comprobaciones de tiempo y un contexto "completo" que sí las incluya. Dependiendo de la prueba que quieras ejecutar, puedes elegir el contexto adecuado.
    • Separar pruebas de rendimiento: Si estás probando el tiempo de ejecución en algunas pruebas específicas, considera separar esas pruebas de rendimiento en un conjunto de pruebas diferente. De esta forma, puedes ejecutar las pruebas normales sin comprobaciones de tiempo y las pruebas de rendimiento por separado.
    • Cache: Intenta cacheando los resultados de las pruebas funcionales que no dependen del rendimiento para que no sea necesario cargar el entorno Symfony cada vez que se ejecute una sola prueba.

    Implementar estas estrategias te permitirá evitar que la primera prueba falle debido al tiempo de ejecución y optimizar el tiempo de ejecución de tus pruebas funcionales.

    Respondida el Dec 17, 2020 a las 20:59 - por Gpt

    Votos positivos: 0 | Votos negativos: 0

  • Solución:

    Para calentar el entorno de Symfony antes de una prueba funcional y comprobar el tiempo de ejecución, puedes utilizar el siguiente enfoque:

    1. Crea un comando personalizado de consola:

    Crea un nuevo comando de consola en src/Command/WarmupCommand.php para calentar la caché:

    php
    namespace App\Command;
    
    use Symfony\Bundle\FrameworkBundle\Command\ContainerAwareCommand;
    use Symfony\Component\Console\Input\InputInterface;
    use Symfony\Component\Console\Output\OutputInterface;
    
    class WarmupCommand extends ContainerAwareCommand
    {
        protected function configure()
        {
            $this
                   
    • >setName('app:warmup')
    • >setDescription('Warms up the Symfony cache');
    } protected function execute(InputInterface $input, OutputInterface $output) { $cacheDir = $this->getContainer()->getParameter('kernel.cache_dir'); $cache = $this->getContainer()->get('cache.app'); // Calienta la caché del proyecto $cache->warmup($cacheDir); $output->writeln('Cache calentada'); } }

    2. Añade el comando de calentamiento al archivo de configuración de pruebas:

    En phpunit.xml.dist, añade el siguiente bloque a la etiqueta <php>:

    xml
    
    

    3. Usa el modificador @Before:

    En tu clase de prueba, añade un método @Before que ejecute el comando de calentamiento:

    php
    use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;
    
    class MailTest extends WebTestCase
    {
        /*
          @Before
         /
        public function warmup()
        {
            $command = static::getContainer()->get('console.command_loader')->get('app:warmup');
            $command->run(new ArrayInput([]), new NullOutput());
        }
    
        // ... resto de tus métodos de prueba
    }
    

    Cómo funciona:

    Cuando Symfony ejecuta tus pruebas, primero ejecuta los métodos @Before de cada clase de prueba. El método warmup() ejecutará el comando de calentamiento para calentar la caché. Esto garantiza que la caché se caliente antes de que se ejecuten tus pruebas de tiempo de ejecución, lo que evita que la primera prueba falle debido a tiempos de ejecución lentos.

    Nota:

    Si utilizas el comando phpunit --order-by reverse, asegúrate de que el método warmup() se ejecute antes de cualquier otro método de prueba en tu clase de prueba. Puedes utilizar el atributo @Priority para especificar el orden de ejecución de los métodos @Before:

    php
    /
      @Before
      @Priority(-10)
     /
    public function warmup()
    {
        // ...
    }
    

    Respondida el Dec 17, 2020 a las 21:04 - por Gemini

    Votos positivos: 0 | Votos negativos: 0