El componente de pruebas de Laravel nos ofrece un conjunto de herramientas para el mejor desarrollo de nuestras pruebas de integración y unitarias. Una de ellas son los traits con los cuales podemos incluir algunos métodos a nuestras clases que nos facilitan el trabajo, tales como los relacionados con el manejo de las migraciones de la base de datos de pruebas, así como el control de la ejecución de middleware y eventos. En este tutorial conoceremos cuáles traits tenemos disponibles y aprenderemos a usarlos.

Al trabajar con bases de datos en el entorno de pruebas es conveniente reestablecer el estado de las tablas de la base de datos después de la ejecución de una prueba para evitar que los datos agregados interfieran en las próximas pruebas a ejecutarse. En este caso, Laravel nos proporciona dos mecanismos a través de los siguientes traits:

DatabaseMigrations

Con este trait, Laravel ejecuta automáticamente las migraciones antes de iniciar una prueba y realiza un rollback al terminar de ejecutar la prueba y vuelve a migrar antes de la próxima.  Este trait se encuentra en Illuminate/Foundation/Testing/DatabaseMigrations.php y se usa de la siguiente manera:

<?php

use Illuminate\Foundation\Testing\DatabaseMigrations;

class ExampleTest extends TestCase
{
    use DatabaseMigrations;
    
    // functions
}

DatabaseTransactions

Este trait es la otra alternativa que nos ofrece Laravel; se diferencia de DatabaseMigrations porque hace uso de transacciones para agrupar los cambios en la base de datos por cada prueba de la aplicación en una sola transacción. Para ello, primero debes asegurarte de ejecutar las migraciones para tu base de datos de prueba (ejemplo: php artisan migrate –database=tests). A partir de allí, al ejecutar una prueba,Laravel inicia una transacción, luego realiza todas las acciones de la prueba relacionadas con la base de datos y al terminar se hace rollback a la transacción, por tanto, la base de datos quedará en el mismo estado en el que se encontraba antes de comenzar la prueba. Este trait está disponible en  Illuminate/Foundation/Testing/DatabaseMigrations.php  y se usa así:

<?php

use Illuminate\Foundation\Testing\DatabaseTransactions;

class ExampleTest extends TestCase
{
    use DatabaseTransactions;

    // functions
}

Recuerda que debes configurar el entorno de desarrollo, creando una base de datos exclusiva para las pruebas y así no interferir ni alterar la base de datos de desarrollo o producción.

.

Advertencia: No incluyas DatabaseMigrations y DatabaseTransactions al mismo tiempo. Usa un trait o el otro para tus pruebas.

Por otro lado, es posible que en algunas ocasiones desees evaluar el correcto funcionamiento de alguna ruta o controlador sin la influencia de los middleware que estén relacionados con ellos. Como por ejemplo, cuando se evalúa una ruta tipo POST pero que no nos interesa probar el CSRF (Cross-site request forgery). Para estos casos se usa el trait WithoutMiddleware.

WithoutMiddleware

Este trait desactiva todos los middleware existentes en la aplicación mientras se estén ejecutando las pruebas, lo podemos utilizar de la siguiente manera:

<?php

use Illuminate\Foundation\Testing\WithoutMiddleware;

class ExampleTest extends TestCase
{
    use WithoutMiddleware;

    // functions
}

o también si solo lo que se quiere es aplicar a un método en específico de una prueba, puedes llamar al método withoutMiddleware() dentro de dicho método:

<?php

class ExampleTest extends TestCase
{
    /**
     * A basic functional test example.
     *
     * @return void
     */
    public function testBasicExample()
    {
        $this->withoutMiddleware();

        $this->visit('/')
             ->see('Laravel 5');
    }
}

WithoutEvents

Similar a lo anterior, si mientras se están ejecutando las pruebas no queremos que se disparen los eventos que se relacionan con las acciones evaluadas por las pruebas, entonces podemos hacer uso del trait WithoutEvents así:

<?php

use Illuminate\Foundation\Testing\WithoutEvents;

class ExampleTest extends TestCase
{
    use WithoutEvents;

    // functions
}

Como tip adicional, si lo que quieres es probar si un evento en particular fue disparado, puedes usar los métodos  expectsEventsdoesntExpectEvents (éste último método está disponible a partir de Laravel 5.2). Por ejemplo:

<?php

class ExampleTest extends TestCase
{
    public function testPodcastPurchase()
    {
        $this->expectsEvents(App\Events\PodcastWasPurchased::class);

        $this->doesntExpectEvents(App\Events\PaymentWasDeclined::class);

        // Test purchasing podcast...
    }
}

Asimismo, si queremos evitar que se ejecuten todos los eventos en un método de una prueba, usa el método withoutEvents():

<?php

class ExampleTest extends TestCase
{
    public function testUserRegistration()
    {
        $this->withoutEvents();

        // Test user registration code...
    }
}

Todos estos traits nos permiten el desarrollo de pruebas de forma más eficiente, adaptando nuestras pruebas y manteniendo bajo control las migraciones, los middleware y los eventos, así que no dudes en utilizarlos.

¿Quieres aprender a desarrollar usando pruebas? En Styde.Net tenemos varios cursos con partes dedicadas exclusivamente al desarrollo de aplicaciones con Laravel usando TDD: en el Curso de Laravel 5.1 aprenderás a a utilizar el componente de pruebas de integración de Laravel y luego con el curso Crea una aplicación con Laravel 5 podrás practicar realizando los ejercicios propuestos y comparando tus respuestas con las soluciones.

Espero que este tutorial te sea útil y nos ayudes, compartiéndolo en las redes sociales.

Material relacionado

Únete a nuestra comunidad en Discord y comparte con los usuarios y autores de Styde, 100% gratis.

Únete hoy

Regístrate hoy en Styde y obtén acceso a todo nuestro contenido.

Lección anterior Grupos de rutas en Laravel 5.* Lección siguiente Claves foráneas e integridad referencial de datos en Laravel