Gerando o Relatório de Cobertura de Testes Unificado com Jacoco, Robolectric e Espresso
Olá, pessoal! No post de hoje, veremos como é possível gerar um relatório de cobertura de testes em um projeto Android incluindo tanto os testes unitários (geralmente escritos com JUnit, Mockito, Robolectric, etc.) quanto os instrumentados (geralmente escritos utilizando o Espresso).
Relatórios de cobertura de testes são uma ferramenta muito importante para mensurar o quanto nossos testes realmente exercitam nosso código. Apesar de não serem a garantia de um software sem bugs, ter uma porcentagem alta de cobertura pode evitar muitas dores de cabeça no desenrolar do projeto.
No Android, para gerar esse tipo de relatório utilizamos o Jacoco (Java Code Coverage), uma das ferramentas mais utilizadas dentro do Java para esse propósito. No ambiente de desenvolvimento do Android, temos um fator dificultador que é o fato de possuirmos dois artefatos de teste diferentes, geralmente representados pelas pastas test (unitários) e androidTest (instrumentados).
Primeiramente, vamos gerar o relatório de cobertura dos testes instrumentados do Espresso. Para este exemplo, teremos uma Activity bem simples:
O layout dessa Activity é o seguinte:
Vamos então criar um teste no Espresso para garantir que o texto do TextView text seja modificado para Hello World! ao clicarmos no Button button:
Após a execução desse teste, temos o relatório de execução:
Porém, o relatório de cobertura ainda não é gerado. Para habilitarmos essa opção, precisamos adicionar uma propriedade para a nossa build variant de debug. Na DSL do plugin do Android, habilite a cobertura por meio da propriedade testCoverageEnabled:
Agora, basta executar a task createDebugCoverageReport para que os testes sejam executados e o relatório seja gerado.
Perfeito! Já temos o relatório de cobertura do nosso projeto.
Vamos agora criar um teste usando o Robolectric para testar o else da lógica da nossa Activity. Porém, um aviso: particularmente, eu não recomendo testar a Activity e componentes do Android diretamente pelo Robolectric. Prefira testes que, de fato, testem unidades de código.
Um teste com Robolectric que testa o comportamento do botão hide, cuja visibilidade é alterada quando clicado, ficaria assim:
Por padrão, o plugin do Android só gera o relatório de cobertura dos testes instrumentados. Para que seja possível gerar a cobertura dos testes unitários, é necessário criar uma task de execução do relatório manualmente:
Com a criação da task jacocoTestReport, temos agora a geração do relatório de cobertura também para os testes unitários.
Porém, permanece o problema: como ter a cobertura unificada do resultado dos dois grupos de testes?
A instrumentação realizada pelo Jacoco produz arquivos de execução que contêm os dados necessários para a criação do relatório (HTML, XML, etc). O grande problema é que o Espresso gera o arquivo .ec, enquanto que a execução dos testes unitários gera o arquivo .exec, ou seja, temos formatos de arquivos diferentes!
E agora? Como converter de um formato para o outro? A resposta, obtida depois de muita pesquisa, é: simplesmente não é necessário converter!
Como não temos acesso à task que configura a execução dos testes com o Espresso, precisamos garantir que ela seja executada primeiro, para que, na execução do relatório dos testes unitários, o arquivo coverage.ec já esteja disponível.
Na task do relatório dos testes unitários, o que vamos fazer é adicionar o arquivo coverage.ec também como parâmetro na propriedade executionData:
Por fim, ao executarmos a task completa, com os testes instrumentados pelo Espresso primeiro, teremos o relatório unificado de cobertura.
gradle clean createDebugCoverageReport jacocoTestReport
E é isso! O projeto de exemplo pode ser encontrado neste repositório do Github! #KeepCoding #KeepTesting