Android

20 jan, 2016

Integrando ferramentas de análise de código no Android – Parte 02

Publicidade

Parte 2: FindBugs

Na semana passada, começamos uma série sobre como integrar ferramentas de análise de código. Na primeira parte, falamos sobre a Checkstyle. Desta vez, vamos falar sobre o FindBugs.

Atualmente, em sua versão 3.0.1, o FindBugs é uma ferramenta de análise que se concentra em bugs comumente encontrados em códigos Java, além de buscar por potenciais problemas de segurança. A partir da análise, ele pode gerar relatórios em diversos formatos, inclusive HTML, que podem posteriormente ser publicados em um servidor de CI.

A integração da ferramenta ocorre de forma bastante semelhante ao CheckStyle, já que o Gradle também possui um plugin para o FindBugs de forma nativa.

O primeiro passo é aplicarmos o plugin ao nosso arquivo build.gradle:

apply plugin: 'findbugs'

Assim como fizemos com o CheckStyle, podemos adicionar a task do FindBugs à nossa task check.

check.dependsOn 'checkstyle', 'findbugs'

Feito isso, vamos então criar a nossa task. Como o FindBugs também verifica os arquivos .class, precisamos fazer com que essa task dependa de uma outra task de build. Neste exemplo, coloquei a task assembleDebug.

task findbugs(type: FindBugs, dependsOn: assembleDebug) {
    ignoreFailures = false
    effort = 'max'
    reportLevel = 'high'
    excludeFilter = new File("${project.rootDir}/config/findbugs-filter.xml")
    classes = files("${project.rootDir}/app/build/intermediates/classes")
 
    source 'src'
    include '**/*.java'
    exclude '**/gen/**'
 
    reports {
        xml.enabled = false
        html.enabled = true
        html {
            destination "$project.buildDir/reports/findbugs/findbugs.html"
        }
    }
 
    classpath = files()

No caso do FindBugs, primeiro configuramos para que o processo de build seja interrompido caso alguma ocorrência seja encontrada. Em seguida, configuramos os níveis de esforço e report, as classes que devem ser ignoradas (já veremos como é este arquivo) e o diretório no qual estão as classes a serem analisadas. Configuramos o atributo source, adicionamos todos os arquivos Java que forem encontrados e ignoramos quaisquer arquivos que estejam na pasta gen (o que geralmente não ocorre em projetos Gradle — essa propriedade faz mais sentido em builds Ant feitas pelo Eclipse).

O arquivo de filtro (findbugs-filter.xml) diz quais classes devem ser ignoradas no processo. Para este exemplo, utilizei um arquivo assim:

<?xml version="1.0" encoding="UTF-8"?>
<FindBugsFilter>
    <Match>
        <Class name="~.*\.R\$.*" />
    </Match>
    <Match>
        <Class name="~.*\.Manifest\$.*" />
    </Match>
    <!-- Todas as classes de teste, exceto bugs específicos do JUnit -->
    <Match>
        <Class name="~.*\.*Test" />
        <Not>
            <Bug code="IJU" />
        </Not>
    </Match>
</FindBugsFilter>

Nesse arquivo, ignoramos a classe R, classes de Manifest e ignoramos bugs referentes ao JUnit nas classes de teste.

Por fim, configuramos a geração do relatório HTML e o classpath.

E pronto! Ao executarmos a task findbugs ou mesmo a task check (já que criamos esta dependência), teremos a execução da ferramenta sobre a nossa base de código. Mas, o que pode dar errado no código? Imagine o seguinte:

public class Client implements Parcelable {
  
  public static TABLE_NAME = "clients";
  
  ...
}

Tenho uma classe de modelo na qual, para organizar melhor meu projeto, coloquei um atributo estático com o nome da tabela do SQLite que armazena objetos desse tipo. Tudo certo, não?

1-kNAm4UI__vmy29JCOhDJ3g

AHN??? Como assim?

Vamos ver o que o FindBugs tem a dizer sobre isso:

net.rafaeltoledo.sample.Client.TABLE_NAME isn’t final but should be

E ele ainda nos dá mais alguns detalhes sobre o motivo disso ser ruim:

MS_SHOULD_BE_FINAL: Field isn’t final but should be

This static field public but not final, and could be changed by malicious code or by accident from another package. The field could be made final to avoid this vulnerability.

Ahhh, sim! Me esqueci do modificador final, já que esse cara é uma constante! Ufa! =)

O FindBugs possui uma lista vasta de verificações, e pode ser um grande aliado para fazer com que nosso código seja mais eficiente e mais seguro.

Então é isso, pessoal! Ficou alguma dúvida ou tem alguma observação? Aproveite o campo abaixo. No próximo artigo vamos conhecer o atirador de elite do nosso grupo, o PMD!

Até lá!

***

Post originalmente publicado no Medium e no Blog pessoal do autor.