Meu nome é Elton Minetto

Gerando code coverage com PHPUnit e phpdbg

Em um post anterior eu mostrei alguns truques para identificar testes que estão demorando muito para serem executados. Neste texto vou mostrar uma forma de melhorar a performance da geração do relatório de cobertura de códigos usando o PHPUnit.

É possível incluir configurações no arquivo phpunit.xml para que sejam gerados relatórios relativos aos testes que estão sendo executados. Por exemplo:


<logging>
    <log type="coverage-clover" target="tests/_reports/logs/clover.xml"/>
    <log type="coverage-html" target="tests/_reports/coverage" charset="UTF-8" yui="true" highlight="true" lowUpperBound="35" highLowerBound="70" />
    <log type="testdox-text" target="tests/_reports/testdox/executed.txt"/>
</logging>

Desta forma será criado o diretório tests/_reports com uma série de informações úteis. No diretório coverage-html podemos ver detalhes da cobertura de testes dos códigos, facilitando a análise. O arquivo clover.xml é uma versão desta mesma informação para ser processada por serviços como Jenkins, CodeCov, Coveralls, Codacy, etc, para automatizarmos alertas e scripts.

Para estas informações serem geradas além de alterarmos o phpunit.xml é necessário que instalemos a extensão XDebug. O problema é que ao fazermos isso temos uma queda considerável de performance. Confira o resultado da execução dos testes sem a geração dos relatórios:

eminetto@MacBook-Air (master) ~/Documents/Projects/planrockr/planrockr-backend: ./vendor/bin/phpunit 
PHPUnit 4.8.26 by Sebastian Bergmann and contributors.
Warning:	The Xdebug extension is not loaded
		No code coverage will be generated.

...............................................................  63 / 173 ( 36%)
............................................................... 126 / 173 ( 72%)
...............................................

Time: 1.08 minutes, Memory: 120.00MB

OK (173 tests, 682 assertions)

Habilitando o XDebug e rodando novamente teremos uma surpresa:

eminetto@MacBook-Air (master *) ~/Documents/Projects/planrockr/planrockr-backend: ./vendor/bin/phpunit 
PHPUnit 4.8.26 by Sebastian Bergmann and contributors.

...............................................................  63 / 173 ( 36%)
............................................................... 126 / 173 ( 72%)
...............................................

Time: 22.26 minutes, Memory: 128.00MB

OK (173 tests, 682 assertions)

Generating code coverage report in Clover XML format ... done

Generating code coverage report in HTML format ... done

O tempo de execução pulou de 1.08 para 22.26 minutos!

Depois de algumas pesquisas pela internet cheguei a este post e resolvi testar o phpdbg.

Como estou usando o MacOS X para este teste eu executei os comandos abaixo para instalar todas as dependências que eu necessito.

brew install php70 --with-phpdbg
brew install php70-apcu
brew install php70-imagick
brew install php70-intl
brew install php70-mcrypt
brew install --HEAD homebrew/php/php70-memcached
brew install php70-mongodb
brew install php70-pdo-pgsql
brew install php70-xdebug

A diferença principal é o parâmetro –with-phpdbg usando na instalação do php7.

Seguindo este post do Sebastian Bergmann, criador do PHPUnit eu cheguei a sintaxe para rodar o teste novamente:

eminetto@MacBook-Air (master *) ~/Documents/Projects/planrockr/planrockr-backend: phpdbg -qrr ./vendor/bin/phpunit 
PHPUnit 4.8.26 by Sebastian Bergmann and contributors.

...............................................................  63 / 173 ( 36%)
............................................................... 126 / 173 ( 72%)
...............................................

Time: 1.59 minutes, Memory: 278.00MB

OK (173 tests, 682 assertions)

Generating code coverage report in Clover XML format ... done

Generating code coverage report in HTML format ... done

1.59 min é um tempo bem melhor do que os 22.26 usados pelo XDebug.

Na empolgação eu comentei isso no Twitter, antes mesmo de escrever este post:

twitter

Se você observar, quem respondeu foi ninguém menos do que o criador do XDebug! Levando isso em conta fiz a comparação entre os resultados gerados pelo XDebug e o phpdbg.

Abaixo a comparação do coverage-html gerado pelo XDebug (na esquerda) e o phpdbg (na direita da imagem).

coverage-html

Usei a ferramenta CodeCov para processar o arquivo clover.xml e o resultado também foi ligeiramente diferente:

CodeCovCloverPHPDBG.png

CodeCovXdebug.png

Segundo o relatório gerado pelo phpdbg o Planrockr está com 66,05 % de cobertura de códigos. Já o XDebug apresenta o resultado de 65,92 %.

Algumas conclusões que posso tirar deste pequeno teste:

  • O XDebug é uma ferramenta incrível e faz muito mais do que gerar cobertura de código, por isso não estou aqui dizendo que deveríamos parar de usá-la. Aqui estou apenas comparando um dos seus recursos
  • Eu estou comparando o resultado “de fábrica”, sem fazer ajustes em configurações do XDebug ou do phpdbg, por isso resultados diferentes podem acontecer em outros cenários
  • Apesar da diferença de resultados entre os dois relatórios a diferença de performance compensa o uso do phpdbg no meu caso.

Vou seguir usando o phpdbg por mais tempo e se algum novo resultado aparecer nas próximas semanas eu atualizo este post, ou gero outro relatando o aprendizado.

E se eu estou errado em minhas conclusões por favor me avisem que terei o maior prazer em me retratar :)