Ir al contenido principal
Laravel, shipping fast.
Capitulo 8 · Pruebas y calidad

La prueba que lo habria atrapado

Julian Beaujardin

He visto a un servicio hoja cambiar de forma sin avisar a nadie. Ni con maldad ni con descuido: simplemente un campo que siempre estaba presente empezó a llegar como null, o directamente ausente, porque alguna migración aguas arriba decidió que una lista vacía no merecía serializarse. Nada en el contrato decía que no pudiera pasar. Nada en la mayoría de las suites lo comprueba tampoco, porque escribir la prueba del camino feliz es fácil y escribir la de «¿y si el campo simplemente no está?» exige imaginar el fallo antes de que ocurra.

// tests/Feature/LicenseControllerTest.php
test('defaults domains to an empty array when Statamic omits it', function () {
    Http::swap(new Factory);
    Http::fake(fn () => Http::response(['data' => [
        ['key' => 'k1', 'name' => 'No Domains License', 'created_at' => '2026-01-28T10:30:00Z'],
    ]], 200));

    $response = getJson('/api/v1/licenses', [
        'Authorization' => "Bearer {$this->token->token}",
    ]);

    $response->assertStatus(Response::HTTP_OK);
    expect($response->json('items.0.domains'))->toBe([]);
});

Esta prueba no simula la lista de dominios: la elimina por completo de la respuesta simulada y comprueba que la API no revienta ni filtra un null a un campo que quien consume espera que siempre sea un array. Va emparejada con el mapper que tomó la decisión:

// app/Http/Mappers/LicenseDTOMapper.php
// A license with no domains is valid; tolerate an absent/non-array field.
/** @var array<string> $domains */
$domains = is_array($license['domains'] ?? null)
    ? array_values($license['domains'])
    : [];

Ese ternario de una línea es el arreglo completo de una clase de fallo que si no aparecería como un TypeError en producción el día que un servicio hoja cambie de forma. La prueba es lo que lo convierte en una decisión en lugar de en un accidente, escrita una vez y reverificada en cada cambio futuro del mapper. Ese es todo el argumento a favor de probar el fallo explícitamente: no que atrapa el fallo de hoy, sino que atrapa la versión del fallo de hoy que aún no ha ocurrido.

Lista de comprobacion

Antes de escribir la prueba:

  • [X] Sabe qué ve quien consume: código de estado, forma de la respuesta, efecto secundario
  • [X] Decide si esto es terreno de prueba de integración o unitaria (casi siempre es de integración)

Mientras la escribes:

  • [X] Simula cada llamada externa; nunca dejes que una prueba dependa del tiempo de actividad de un servicio hoja
  • [X] Usa estados de factory para nombrar la intención
  • [X] Escribe el caso de fallo junto al de éxito, no «algún día»
  • [X] Pon a cero todo lo que duerma en producción

Antes de publicarla:

  • [X] composer test pasa
  • [X] composer check (PHPStan nivel 9) está limpio
  • [X] Los presets de arch() y tus reglas de arquitectura siguen sosteniéndose

Las pruebas no te frenan. Lo que te frena es una suite que te da miedo ejecutar. Escribe las que atraparían el fallo antes de que se publique, mantenlas rápidas para que nadie se las salte, y la confianza se compone igual que la arquitectura.