Capítulo 2.8: Pruebas de API
Tiempo de estudio: 1 hora
1. ¿Por qué son necesarias las pruebas?
Imagine que construyó una nave espacial. Antes de enviarla a Marte, realiza miles de verificaciones en la Tierra. Las pruebas en programación son lo mismo. Ellas:
- Dan confianza: Puede cambiar el código y, si las pruebas pasan, significa que no ha roto nada.
- Ahorran tiempo: En lugar de "hacer clic" manualmente en todo en Postman después de cada cambio, ejecuta un solo comando y este verifica todo por usted en segundos.
- Sirven como documentación: Las buenas pruebas muestran cómo debe funcionar su API.
2. Configuración del "Laboratorio" de pruebas
Laravel hace que la configuración de pruebas sea increíblemente sencilla. Por defecto, utiliza una configuración separada para no afectar su base de datos principal.
Base de datos para pruebas:
Por defecto, Laravel utiliza una base de datos en memoria (:memory:
). Este es el método más rápido, ya que no es necesario escribir nada en el disco. La base de datos se crea antes de las pruebas y se destruye después de ellas. ¡Ni siquiera necesitamos configurar nada para esto!
Creación de archivo de prueba: Creemos un archivo especial para las pruebas relacionadas con los planetas.
Este comando creará el archivo tests/Feature/PlanetApiTest.php
. La palabra Feature
significa que probaremos la funcionalidad en general (por ejemplo, "¿puede el usuario crear un planeta?"), y no una pequeña clase individual.
3. Anatomía de un test: Preparación, Acción, Verificación
Abra tests/Feature/PlanetApiTest.php
. Dentro escribiremos nuestra primera prueba. Una buena prueba siempre consta de tres partes (Arrange, Act, Assert).
<?php
namespace Tests\Feature;
use App\Models\Planet; // ¡No olvide importar el modelo!
use Illuminate\Foundation\Testing\RefreshDatabase; // ¡Herramienta esencial!
use Tests\TestCase;
class PlanetApiTest extends TestCase
{
// Este trait "mágicamente" limpia y recrea
// nuestra base de datos de prueba antes de cada test.
// Esto garantiza que los tests no se afecten entre sí.
use RefreshDatabase;
/**
* Test: el endpoint para obtener la lista de planetas funciona correctamente.
* ¡Los nombres de los tests deben ser significativos!
*/
public function test_can_get_all_planets(): void
{
// 1. PREPARACIÓN (Arrange)
// Creamos 3 planetas falsos en nuestra base de datos de prueba
// usando la factoría que creamos anteriormente.
Planet::factory()->count(3)->create();
// 2. ACCIÓN (Act)
// Simulamos una solicitud GET real a nuestra API.
$response = $this->getJson('/api/planets');
// 3. VERIFICACIÓN (Assert)
// Verificamos que todo salió como se esperaba.
$response->assertStatus(200); // Esperamos que el servidor haya respondido "200 OK"
$response->assertJsonCount(3); // Esperamos que haya exactamente 3 planetas en la respuesta
}
}
use RefreshDatabase
: Este trait es su mejor amigo. Garantiza que cada test comience con una "pizarra limpia", con una base de datos vacía.Planet::factory()
: Las factorías son ideales para crear datos de prueba.$this->getJson()
: Este es un método especial de Laravel para enviar solicitudes API dentro de los tests.assert...()
: Estas son "afirmaciones" o "verificaciones". Si al menos una de ellas no se cumple, el test fallará.
4. Pruebas de operaciones básicas (CRUD)
Escribamos tests para la creación, actualización y eliminación de planetas.
A. Test de creación de un planeta (POST)
<?php
public function test_can_create_a_planet(): void
{
// 1. Preparación: preparamos los datos para el nuevo planeta
$planetData = [
'name' => 'Kepler-186f',
'description' => 'La primera exoplaneta del tamaño de la Tierra en la zona habitable.',
'size_km' => 14000,
'solar_system' => 'Kepler-186'
];
// 2. Acción: enviamos una solicitud POST con los datos
$response = $this->postJson('/api/planets', $planetData);
// 3. Verificación
$response->assertStatus(201); // Esperamos el estado "201 Created"
$response->assertJsonFragment(['name' => 'Kepler-186f']); // Verificamos que el nombre creado esté en la respuesta
// La verificación más importante: ¿realmente los datos llegaron a la base de datos?
$this->assertDatabaseHas('planets', [
'name' => 'Kepler-186f'
]);
}
B. Test de eliminación de un planeta (DELETE)
<?php
public function test_can_delete_a_planet(): void
{
// 1. Preparación: creamos el planeta que vamos a eliminar
$planet = Planet::factory()->create();
// 2. Acción: enviamos una solicitud DELETE
$response = $this->deleteJson("/api/planets/{$planet->id}");
// 3. Verificación
$response->assertStatus(204); // Esperamos "204 No Content" - eliminación exitosa
// Verificamos que el registro realmente haya desaparecido de la base de datos
$this->assertDatabaseMissing('planets', [
'id' => $planet->id
]);
}
5. Pruebas de escenarios "malos"
Probar casos exitosos es bueno. ¡Pero es aún más importante probar los errores!
A. Test de error de validación
<?php
public function test_creation_fails_with_invalid_data(): void
{
// 2. Acción: enviamos datos intencionadamente incorrectos
$response = $this->postJson('/api/planets', ['name' => '']); // Nombre vacío
// 3. Verificación
$response->assertStatus(422); // Esperamos "422 Unprocessable Entity"
$response->assertJsonValidationErrors('name'); // Esperamos que el error esté específicamente en el campo 'name'
}
B. Test de "no encontrado" (404)
<?php
public function test_returns_404_for_non_existent_planet(): void
{
// 2. Acción: solicitamos un planeta con un ID inexistente
$response = $this->getJson('/api/planets/99999');
// 3. Verificación
$response->assertStatus(404); // Esperamos "404 Not Found"
}
6. Ejecución de tests
Ahora que los tests están escritos, ejecutarlos es muy sencillo. Ejecute en la terminal:
Laravel encontrará todos sus tests y los ejecutará uno por uno. Si todo sale bien, verá una salida verde. Si algún test falla, verá una salida roja con una descripción detallada del error, lo que le permitirá corregirlo rápidamente.
Para ejecutar solo un archivo específico:
8. Cobertura de código (Code Coverage)
Paso 1: Instalación de Xdebug
Para recopilar información sobre la cobertura del código se requiere la extensión de PHP — Xdebug.
Envíe su
php -i
al wizard y siga las instrucciones.
Paso 2: Configuración de phpunit.xml
<phpunit ... >
<coverage processUncoveredFiles="true">
<include>
<directory suffix=".php">./app</directory>
</include>
</coverage>
</phpunit>
Paso 3: Ejecución con informe
Informe: Abracoverage/index.html
en el navegador
9. Integración con Postman
Automatización a través de Newman:
- Exporte la colección de Postman a
tests/Postman/SpaceApi.postman_collection.json
- Instale Newman:
- Agregue el script a
composer.json
: - Ejecución:
Cuestionario para afianzar
🚀 Resumen del capítulo:
¡Has completado el ciclo completo de pruebas previas al vuelo! Ahora tu API:
- ✅ Configurar el entorno de prueba sin esfuerzo adicional
- 🛡️ Escribir pruebas siguiendo el principio "Preparación-Acción-Verificación".
- 📊 Probar tanto escenarios exitosos (CRUD) como errores (validación, 404).
- 🔁 Ejecutar pruebas con un solo comando y tener confianza en tu código.
¡La nave espacial está lista para el lanzamiento! Has completado la sección sobre la creación de API en Laravel.
📌 Verificación final:
- Ejecuta
php artisan test
- Asegúrate de que todas las pruebas pasen (¡luz verde!)
- Revisa el informe de cobertura
⚠️ Si las pruebas fallan:
- Verifica el funcionamiento de la API a través de Postman
- Asegúrate de que la base de datos de prueba esté configurada
- Usa
dd($response->content())
para depurar
¡Felicidades por completar el Capítulo 2! No solo has creado una API, has creado una "nave espacial" fiable y probada, lista para futuras misiones.
🌌 Próximos pasos:
- Configuración de autenticación (Sanctum)
- Documentación de la API con Swagger
- Despliegue en el servidor (Forge, VPS)
- Escritura del frontend en Vue/React
¡Éxito en el lanzamiento de tu misión espacial! En el próximo capítulo, veremos la creación de una API desde cero 🚀