Nuevo en Symfony 3.4: mejores indicadores sobre cobertura de código

La "cobertura de código" ("code coverage" en inglés) es un indicador que describe qué porcentaje de código de la aplicación está testeado. En teoría, una cobertura alta indica que el código está más testeado y por tanto, seguramente contiene menos errores. PHPUnit incluye varias utilidades para calcular este indicador, pero no son muy precisas.

Considera este ejemplo sencillo:

class Bar
{
    public function barMethod() { return 'bar'; }
}
 
class Foo
{
    private $bar;
 
    public function __construct(Bar $bar)
    {
        $this->bar = $bar;
    }
 
    public function fooMethod()
    {
        $this->bar->barMethod();
 
        return 'bar';
    }
}

Si tienes un test como este:

class FooTest extends PHPUnit\Framework\TestCase
{
    public function test()
    {
        $bar = new Bar();
        $foo = new Foo($bar);
 
        $this->assertSame('bar', $foo->fooMethod());
    }
}

PHPUnit considera que una línea ha sido testeada tan pronto como se ejecute en cualquier test. Como el método FooTest::test() ejecuta todas las líneas de código de las clases Foo y Bar, la cobertura de código calculada por PHPUnit será del 100%. Pero esto no es verdad, ya que la clase Bar no ha sido testeada de verdad.

La solución consiste en añadir la anotación @covers de PHPUnit a cada test para indicar qué clase están testeando. El problema es que hacer esto es muy aburrido y difícil de mantener. Así que en Symfony 3.4 hemos añadido un nuevo CoverageListener en el componente PHPUnit Bridge para generar mejores indicadores de cobertura de código.

El único cambio que tienes que hacer en tu aplicación es registrar CoverageListener como listener de PHPUnit en el archivo de configuración phpunit.xml:

<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:noNamespaceSchemaLocation="http://schema.phpunit.de/6.0/phpunit.xsd"
>
    <!-- ... -->
 
    <listeners>
        <listener class="Symfony\Bridge\PhpUnit\CoverageListener" />
    </listeners>
</phpunit>

Este listener hace la siguiente comprobación antes de cada test:

  1. Si la clase incluye la anotación @covers, no hace nada.
  2. Si no existe la anotación @covers, busca el código testeado por este test y añade automáticamente esa anotación.

La lógica que se usa para buscar el código testeado es la misma que recomienda Symfony al crear los tests: un test utiliza la misma estructura de directorios que el código testeado y añade el sufijo Test al nombre de la clase. Así por ejemplo, si la clase del test es My\Namespace\Tests\FooTest, entonces la clase asociada que se busca es My\Namespace\Foo.

Como siempre, en Symfony puedes adaptar todo a tus necesidades, así que si esta lógica te parece demasiado simple o no funciona en tu aplicación, puedes utilizar tu propio solver definiéndolo como argumento del listener:

<listeners>
    <listener class="Symfony\Bridge\PhpUnit\CoverageListener">
        <arguments>
            <string>App\Test\CoverageSolver::solve</string>
        </arguments>
    </listener>
</listeners>

Esta funcionalidad fue contribuida por Grégoire Pineau en el pull request #23149.

Fuente: New in Symfony 3.4: Better code coverage reports

Comentarios

Publicada el

28 de septiembre de 2017

Etiquetas

Proyectos Symfony destacados

La plataforma de eCommerce 100% Symfony que rivaliza con Magento y PrestaShop. Ver más

Síguenos en @symfony_es para acceder a las últimas noticias.