Integrando Gradle + Jacoco + SonarQube
Tags: testing, gradle, jacoco, sonarqube
Published: 2021-04-18 21:16:41

Cobertura de testes é um assunto polêmico. Se meu código tem 100% de cobertura de código, significa que ele está a prova de falhas? Não exatamente. Mas é essencial ter uma boa noção da cobertura dos teste no nosso código e ter em mãos ferramentas de análise que nos ajudem a ter uma noção melhor dos pontos de atenção no código (seja quanto a sua complexididade, tamanho de classes, dependências etc).

Em alguns projetos que trabalhei muitas vezes utilizava apenas o [Jacoco](https://www.eclemma.org/jacoco) para analisar a cobertura dos meus testes a partir dos relatórios gerados por ele. 

Com o SonarQube podemos dar um passo adiante, já que a partir do relatório gerado pelo Jacoco ele consegue dar um complemento na análise e saúde do nosso código, gerando um dashboard com várias informações. Ele complementa esse relatório de cobertura, trazendo informações de violações de boas práticas no código, potênciais bugs, duplicações, falhas de segurança e entre outras coisas...

# Rodando SonarQube localmente

Nesta demonstração utilizei a versão _**8.8-community**_.

Antes de mais nada é preciso seguir as recomendações da página do [Dockerhub](https://hub.docker.com/_/sonarqube/), que sugerem ajustar a quantidade de memória virtual: 

> For example, on Linux, you can set the recommended values for the current session by running the following commands as root on the host:


```shell
sysctl -w vm.max_map_count=262144
sysctl -w fs.file-max=65536
ulimit -n 65536
ulimit -u 4096
```

Após isso criar um docker-compose.yml seguindo as orientações fornecidas na [documentação para Docker](https://docs.sonarqube.org/latest/setup/install-server/) do SonarQube e subir o container localmente:

```shell
docker-compose up -d
```

No navegador acessar `http://localhost:9000/` e entrar na tela de login, como abaixo:

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/j2mixtq91qlq8oszsnv0.png)

Neste primeiro acesso conectei com login e senha _admin/admin_. Em seguida será solicitada uma nova senha:

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/pfc9xr32q8oq7m56uhx5.png)

Pronto! Podemos acessar nosso SonarQube:

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/lmxl5ojtlpzdeg5pu80t.png)


# Configurando meu projeto

Para fazer essa integração utilizei um projeto pessoal desenvolvido em Kotlin: https://github.com/flflima/shopping-cart.

Primeiramente no SonarQube criei e configurei um projeto manualmente:

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/kcsw2mvrvoq7wavy213u.png)
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/o4c9osg5vphvdlwau3jw.png)

Foi gerado um código para adicionar no meu arquivo de configuração do projeto. No meu caso, estou utilizando o Gradle como gerenciador de dependência:

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/tkayxu17dzpnvkhmb2eg.png)

Após adicionar o plugin conforme sugerido, bastou executar o comando que gera meus relatórios via Jacoco e integra com o SonarQube:

```shell
./gradlew clean test sonarqube \
  -Dsonar.projectKey=<<your-project-key-configured>> \
  -Dsonar.host.url=http://localhost:9000 \
  -Dsonar.login=<<the-login>>
```

Na primeira vez que executei, o report marcou **0%** de cobertura, o que não deveria ter acontecido já que o relatório do Jacoco marcava uma cobertura acima de **80%**.

Mais precisamente **99%** para cobertura por linha e **86%** para cobertura por branches:

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/wn1sytqxcwnsqwcgny6g.png)

Já no SonarQube:

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/dqruetk82cuzi5yy7dnq.png)

Após algumas pesquisas, descobri que precisava fazer alguns ajustes para que o Sonarqube pudesse enxergar o relatório gerado pelo Jacoco:
- habilitar a flag **xml.enabled**, para que o SonarQube pudesse ler o relatório gerado em formato XML (a partir da versão 8 ele deixou de suportar o arquivo **.exec** gerado pelo Jacoco - mais [aqui](https://community.sonarsource.com/t/sonarqube-community-version-8-3-is-showing-0-code-coverage-however-with-the-same-configurations-i-am-able-to-get-coverage-in-community-version-8-1/28007))

```java
jacocoTestReport {
    reports {
        xml.enabled true // a flag anteriormente era false
        csv.enabled false
        html.destination file("${buildDir}/jacocoHtml")
    }

    afterEvaluate {
        excludeFiles(classDirectories, coverageExclusions)
    }
}
```
- incluí uma configuração para o SonarQube localizar o relatório em XML e mapeei os mesmos arquivos excluídos da verificação do Jacoco:

```java
sonarqube {
    properties {
        property "sonar.coverage.jacoco.xmlReportPaths", "${buildDir}/reports/jacoco/test/*.xml"
        property "sonar.java.coveragePlugin", "jacoco"
        property "sonar.coverage.exclusions", coverageExclusions
    }
}
```
- na verificação da cobertura de código, removi a flag **enabled = false**, para que o relatório fosse gerado sempre, mesmo que a cobertura de código não fosse atingida:

```java
jacocoTestCoverageVerification {
    violationRules {
        rule {
            limit {
                // enabled = false
                counter = 'BRANCH'
                value = 'COVEREDRATIO'
                minimum = 0.8
            }
        }
    }

    afterEvaluate {
        excludeFiles(classDirectories)
    }
}
```

Após essas alterações o SonarQube começou a apresentar os valores de cobetura. Na aba 'Measures' podemos ver que o mesmo valor (ou uma aproximação) é marcado, tanto para cobertura por linhas como por branches:
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/o7rln65v1heh385lrgx9.png)
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/fc5dipzipogqqmf5bm91.png)
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/wn1sytqxcwnsqwcgny6g.png)

E como cobertura geral do SonarQube temos:
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/52nxk0iy9i0bl98u5tjv.png)

---

Como comentei no início do texto, essas são ferramentas que agregam nossa busca em qualidade de código. 

É claro que precisamos estar sempre atentos porque até mesmos os testes podem estar sujeitos a bugs e nos dar a falsa sensação de que por termos uma alta cobertura nosso código está protegido. 

Mas como toda ferramenta de apoio é bem vinda, acredito que seja extremamente interessante que um desenvolvedor tenha conhecimento delas e ao longo do tempo vá usando todas com consciência.

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/l6r2zqi6u71h8ean0fo7.gif)

----

# Referências

https://www.eclemma.org/jacoco/
https://www.sonarqube.org/
https://hub.docker.com/_/sonarqube
https://docs.sonarqube.org/latest/setup/install-server/

_Referência ao erro:_ https://github.com/SonarSource/docker-sonarqube/issues/317