Testar é fundamental no desenvolvimento de software. Quando bem escritos, os testes automatizados aumentam a qualidade do código, ajudam a identificar erros mais cedo e dão segurança para que os desenvolvedores façam alterações sem medo. No entanto, uma dúvida comum costuma surgir: “até que ponto o código realmente está sendo testado?”. É aqui que entra o conceito de Code Coverage (ou cobertura de código) e ferramentas como o JaCoCo, que permitem visualizar quanto do sistema está de fato protegido pelos testes.

O que é Code Coverage (Cobertura de Código)?

Code Coverage é uma métrica que indica a porcentagem de código executada durante a execução dos testes automatizados. Em outras palavras, mostra se os testes realmente percorrem os métodos, condições e fluxos existentes em uma aplicação.

As formas mais comuns de medir cobertura de código são:

  • Line Coverage: verifica se cada linha de código foi executada ao menos uma vez durante os testes.
  • Branch Coverage: garante que todas as ramificações de decisão (if/else, switch) foram percorridas.
  • Method Coverage: checa se todos os métodos definidos na aplicação foram invocados nos testes.
  • Class Coverage: indica se todas as classes foram carregadas e exercitadas pelos testes.

Ter 100% de cobertura não significa que o código está livre de erros. Essa métrica apenas indica que todos os caminhos foram executados durante os testes, mas não garante que a lógica foi validada corretamente.

O que é o JaCoCo?

O JaCoCo (Java Code Coverage) é uma ferramenta open source voltada para medir a cobertura de código em aplicações Java. Ele permite gerar relatórios detalhados que evidenciam quais trechos do código foram efetivamente executados durante a execução dos testes automatizados.

O JaCoCo pode ser integrado de forma simples a ferramentas de build, como Maven e Gradle. A seguir, apresentamos um exemplo de configuração para o Maven:

<build>
    <plugins>
        <plugin>
            <groupId>org.jacoco</groupId>
            <artifactId>jacoco-maven-plugin</artifactId>
            <version>0.8.13</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>
    </plugins>
  </build>

Agora, vamos criar uma classe de exemplo para ser testada — uma calculadora simples.

public class Calculadora {

    public int somar(int a, int b) {
        return a + b;
    }

    public int subtrair(int a, int b) {
        return a - b;
    }

    public double dividir(double a, double b) {
        if (b == 0.0) {
            throw new IllegalArgumentException("Divisão por zero não é permitida");
        }
        return a / b;
    }

    public boolean ehPar(int numero) {
        return numero % 2 == 0;
    }
}

A seguir, apresentamos uma classe contendo os testes unitários:

public class CalculadoraTest {

    private Calculadora calculadora;

    @BeforeEach
    void setup(){
        this.calculadora = new Calculadora();
    }

    @Test
    void deveSomarDoisNumeros(){
        
        int resultado = this.calculadora.somar(10, 20);

        assertEquals(resultado, 30);

    }

    @Test
    void deveSubtrairDoisNumeros(){
        
        int resultado = this.calculadora.subtrair(10, 20);

        assertEquals(resultado, -10);

    }

    @Test
    void deveDividirDoisNumeros(){
        
        double resultado = this.calculadora.dividir(10, 2);

        assertEquals(resultado, 5);

    }
}

Em seguida, podemos executar os testes e gerar o relatório de cobertura utilizando o seguinte comando:

mvn clean test jacoco:report

Após a execução do comando, o JaCoCo gerará um relatório em HTML que pode ser acessado em: target/site/jacoco/index.html

Relatório de Cobertura de Código do Jacoco - index.html

Em seguida, acessamos a classe Calculadora no relatório.

Relatório de Cobertura de Código do Jacoco - Classe Calculadora

Pelo relatório, é possível observar que o método dividir não está totalmente coberto pelos testes, enquanto o método ehPar não possui cobertura alguma. Além disso, podemos clicar em cada método para visualizar o trecho correspondente no código da classe.

Relatório de Cobertura de Código do Jacoco - Classe Calculadora com as linhas não testadas em vermelho

Agora, podemos identificar as linhas de código que não estão sendo cobertas por nenhum teste automatizado.

Para corrigir essa situação, vamos adicionar mais dois testes à classe CalculadoraTest.

@Test
void naoDeveDividirPorZero(){
        
    assertThrows(IllegalArgumentException.class, () -> {
        this.calculadora.dividir(10, 0);
    });
}

@Test
void deveVerificarSeEhPar(){
    assertTrue(this.calculadora.ehPar(12));
}

Em seguida, executamos os testes novamente e geramos o relatório atualizado:

mvn clean test jacoco:report
Relatório de Cobertura de Código do Jacoco - Classe Calculadora exibindo linhas que não foram testadas.

Observe que agora não há mais linhas vermelhas indicando código não testado. No entanto, a linha 21 aparece em amarelo, indicando que apenas um dos possíveis caminhos do método foi executado — no caso, testamos apenas com um valor par. Para deixar a linha verde deveríamos também escrever um teste para verificação de um número impar

Conclusão

O JaCoCo é uma ferramenta fundamental para desenvolvedores Java que desejam medir e aprimorar a qualidade dos testes automatizados. Embora a cobertura de código não garanta a ausência de erros, ela funciona como um excelente termômetro para avaliar a robustez da suíte de testes e identificar trechos que merecem atenção. Por isso, a cobertura de código deve ser usada como indicador auxiliar, e não como objetivo final.