Tipos de test en laravel
Realizar test, es muy importante . Muchas veces pensamos que como no los necesitamos para que la apliación funcione lo dejamos para el final, o simplemente no lo hacemos (para ejemplo yo mismo 🥶 )
Laravel ya aporta una estructura de test, que podemos ver en la carpeta correspondiente.
En ella vemos que tenemos dos tipos de test:
Test de caracterÃsticas dónde se testean diferentes componentes interactuando entre ellos
Que testean métodos concretos del código
*El funcionamiento de los métodos creados es el muy parecido. Para esta api, vamos a realizar los test usando los FeatureText
Ejecutando los test en laravel
En el terminal escribimos
Vamos a crear métodos para validar cada uno de los 5 métodos que tenemos en el controlador
Un test es un método que nos va a permitir validar otro método
En el método del test, básicamente vamos a hacer 3 acciones
*Invocar al método que queremos testear pasándole los valores que consideremos
*Comprobar que lo que devuelve ese método que validamos es lo que esperamos que devuelva
*Informar de ello
Los test no son infalibles, es decir, nosotros validamos lo que consideramos, por ejemplo si valido un método de fecha, si le paso una fecha incorrecta, espero que me lo diga, y si es correcta igual, eso me permitirÃa validar el método.
Veamos cómo se realizan estas acciones
**1.- Creamos una clase para el test del api. **
El método de test, se espera que termine con la palabra Test. Creamos una clase llamada
BookApiTest para nuestro ejemplo
1
php artisan make:test BookApiTest
Empezamos validando el método
index para ello vamos a crear un método
Importante que el método empiece por la palabra test
1
2
3
public function test_can_get_all_books (): void{
}
Pero claro, necesitamos tener la base de datos poblada y comprobar que cuando consultamos obtenemos todos los registros
Pero no queremos tocar la base de datos original, si no que vamos a craar una base de datos para los test, para lo cual vamos a usar la clase (traid) RefreshDatabase que nos ofrece Laravel
Creamos una nueva base de datos (también podrÃamos usar sqlite en memoria)
Para configurar la base de datos de test, primero la creamos en nuestro gestor
creamos la base de datos api_test
Ahora lo configuramos en el fichero phpunit.xml
1
2
3
4
5
6
<php>
<env name= "APP_ENV" value= "testing" />
<env name= "BCRYPT_ROUNDS" value= "4" />
<env name= "CACHE_DRIVER" value= "array" />
<!-- <env name="DB_CONNECTION" value="sqlite"/> -->
<env name= "DB_DATABASE" value= "api_test" />
Para poblar la base de datos de pruebas, vamos a usar el factory que creamos cuando construimos el modelo
Una vez creado, lo invocamos desde el método credado
Vamos simplemente a crear un libro y visualizarlo
1
2
3
4
5
6
7
8
9
10
11
12
//En el factory
public function definition (): array {
return [
'titulo' =>fake()->sentence (),
];
}
//En el test
public function test_can_get_all_books (): void{
$book = Book::factory ()->create ();
dd($book );
}
Por ejemplo vamos a creaer 4 libros y verificamos que haya 4 libros
1
2
3
4
5
6
public function test_can_get_all_books (): void
{
$book = Book::factory ()->count (4 )->create ();
dd($book ->count ());
}
Ahora vamos a ver lo que retorno si hacemos una solicitud
get
1
2
3
4
5
public function test_can_get_all_books (): void
{
$book = Book::factory ()->count (4 )->create ();
$this ->get ("/api/books" )->dump ();
}
Ahora que vemos esto, se tratarÃa de verficar los libros que nos devuelve son los que hemos creado
Para ello vamos a hacer uns aserción y verficar que esto funciona.
para ello vamos a recoger la respuesta y vamos a comparar por ejemplo los tÃtulos de los dos primeros libros recibidos con los tÃtulos de los dos primeros libros creados.
1
2
3
4
5
6
7
8
9
10
11
12
13
public function test_can_get_all_books (): void
{
$book = Book::factory ()->count (4 )->create ();
$response = $this ->getJson (route("books.index" ));
$response ->assertJsonFragment ([
'titulo' =>$book [0 ]->titulo
])
->assertJsonFragment ([
'titulo' =>$book [1 ]->titulo
]);
}
Ejecutamos el test y vemos que funciona
Probar por ejemplo a modificar el método index y ver que no funciona, por ejemplo si solo retornamos un libre en lugar de todos , o no devolvemos nada …
**Verificar el método
show
1
2
3
4
5
6
7
8
9
10
11
12
/**
* @test
*/
public function can_get_one_book ():void{
$book =Book::factory ()->create ();
$response = $this ->getJson (route("books.index" ));
$response ->assertJsonFragment ([
'titulo' =>$book ->titulo
]);
}
* Observa que si ponemos la directiva **@test** ya no hay que hacer que el nombre del método empiece por la palabra **test**
Verificar el método store
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
/**
* @test
*/
public function can_crate_book ():void{
$this ->postJson (route('books.store' ),[
'titulo' =>"Mi libro de pruebas"
])->assertJsonFragment ([
'titulo' =>"Mi libro de pruebas"
]);
$this ->assertDatabaseHas ('books' ,
['titulo' =>"Mi libro de pruebas" ]
);
}
En este caso hacemos dos aserciones, podemos ver cómo tanto con solo una, como con dos, funciona correctamente
Vamos a ver cómo podemos también validar que si no le pasamos nada, nuestra aplicación esparemos que nos de un error. Por ejemplo si quitáramos la validación en el controlador,
1
2
3
4
public function can_crate_book ():void{
$this ->postJson (route('books.store' ),[])
->assertJsonValidationErrors ('titulo' );
/....
Actualizar un libro
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
/**
* @test
*/
public function can_update_book ():void{
$book =Book::factory ()->create ();
$this ->patch (route("books.update" ,$book ),[
'titulo' =>"Libro editado"
])->assertJsonFragment ([
'titulo' =>'Libro editado'
]);
//Verificamos también en la base de datos
$this ->assertDatabaseHas ('books' ,[
'titulo' =>"Libro editado"
]);
}
*Podemos (debemos) de verificar también la validación
1
2
3
//Validamos también la validación
$this ->patch (route("books.update" ,$book ),[])
->assertJsonValidationErrors ('titulo' );
Borrar un libro
*En este caso vamos a eliminar un libro y verificar que no existe
1
2
3
4
5
6
7
8
9
10
11
12
13
/**
* @test
*/
public function can_delete_book (): void
{
$book = Book::factory ()->create ();
//Validamos también la validación
$respuesta = $this ->deleteJson (route("books.destroy" , $book ), [])
->assertContent ("Se ha borrado " .$book ->titulo );
// ->assertNoContent();
}