Testes unitários já foram vistos com maus olhos pela comunidade de desenvolvimento de software quando surgiram, e hoje em dia é uma das práticas obrigatórias no desenvolvimento da maioria dos sistemas. Mas afinal o que fez todo mundo mudar a maneira de pensar e trabalhar? O que motiva um desenvolvedor a “perder tempo” escrevendo testes unitários?
As respostas hoje em dia são bem claras na cabeça de muitos desenvolvedores, por isso vamos passar por temas que vão além dos testes unitários e abordar como nos beneficiamos a longo prazo com uma política de testes e boas práticas bem definida.
Já que todos concordam (a grande maioria pelo menos) que testes nos beneficiam, porque não testar em todo o processo de desenvolvimento? Uma dúvida que surge assim que a equipe resolve testar suas classes: devemos estimar também o tempo que levaremos para escrever os testes? A resposta é simples, sim e não. Sim porque com certeza o tempo para executar a tarefa será diferente quando resolvemos escrever testes para nossas classes, e não porque não devemos separar a estimativa, como se escrever testes fossem uma tarefa diferente. Inclusive deveríamos considerar que uma tarefa só é concluída se existem testes unitários que garantem o funcionamento da mesma, e que tais testes estejam passando.
Podemos pensar que se para cada funcionalidade que implementamos garantimos o funcionamento da mesma, estamos seguros para implementar uma nova funcionalidade sem interferir no progresso do sistema até então. A única maneira de garantirmos que toda funcionalidade nova estará de acordo com as já existentes é testando ao longo de todo o projeto. O mesmo vale para testes de uso, feitos por uma equipe de testes, pois se pensarmos que os testes unitários nos protegem de nossos próprios erros, ainda assim não estamos protegidos de erros de sistemas externos que serão usados par integração com o nosso projeto.
O fator mais crítico em se testar sempre, é que quando nos deparamos com um determinado erro, nossa cabeça ainda está no contexto da tarefa ao qual o teste falhou, e portanto está mais claro em nossas mentes como corrigi-la, acelerando a correção de erros e o desenvolvimento de novas tarefas mais futuramente.
Os relatórios de cobertura de testes a primeira vista parecem um ferramenta de controle sobre como estamos desenvolvendo. Muito pelo contrário, porque os relatórios de cobertura apenas expoem as linhas e blocos do código que são executados durante os testes, escondendo muitos outros fatores relevantes no desenvolvimento, além do que é bem fácil “roubar” no teste para obter uma cobertura alta.
O relatório de cobertura serve como ferramenta de alerta para a equipe como um todo, para que a qualquer momento, qualquer membro da equipe possa consultar o relatório e se certificar que dado a cobertura de testes, ele pode continuar o desenvolvimento de suas tarefas ou então, notificar toda a equipe que existem partes do código não testadas e que devem receber mais atenção para garantir uma evolução contínua do sistema.
O FindBugs é uma ferramenta que nos auxilia no desenvolvimento prevendo possíveis pontos problemáticos do sistema. O FindBugs funciona com o Java mas existem versões para diversas plataformas.
No mesmo espírito do relatório de cobertura, os possíveis bugs apontados pelo FindBugs servem como alerta para a equipe para pontos do sistema que talvez mereçam mais atenção, e da mesma forma é possível “roubar” e sempre deixar o FindBugs “contente”, por isso é essencial a consciência da equipe para manter o FindBugs dentro da linha.
O relatório gerado pelo PMD é mais um guia de boas práticas que deveriam ser seguidas durante a implementação do código. O PMD é bem menos intrusivo que o FindBugs no sentido de que a análise feita por ele é mais voltada a estilo de programação, e pode ser configurada e ajustada de acordo com o projeto e a equipe. O ideal seria que conseguíssemos estabelecer uma configuração do PMD e do FindBugs para a redspark, garantindo que se mudarmos algum desenvolvedor de equipe, o desenvolvedor iria estar familiarizado com as práticas e padrões do novo projeto, afinal seriam os mesmos padrões exigidos no projeto em que o desenvolvedor estava.
Um dos principais objetivos de se empregar boas práticas de programação, é garantir uma linguagem comum entre equipes de desenvolvimento. Para facilitar tal compreensão, seria interessante que o código implementado independente da equipe, seguisse uma mesma identação e organização. Dessa forma um desenvolvedor novo no projeto consegueria “se encontrar” no código de maneira mais rápida, porque a estrutura adotada seria a mesma em todos os projetos.
Para facilitar e garantir que o padrão está sendo seguido, existe por exemplo, o plugin de ‘checkstyle’ do eclipse. O plugin nada mais faz do que colocar warnings no código, nos trechos em que o padrão de identação e organização definido não está sendo seguido. O plugin consegue ir um pouco mais longe do que meramente validar formatação de código, e consegue “cobrar” o emprego de algumas boas práticas mais básicas, como por exemplo encapsulamento e gerenciamento de variáveis.
Se escrever código de maneira padronizada, organizada e compreensível é essencial para comunicação, o mesmo se aplica para a documentação das classes.
Por isso que existem ferramentas como o javadoc, que é uma das ferramentas mais difundidas na comunidade. Isso porque garante a geração de uma documentação livre de código de maneira automática e simples. O que deveríamos ter em nossas classes, é uma documentação na qual não seja necessário ler o código para entender o funcionamento da classe. A única maneira de garantir um nível de documentação desses, é sempre manter a documentação atualizada e constantemente mudá-la conforme desenvolvemos o sistema.
No Java existe o Javadoc que é tão difundido que já vem integrado com o Eclipse IDE, e existem versões disponíveis para todas as grandes plataformas, inclusive Flex.
Apesar de citar algumas tecnologias usadas no Java, o objetivo principal do post é mostrar que o emprego de tais ferramentas nos ajuda no dia-a-dia de desenvolvimento em geral, não importando a tecnologia utilizada. A idéia é atingir um nível de qualidade geral, independente de plataforma. Se atingirmos um nível aceitável e conseguirmos seguir um padrão, conseguiremos migrar entre projetos tendo que apenas entender a regra de negócio do projeto, já estando familiarizado com as práticas de desenvolvimento.