Introdução ao JaCoCo
1. Visão geral
*Cobertura de código* é uma métrica de software usada para medir quantas linhas de nosso código são executadas durante testes automatizados.
Neste artigo, examinaremos alguns aspectos práticos do uso do JaCoCo - um gerador de relatórios de cobertura de código para projetos Java.
*2. Configuração do Maven *
Para começar a operar com a JaCoCo, precisamos declarar este https://search.maven.org/classic/#search%7Cga%7C1%7Cg%3A%22org.jacoco%22%20AND%20a%3A% 22jacoco-maven-plugin% 22 [maven plugin] em nosso arquivo pom.xml:
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>0.7.7.201606060606</version>
<executions>
<execution>
<goals>
<goal>prepare-agent</goal>
</goals>
</execution>
<execution>
<id>report</id>
<phase>prepare-package</phase>
<goals>
<goal>report</goal>
</goals>
</execution>
</executions>
</plugin>
O link fornecido aqui anteriormente sempre o levará à versão mais recente do plug-in no repositório central do maven.
===* 3. Relatórios de cobertura de código *
Antes de começarmos a examinar os recursos de cobertura de código da JaCoCo, precisamos ter uma amostra de código. Aqui está uma função Java simples que verifica se uma string lê o mesmo para trás e para frente:
public boolean isPalindrome(String inputString) {
if (inputString.length() == 0) {
return true;
} else {
char firstChar = inputString.charAt(0);
char lastChar = inputString.charAt(inputString.length() - 1);
String mid = inputString.substring(1, inputString.length() - 1);
return (firstChar == lastChar) && isPalindrome(mid);
}
}
Tudo o que precisamos agora é de um teste* JUnit *simples:
@Test
public void whenEmptyString_thenAccept() {
Palindrome palindromeTester = new Palindrome();
assertTrue(palindromeTester.isPalindrome(""));
}
A execução do teste usando o JUnit colocará automaticamente em movimento o agente JaCoCo, portanto, ele criará um relatório de cobertura em* formato binário *no diretório de destino - target/jacoco.exec.
Obviamente, não podemos interpretar a saída sozinho, mas outras ferramentas e plugins podem - por exemplo* https://docs.sonarqube.org/display/SONARQUBE45/JaCoCo+Plugin [Sonar Qube] *.
A boa notícia é que podemos usar a meta jacoco: report para gerar relatórios de cobertura de código legíveis em vários formatos, por exemplo HTML, CSV e XML.
Agora, podemos dar uma olhada, por exemplo, na página target/site/jacoco/index.html para ver como é o relatório gerado:
Seguindo o link fornecido no relatório - Palindrome.java , podemos detalhar uma visualização mais detalhada para cada classe Java:
Observe que você pode gerenciar diretamente a cobertura de código usando JaCoCo dentro do Eclipse com configuração zero , graças ao plugin do Eclipse Eclipse.
*4. Análise de relatório *
Nosso relatório mostra 21% de cobertura de instruções, 17% de cobertura de agências, 3/5 para* complexidade ciclomática *e assim por diante.
As 38 instruções mostradas pela JaCoCo no relatório referem-se às* instruções bytecode * em oposição às instruções comuns de código Java.
Os relatórios da JaCoCo ajudam você a analisar visualmente a cobertura do código usando diamantes com cores para ramificações e cores de fundo para linhas:
-
Diamante vermelho significa que nenhuma ramificação foi exercida durante a fase de teste.
-
Diamante amarelo mostra que o código está parcialmente coberto - algumas filiais não foram exercidas.
-
Diamante verde significa que todos os ramos foram exercitados durante o teste.
O mesmo código de cor se aplica à cor de fundo, mas à cobertura de linhas.
A JaCoCo fornece principalmente três métricas importantes:
-
Cobertura de linhas reflete a quantidade de código que foi exercida com base no número de instruções de código de bytes Java chamadas pelos testes.
-
Cobertura de ramificações mostra a porcentagem de ramificações exercidas no código - geralmente relacionadas às instruções if/else e switch.
-
Complexidade ciclomática reflete a complexidade do código, fornecendo o número de caminhos necessários para cobrir todos os caminhos possíveis em um código por meio de combinação linear.
Para dar um exemplo trivial, se não houver instruções if ou switch no código, a complexidade ciclomática será 1, pois precisamos apenas de um caminho de execução para cobrir todo o código.
Geralmente, a complexidade ciclomática reflete o número de casos de teste que precisamos implementar para cobrir todo o código.
*5. Composição do conceito *
JaCoCo é executado como um* Java agent , é responsável por *instrumentar o bytecode durante a execução dos testes. A JaCoCo analisa cada instrução e mostra quais linhas são exercitadas durante cada teste.
Para coletar dados de cobertura, a JaCoCo usa ASM para instrumentação de código em tempo real, recebendo eventos do _ JVM Tool Interface_ no processo:
Também é possível executar o agente JaCoCo no modo servidor; nesse caso, podemos executar nossos testes com jacoco: dump como objetivo, para iniciar uma solicitação de despejo.
Você pode seguir o link da documentação oficial para obter detalhes mais detalhados sobre o design do JaCoCo.
*6. Pontuação de cobertura de código *
Agora que sabemos um pouco sobre como o JaCoCo funciona, vamos melhorar nossa pontuação de cobertura de código.
Para obter 100% de cobertura do código, precisamos apresentar testes, que cubram as partes ausentes mostradas no relatório inicial:
@Test
public void whenPalindrom_thenAccept() {
Palindrome palindromeTester = new Palindrome();
assertTrue(palindromeTester.isPalindrome("noon"));
}
@Test
public void whenNearPalindrom_thanReject(){
Palindrome palindromeTester = new Palindrome();
assertFalse(palindromeTester.isPalindrome("neon"));
}
Agora podemos dizer que temos testes suficientes para cobrir todo o código, mas para garantir isso, vamos executar o comando Maven mvn jacoco: report para publicar o relatório de cobertura:
Como você pode ver, todas as linhas/filiais/caminhos em nosso código são totalmente cobertas:
No projeto do mundo real, e à medida que os desenvolvimentos vão além, precisamos acompanhar a pontuação da cobertura do código.
JaCoCo oferece uma maneira simples de declarar* requisitos mínimos *que devem ser atendidos, caso contrário, a construção falhará.
Podemos fazer isso adicionando a seguinte meta check em nosso arquivo pom.xml:
<execution>
<id>jacoco-check</id>
<goals>
<goal>check</goal>
</goals>
<configuration>
<rules>
<rule>
<element>PACKAGE</element>
<limits>
<limit>
<counter>LINE</counter>
<value>COVEREDRATIO</value>
<minimum>0.50</minimum>
</limit>
</limits>
</rule>
</rules>
</configuration>
</execution>
Como você provavelmente pode adivinhar, estamos limitando aqui a pontuação mínima para cobertura de linhas a 50%.
O objetivo jacoco: check está* vinculado *a verify, para que possamos executar o comando Maven - mvn clean confirm para verificar se as regras são respeitadas ou não. Os logs mostrarão algo como:
[ERROR] Failed to execute goal org.jacoco:jacoco-maven-plugin:0.7.7.201606060606:check
(jacoco-check) on project mutation-testing: Coverage checks have not been met.
===* 7. Conclusão *
Neste artigo, vimos como usar o plugin maCo JaCoCo para gerar relatórios de cobertura de código para projetos Java.
Porém, lembre-se de que* a cobertura de código 100% não é necessária para refletir testes eficazes , pois reflete apenas a quantidade de código exercida durante os testes. Em um artigo anterior, falamos sobre *link:/java-mutation-testing-with-pitest [mutation testing] como uma maneira mais sofisticada de rastrear a eficácia dos testes em comparação com a cobertura de código comum.
Você pode conferir o exemplo fornecido neste artigo no link https://github.com/eugenp/tutorials/tree/master/testing-modules/testing-libraries [projeto GitHub] *.