Mostrando postagens com marcador Testes. Mostrar todas as postagens
Mostrando postagens com marcador Testes. Mostrar todas as postagens

4 de maio de 2012

TDD - Test Driven Development

http://xion.org.pl/wp-content/uploads/2012/02/tdd.png

Pessoal, hoje vou postar sobre TDD, vejo muitas discussões e dúvidas sobre como desenvolver utilizando esta prática, espero sanar algumas delas, assim como tentar passar o modo que o utilizo no meu dia a dia.

TDD (Test Driven Development - Desenvolvimento Orientado a Teste) a forma como aprendemos a programar normalmente é:
 Desenvolvo o código e quando termino, testo, fazendo isso estamos arriscados a deixar uma grande quantidade de Bugs passar, muitas vezes esses erros acabam entrando em produção e o custo da manutenção ficará muito caro.

Ok, mas como deveria ser feito?
A resposta é: devemos começar com os testes, antes mesmo de criar as classes do sistema e é aí que sinto que muitos (assim como também senti no início) encontram dificuldades.

Como começar com os testes? Como vou saber o que minha classe vai ter?

Não precisamos saber tudo de uma vez, conforme eu desenvolvo um teste, crio e implemento as classes que serão testadas, por exemplo:

OBS: Para esses testes utilizei apenas o JUnit com a IDE Eclipse, não utilizei Mocks para esse caso.

Tenho um sistema de calculadora, nessa calculadora preciso das 4 operações matemáticas (adição, subtração, divisão e multiplicação) para calcular 2 números.

Por onde começo?
Vamos criar a classe de teste (Crie como uma classe JUnit New -> JUnit Test Case), eu chamei de FuncaoTest, dentro eu criei o primeiro método que se chama: deveriaSomarDoisNumeros.

Por que esse nome? Para ser simples, quero testar a adição de dois números, então, eu digo o que meu teste deveria fazer naquele método.

Nosso primeiro método ficou assim:
@Test
    public void deveriaSomarDoisNumeros() throws Exception {
        resultado = funcao.soma(2,2);

        Assert.assertTrue(resultado==4);
    }
Mas eu não possuo a classe Funcao.java ainda, então vamos criá-la (New -> Class) e dentro da classe criaremos o método soma:
public int soma(int primeiroValor, int segundoValor) {
        return primeiroValor+segundoValor;
    }
Agora vamos rodar o teste e ver o resultado (Run As -> JUnit Test):





Verde significa que nosso teste foi executado com sucesso.
Pronto, você conseguiu fazer seu primeiro teste, agora dando seqüência vamos criar a função de subtração, segue o mesmo passo anterior, vá no teste e crie o método deveriaSubtrairDoisNumeros, implemente o método na classe Funcao:

Método do teste deve ficar assim:
@Test
    public void deveriaSubtrairDoisNumeros() throws Exception {
        resultado = funcao.subtrai(2,2);

        Assert.assertTrue(resultado==0);
    }
E o método de subtração deve ficar assim:
public int subtrai(int primeiroValor, int segundoValor) {
        return primeiroValor-segundoValor;
    }
Claro que quando rodarmos o teste, a barra mostrará verde, mas e se durante o copy/paste nós fizessemos isso:
public int subtrai(int primeiroValor, int segundoValor) {
        return primeiroValor+segundoValor;
}


 O resultado seria isso:


 Durante nosso dia a dia, temos a mania de copiar e colar métodos que se parecem e fazer as alterações neles para que se comportem como esperamos, mas se nesse monte de copia e cola nós esquecessemos de mudar o sinal? Sem a classe de teste, só descobriríamos esse bug após o desenvolvimento ter terminado.

Mais uma observação, notaram que durante essa criação o teste contém elementos que duplicamos?
Notem a classe Função sendo instânciada duas vezes Funcao funcao = new funcao(); como vamos chamá-la sempre podemos instânciá-la logo no início, também notem que todos os métodos tem retorno int resultado, este também pode ser declarado no início da classe fora dos métodos, nossa classe de testes ficaria assim:
public class FuncaoTest {

    private Funcao funcao;
    private int resultado;
   
    @Before
    public void setUp() throws Exception {
        funcao = new Funcao();
    }
   
    @Test
    public void deveriaSomarDoisNumeros() throws Exception {
        resultado = funcao.soma(2,2);

        Assert.assertTrue(resultado==4);
    }
   
