Volver al inicio

PHPUnit covers: navegación y cobertura de pruebas para desarrolladores

El artículo explica cómo usar anotaciones y atributos covers en PHPUnit para mejorar la navegación entre pruebas y código de la aplicación. Cubre enfoques para vincular pruebas a métodos, configuración de IDE y limitaciones de cobertura.

Mejorando las pruebas en PHP: guía sobre covers en PHPUnit
Advertisement 728x90

PHPUnit: Dominando Covers para Mejor Navegación y Cobertura en Pruebas

Probar controladores web en PHP suele generar líos de navegación entre las pruebas y el código de la app. Vamos a ver cómo las anotaciones y atributos @covers de PHPUnit resuelven esto, agilizando el desarrollo sin sacrificar la cobertura.

El Problema de Navegación entre Pruebas y Código

Al probar controladores mediante peticiones HTTP, no puedes invocar métodos directamente, lo que complica saltar de la prueba al código. Por ejemplo, una prueba para el endpoint /hello no hace referencia directa a GreetingController::hello(). Esto obliga a búsquedas manuales en el IDE, ralentizándote.

Aquí un ejemplo de controlador y prueba:

Google AdInline article slot
final class GreetingController extends AbstractController
{  
    #[Route('/hello')]
    public function hello(): Response
    {
        return new Response($this->generate("¡Hola!"));
    }
}
class GreetingControllerTest extends WebTestCase
{
    public function test_hello(): void
    {
        $content = get('/hello');
        assert_starts_with('¡Hola!', $content);
    }
}

Tres Formas de Vincular Pruebas con Código

Los desarrolladores usan varios trucos para mejorar la navegación.

1. Sintaxis Nativa con Reflexión

Cambia rutas de strings por llamadas a métodos vía reflexión, como request(GreetingController::hello(...)). Desventaja: Las pruebas pierden independencia del código de la app, pudiendo romperse con cambios.

Google AdInline article slot

2. Anotación @see

Usa PHPDoc para enlazar:

/**
 * @see \App\Controller\GreetingController::hello()
 */
public function test_hello(): void { ... }

Ventajas: Soporte del IDE. Desventajas: Requiere rutas completas de clases, etiqueta genérica sin manejo especial.

Google AdInline article slot

3. Covers Especializados de PHPUnit

Anotaciones o atributos diseñados para cobertura y navegación.

Usando Anotaciones Covers en PHPUnit

Antes de PHPUnit 12, @coversDefaultClass y @covers mandaban:

/**
 * @coversDefaultClass \App\Controller\GreetingController
 */
class GreetingControllerTest extends WebTestCase
{
    /**
     * @covers ::hello
     */
    public function test_hello(): void { ... }
}

Ventajas:

  • Soporte excelente en PhpStorm: autocompletado, navegación, detección de uso.
  • Plantillas personalizadas para generar pruebas.

Desventajas de plantillas en PhpStorm:

  • Limitadas a dos plantillas de PHPUnit.
  • Nombres confusos.
  • Fallos ocasionales en el generador.

Pasando a Atributos Covers en PHPUnit 12+

PHPUnit 12 eliminó las anotaciones por atributos, pero con trampa: solo aplican a clases, no a métodos.

Uso Básico:

#[CoversClass('App\Controller\GreetingController')]
class GreetingControllerTest extends WebTestCase
{
    public function test_hello(): void { ... }
}

Esto perjudica la precisión de navegación sin especificar métodos.

Especificando Métodos con CoversMethod:

#[CoversMethod('App\Controller\GreetingController', 'hello')]
#[CoversMethod('App\Controller\GreetingController', 'bye')]
class GreetingControllerTest extends WebTestCase
{
    public function test_hello(): void { ... }
    public function test_bye(): void { ... }
}

Desventaja: Atributos acumulados en pruebas con múltiples métodos.

Estrategia Ideal: Una Clase de Prueba por Método

Clases de prueba dedicadas por método simplifican todo:

#[CoversMethod('App\Controller\GreetingController', 'hello')]
class HelloTest extends WebTestCase
{
    public function test_hello(): void { ... }
    public function test_hello2(): void { ... }
}

Beneficios:

  • Menos carga mental.
  • No hace falta covers por método.
  • Promueve diseño limpio: un controlador, un endpoint.

Las plantillas de atributos funcionan como anotaciones, pero requieren ajustes manuales en CoversMethod tras generar.

Integración con IDE y Mejoras Futuras

PhpStorm ya maneja saltos de prueba a clase con Ctrl+Shift+T. Espera navegación a nivel de método pronto.

Lecciones Clave

  • Usa covers para potenciar navegación, pero ten en cuenta el impacto en cobertura.
  • Atributos de PHPUnit 12+ son solo para clases, así que adapta tus pruebas.
  • Ideal: Una clase de prueba por método para mantenimiento fácil.
  • Configura plantillas en IDE para covers automáticos.
  • Sigue las actualizaciones de PhpStorm para mejor soporte de atributos.

Límites de Cobertura: El Mayor Defecto de Covers

La función principal de Covers es acotar la cobertura a clases/métodos. CoversClass excluye código externo de informes —ideal para proyectos estrictos, pero la mayoría solo quiere detectar huecos.

Soluciones para desactivar:

  • Truco Excesivo: Scripts que eliminan etiquetas antes de ejecutar pruebas.
  • Solución Práctica: Parchea phpunit/php-code-coverage vía Composer.

Elige según necesidades del proyecto y preferencias del equipo.

— Editorial Team

Advertisement 728x90

Leer después