Desenvolvimento Orientado por Testes

Category : TDD

Como comentei no meu primeiro artigo aqui no Blog, durante meus estudos para a SCJP conheci muitas coisas bacanas. Foi meu primeiro contato com algumas das metodologias do Agile. Entre elas a que mais procurei praticar, mesmo enquanto criava simples códigos de aprendizagem era o Test Driven Development (TDD).

A premissa do TDD é que o desenvolvedor deve escrever o código de testes antes de escrever o código de produção. Minha primeira reação ao ler isso era de achar maluquice: “como posso testar algo antes mesmo de existir?”. A resposta para isso encontrei pesquisando mais sobre o assunto e tudo passou a fazer muito sentido depois que entendi seus conceitos. Meu pensamento então passou a ser: “como um programador pode viver sem isso?”.

As três leis básicas

Para começar você deve seguir três regras básicas:

  • Escreva um teste que falhe.
  • Não escreva mais de um teste que falhe, sendo que não compilar é falhar.
  • Escreva o código de produção necessário para passar neste teste.

Um exemplo simples

Você começa a escrever um código de teste que propositalmente falhe, já que neste ponto não deverá haver nenhum código de produção. No JUnit 4 o caso de teste seria algo simples como:

1
2
3
4
5
6
7
8
9
10
import org.junit.Test;
import static org.junit.Assert.assertEquals;

public class HelloWorldTest {
    @Test
    public void aSimpleHelloTest() {
        HelloWorld hello = new HelloWorld();
        assertEquals("Hello world!", hello.sayHello());
    }
}

Execute o teste. O mesmo deverá falhar neste ponto.

Em seguida implemente na classe alvo o código de produção de maneira que passe no teste. Por exemplo:

1
2
3
4
5
public class HelloWorld {
    public String sayHello() {
        return "Hello world";
    }
}

Execute o teste novamente e faça com que o código passe no teste. Repita o processo.

“No Eclipse você pode facilmente criar uma unidade de testes indo em New : Other : Junit Test Case. Certifique-se de utilizar o JUnit 4 para seus testes. Para executá-lo bas ir em Run : Run As : JUnit Test

Benefícios

Gosto de classificar cinco benefícios quando me perguntam sobre TDD.

1. Entendimento do domínio:

Escrevendo testes antes do código o desenvolvedor é levado a refletir sobre o que está sendo implementado, o que leva a uma maior clareza sobre o domínio do problema, e até mesmo a levantar fatos que poderiam passar despercebido na especificação de requisitos.

2. Segurança:

Os testes são um selo de garantia que tudo está funcionando corretamente. Se for necessário alterar algo no futuro, o desenvolvedor terá certeza que a alteração não quebrou nada.

3. Ganho de produtividade:

A codificação de um caso teste é simples e ocupa uma fração insignificante do tempo de desenvolvimento. A unidade de testes se transforma numa documentação sempre atualizada do código. Com isso em mãos o desenvolvedor fará a manutenção do código mais rápidamente.

4. Melhoria na qualidade:

Os testes de unidade garantem que o que foi implementado funcione sempre da maneira esperada. Muitos dos bugs que poderiam passar despercebidos em um código sem teste não passarão aqui. O desenvolvedor que reflete sobre o domínio sendo implementado cria códigos menos propensos a bugs.

5. Melhoria estrutual do código:

Desenvolver orientado por testes nos força a criar códigos com menor acoplamento, orientado a objetos. Os testes também são essenciais para a refatoração do código. Como eu disse outro dia no Twitter: “Refatorar sem testes é como paraquedismo sem para-quedas!”

Links relacionados:

http://www.junit.org/
http://en.wikipedia.org/wiki/Test_driven_development
http://en.wikipedia.org/wiki/Agile_software_development

Livros relacionados

Clean Code: A Handbook of Agile Software Craftsmanship [Robert C. Martin]
Test-driven development: by example [Kent Beck]

Cadê o Meu Gato? Ou, Cadê o Bug?

Category : Boas Práticas

Kitty BugFaz tempo estava querendo escrever este post, mas um fato interessante me fez mudar o título e o texto.

Nosso novo bichano de estimação na primeira semana desapareceu do apartamento. Minha esposa me ligou desesperada dizendo que ele havia fugido enquanto eu saia pra trabalhar. Esta idéia já estava formada na cabeça dela, e não adiantou eu argumentar que sempre tomo cuidado ao sair e que a gata ainda filhote sempre fica insegura quando a porta é aberta e prefere se esconder a sair.

Depois de procura-la por todo o prédio, casas e lotes vizinhos minha esposa resolveu desistir e colocar cartazes de “procura-se” por aí. Eu tinha certeza que ela estava em casa, mas ela teimou que já havia revirado todos os locais e nenhum sinal do bichinho.

Você pode rir, mas ao chegar a noite em casa não demorei mais de cinco minutos para encontrar a danadinha. Fui no local mais óbvio, onde todo gato gosta de entrar quando não estamos olhando, o guarda-roupas.

Mas o que isso tem a ver com software?

Este fato me levou a lembrar um erro que cometi poucas semanas antes na implementação de uma classe responsável pela manipulação dos dados de produtos no sistema.

Eu conhecia a classe de cor e só precisava adicionar uma nova propriedade. Basicamente um par de getter/setter. O design da classe é um pouco mais complicado que isso, e não vem ao caso, colocar uma nova propriedade implica sempre em mais algumas gambiarras tarefas por uma decisão de design.

Mas eu estava confiante, já conhecia o código e estava mais preocupado em terminar outra tarefa de maior importância. Basicamente usei a clássica combinação rápida que destrói qualquer código: Ctrl+C, Ctrl+V e renomear. Agora era só voltar para a tarefa de maior importância e commitar aquele bug que eu acabara de criar.

Não existe menos ou mais atenção!

Ou você está prestando atenção no que está fazendo ou não. Pequenas alterações, por mais insignificantes que sejam precisam de testes. Testar apenas as partes mais complexas de um software é se submeter a perder horas procurando pela vizinhança por algo que está no seu guarda-roupas quando ocorrer um bug.

Leve a sério e pratique TDD e BDD ou você nunca vai ter certeza se seu gato fugiu ou está tirando uma soneca dentro de uma gaveta!