    @Test
    public void deveriaSubtrairDoisNumeros() throws Exception {
        resultado = funcao.subtrai(2,2);

        Assert.assertTrue(resultado==0);
    }
}
O @Before, fará a instância da classe para nós, isso de tirar a instância de todos os métodos e reescrever de uma forma que torne nosso método mais simples e prático, isso é chamado de Refatoração.
Quando utilizamos TDD, devemos sempre nos lembrar de seguir essa regra nos testes: Test Red, Test Green and Refactoring, ou seja, nós esperamos sempre que nosso teste falhe, depois corrigimos e após a correção, aplicamos refatoração e testamos novamente para ver se os métodos ainda estão funcionando.
Refatorar é reescrever um código, melhorando sua estrutura e mantendo a mesma funcionalidade.

http://www.testically.org/wp-content/uploads/2011/01/TestDrivenGameDevelopment.png


Para os métodos de divisão e multiplicação, basta seguir este mesmo conceito.
A classe de teste deverá ficar assim:
public class FuncaoTest {

    private Funcao funcao;
    private int resultado;
  
    @Before
    public void setUp() throws Exception {
        funcao = new Funcao();
    }
  
    @Test
    public void deveriaSomarDoisNumeros() throws Exception {
        resultado = funcao.soma(2,2);

        Assert.assertTrue(resultado==4);
    }
  
    @Test
    public void deveriaSubtrairDoisNumeros() throws Exception {
        resultado = funcao.subtrai(2,2);

        Assert.assertTrue(resultado==0);
    }
  
    @Test
    public void deveriaDividirDoisNumeros() throws Exception {
        resultado = funcao.divide(2,2);

        Assert.assertTrue(resultado==1);
    }

    @Test
    public void deveriaMultiplicarDoisNumeros() throws Exception {
        resultado = funcao.multiplica(2,2);

        Assert.assertTrue(resultado==4);
    }
}
E a Classe Funcao deverá ficar assim:
public class Funcao {

    public int soma(int primeiroValor, int segundoValor) {
        return primeiroValor+segundoValor;
    }

    public int subtrai(int primeiroValor, int segundoValor) {
        return primeiroValor-segundoValor;
    }

    public int divide(int primeiroValor, int segundoValor) {
        return primeiroValor/segundoValor;
    }
  
    public int multiplica(int primeiroValor, int segundoValor) {
        return primeiroValor*segundoValor;
    }
}
Bem lembrado pelo meu amigo Rafael Afonso, se a pessoa dividir por zero? Como poderia fazer meu teste?

A Solução ficaria desta forma:
@Test(expected = ArithmeticException.class)
    public void deveriaDividirDoisNumerosComExcessao() {
        resultado = funcao.divide(2,0);
        Assert.fail("Não deveria dividir por zero! " + resultado);
    }
Podemos testar também nossas exceções: Adicionamos o atributo 'expected' com a classe da exceção esperada.


Conclusão:
Esse foi apenas o ínicio da sua aventura com TDD, no final vou colocar alguns links interessantes, acostume-se a começar seu desenvolvimento pelo teste, não saia fazendo tudo loucamente, refatorem sempre, estude também Mocks, atualmente utilizo Mockito, um ótimo framework para mockar os objetos, entenda mockar como criar objetos falsos para facilitar nossos testes em camadas.

Links Úteis:
http://improveit.com.br/xp/praticas/tdd
http://www.slideshare.net/eduardo.bregaida/refatorao-de-cdigo-com-capito-nascimento-verso-completa
http://blog.caelum.com.br/facilitando-seus-testes-de-unidade-no-java-um-pouco-de-mockito/
http://rodrigomaia.net/2011/09/27/conhecendo-testes-unitarios-com-junit4/
http://blog.fragmental.com.br/2007/10/31/programadores-profissionais-escrevem-testes-ponto-final/
http://www.devmedia.com.br/junit-implementando-testes-unitarios-em-java-parte-i/1432
http://www.devmedia.com.br/junit-implementando-testes-unitarios-em-java-parte-ii/1549
http://rodrigomaia.net/2011/09/27/mock-objects-com-mockito/

14 de setembro de 2011

QConSP 2011 - Eu Fui e foi Show!



