Você está na página 1de 3

Otimização do processo de execução de testes automáticos

Autor: Telmo Pimentel Mota


Área temática: Engenharia de Software
Público: Desenvolvedores
Nível: Intermediário
Produzido em: Junho de 2023

Introdução

Um projeto com execução automática de testes (ex. a cada novo código submetido a um
servidor) pode sofrer com a demora na execução e análise de resultados desses testes. O
ideal é que o tempo para cada rodada de execução e análise fique entre cinco e dez
minutos [1].
Vamos apresentar como foi feita a redução de trinta/quarenta para dez/vinte minutos
usando o agrupamento e execução paralela de testes.

Contexto

Os projetos onde aplicamos os procedimentos descritos a seguir são de serviços escritos na


linguagem PHP [2] usando Symfony [3]. Os testes foram escritos para PHPUnit [4] e análise
feita com SonarQube [5]. A execução automática acontece pela integração do git [6] com
Jenkins [7] através de eventos de mudança no repositório como push de commits em pull
requests e merges em branches principais.
A estratégia de evolução do código usava diferentes linhas de desenvolvimento e quando
uma atividade estava pronta criava-se um Pull Request para a linha principal. Um resumo
do resultado da análise pode ser vista na interface do Github Enterprise [8] e, dependendo
da qualidade identificada, a integração do código novo era bloqueada.

Desenvolvimento

Inicialmente identificamos quais são os testes mais lentos. Para isso adicionamos
johnkary/phpunit-speedtrap [9] na dependência de desenvolvimento da aplicação e
adicionamos o seguinte trecho ao arquivo phpunit.xml.dist.

<listeners>
<listener class="JohnKary\PHPUnit\Listener\SpeedTrapListener">
<arguments>
<array>
<element key="slowThreshold">
<integer>500</integer>
</element>
<element key="reportLength">
<integer>500</integer>
</element>
</array>
</arguments>
</listener>
</listeners>
O parâmetros são:
● slowThreshold: número de milissegundos para um teste ser considerado lento
● reportLength: número de testes lentos a serem incluídos no relatório

Em seguida, separamos os testes em diferentes grupos, de forma que a soma dos tempos
de execução de cada grupo não fosse superior a dez minutos. A opção escolhida foi o uso
de comentários de classe no estilo do phpDocumentor [10] com @group.

<?php
namespace MyApp\Tests;
use PHPUnit\Framework\TestCase;
/**
* @group g1
*/
class MyTest extends TestCase
{
// ...
}

E na execução dos testes usamos o parâmetro --group.

bin/phpunit --group g1

A efetiva execução dos testes em paralelo foi conseguida usando uma lista de estágios de
execução e a diretiva parallel [11] no Jenkinsfile. Onde cada estágio guarda os logs dos
testes usando a diretiva stash e o nome do grupo.

#!groovy
def groups = ['g1', 'g2']
def stages = [:]
groups.each { group ->
stages["Backend: ${group}"] = {
stage("Tests ${group}") {
// phpunit execution with:
// --group ${group}
// --coverage-php build-logs/clover/${group}.cov
// --log-junit build-logs/junit/${group}.xml
stash includes: 'build-logs/', name: group
}
}
}
parallel stages

Na sequência é necessário unificar os relatórios de teste e de cobertura para que sejam


analisados como se a execução dos testes tivesse ocorrido sequencialmente. Para isso
usamos phpjunitmerge [12] e phpcov [13].

groups.each { unstash it }
mkdir -p coverage
bin/phpjunitmerge build-logs/junit coverage/junit.xml
bin/phpcov merge --clover coverage/clover.xml build-logs/clover

Tendo no arquivo sonar-project.properties as seguintes linhas

sonar.php.tests.reportPath=coverage/junit.xml
sonar.php.coverage.reportPaths=coverage/clover.xml

Podemos executar o sonar-scanner [14] para realizar a análise e enviar para o serviço
SonarQube, de forma a disponibilizar um relatório que apresenta os pontos de cobertura de
código que devem ser melhorados.

Conclusão

Usando ferramentas e funcionalidades já disponíveis foi possível reduzir o tempo total de


execução e análise de testes para um valor mais aceitável.

Referências

[1] Best Practice 6 – Basic Builds are Fast (5 – 10 minutes)


https://codefresh.io/blog/enterprise-ci-cd-best-practices-part-1/
[2] PHP
https://www.php.net/
[3] Symfony
https://symfony.com/
[4] PHPUnit
https://phpunit.de/
[5] SonarQube
https://docs.sonarqube.org/latest/
[6] Git
https://git-scm.com/
[7] Jenkins
https://www.jenkins.io/
[8] Github Enterprise
https://github.com/enterprise
[9] phpunit-speedtrap
https://github.com/johnkary/phpunit-speedtrap
[10] phpDocumentor
https://phpdoc.org/
[11] Jenkins pipeline parallel directive
https://www.jenkins.io/doc/book/pipeline/syntax/#parallel
[12] phpjunitmerge
https://github.com/andreaskweber/php-junit-merge
[13] phpcov
https://github.com/sebastianbergmann/phpcov
[14] sonar-scanner
https://docs.sonarqube.org/latest/analyzing-source-code/scanners/sonarscanner/

Você também pode gostar