Esse ano houve a segunda edição do QConSP (Twitter: #QConSP) com diversas palestras de alto nível, o melhor evento de TI do ano, diversos palestrantes de fora do Brasil, vou falar um pouco do fim de semana na QCon São Paulo.
Os slides das palestras podem ser vistos acompanhando a time line do #QConSP pelo twitter.
Antes de falar das apresentações vou falar da galera (que com certeza esquecerei de botar todos, pois foram muitos amigos tanto os que estavam fora como os que moram em outros estados do Brasil), foi ótimo rever o pessoal do JavaCE que foram numa caravana enorme para o QCon, o Handerson Frota, o Celso Martins, o Danilo Sato que atualmente está na Europa, a Loiane (IBM), o Diego Plentz, Bruno Borges de Wicket, o Fabio Akita, Luca Bastos, Christiano Milfont, Lucas Cavalcanti, Maurício Linhares, Fernando Boaglio, Washington Botelho, Bruno Oliveira, Alberto Luiz Souza, Cristiano Sanchez, Jean Donato, Alexandre Freire, Marcelo Tozzi,  o pessoal do GURUSP, do CafeComJava (Alexandre Saudate, Rafael Afonso, Léo Biscassi e Christian Reichel), muitos amigos do GUJ (incluindo os desaparecidos como Fernando Meyer, Fábio Kung e o Daniel Destro) e é claro está de Parabéns novamente pela organização a CAELUM, revi meus grandes amigos que considero como irmãos, o Paulo Silveira, o Guilherme Silveira, o Guilherme Moreira que atualmente cuida da Caelum no DF, o Nico Steppat (atualmente cuidando da Caelum RJ), o Sérgio Lopes, Luiz Bassi, Renata Bassi, Camila Farinho, Cecilia Fernandes, Adriano Almeida, Anderson Leite, David Paniz, Rubem Azenha, Douglas Campos (qmx), Gabriel Oliveira, José Donizetti, Raphael Lacerda, certeza que estou esquecendo pessoas... 


Sábado:

No Sábado assisti as palestras:
Jim Webber - Aprendizados de grandes sistemas HTTP-centric.

Sérgio Lopes - Por uma Web mais rápida: Técnicas de otimização de Sites
Danilo Sato - Refatoração em larga escala

Guilherme Silveira - Design de código: a qualidade que faz a diferença
Daniel Destro -
Arquitetura de um sistema crítico de alta disponibilidade com soluções open source
Raphael Lacerda - Além do CDI com Seam 3
Daniel Sobral - Akka - Uma plataforma para o desenvolvimento de sistemas concorrentes e distribuídos para a JVM 
 

Lightning Talks

Christian Reichel - Por um Java mais funcional

José Donizetti - Dicas para testar código legado.
Eder Ignatowicz - Desenvolvimento Ágil Orientado a Testes: Como a busca pela qualidade transformou uma equipe de desenvolvimento Java
Daniel Cukier - Desenvolvendo sua infra-estrutura com testes
Handerson Frota - Aceite os testes de aceitação
Eduardo Bregaida - Cultura da Empresa - um problema na Adoção Ágil 

Eu adorei ter tido a oportunidade no QCon de apresentar um Lightning, achei que ia estourar o tempo, no final ainda sobrou um minuto e quarenta e um segundos rs ;D

Depois fomos para o hora extra no bar Opção continuar o networking.

Domingo:

As palestras que assisti no domingo foram:
Kunal Bhasin - Caching e NoSQL? 
Khawaja Shams - MythBusters - Mission Cloud Computing @ NASA
Nelson Haraguchi -  Escalando e Otimizando Projetos Legados
Saulo Arruda -  5 anos em 1 - aprendendo a empreender
Cecilia Fernandes - Melhorando um ambiente ágil
Fernando de la Riva -  Lean Startups
Cristiano Sanchez e Wladimir Domingues - Aplicações Móveis Híbridas: usando Web e Nativo juntos

Final das contas, o evento superou o de 2010, vale cada centavo, aprendi muitas táticas algumas que já comecei utilizar na empresa, o QConSP é um evento que se mostrou eficaz e de grande valia, não só por essas ótimas palestras, mas também pelo networking, rever os amigos que não estão por perto e conhecer as pessoas que normalmente conversamos apenas pelo fórum ou através de emails, messengers e afins...
Parabéns Caelum por mais esse sucesso.

Ano que vem tem mais QConSP.

Nos vemos lá =)