Desenvolvimento Dirigido por Testes com Junit

5.687 visualizações

Publicada em

O objetivo desta palestra é apresentar como funciona o desenvolvimento dirigido por testes (TDD, do termo em inglês "test-driven development"), uma técnica de projeto de software utilizada principalmente em métodos ágeis para o desenvolvimento de software. Além disso, serão mostrados exemplos práticos de como desenvolver sofwtare utilizando TDD com o auxílio do framework open source JUnit (http://junit.sourceforge.net/).

Publicada em: Educação
1 comentário
2 gostaram
Estatísticas
Notas
  • Muito bom, professor. Gostei desse padrão de projeto!
       Responder 
    Tem certeza que deseja  Sim  Não
    Insira sua mensagem aqui
Sem downloads
Visualizações
Visualizações totais
5.687
No SlideShare
0
A partir de incorporações
0
Número de incorporações
23
Ações
Compartilhamentos
0
Downloads
217
Comentários
1
Gostaram
2
Incorporações 0
Nenhuma incorporação

Nenhuma nota no slide

Desenvolvimento Dirigido por Testes com Junit

  1. 1. Desenvolvimento Dirigido por Testes com JUnit Adolfo Neto DAINF-UTFPR http://bit.ly/ADOLFO_NETO Apresentado na VII SEMINFO Semana Acadêmica de Informática da UTFPR http://seminfo7.dainf.ct.utfpr.edu.br/
  2. 2. Resumo O objetivo desta palestra é apresentar como funciona o desenvolvimento dirigido por testes (TDD, do termo em inglês "test-driven development"), uma técnica de projeto de software utilizada principalmente em métodos ágeis para o desenvolvimento de software. Além disso, serão mostrados exemplos práticos de como desenvolver sofwtare utilizando TDD com o auxílio do framework open source JUnit (http://junit.sourceforge.net/).
  3. 3. Abreviações ● Test-driven development = TDD ● Desenvolvimento dirigido por testes = DDT? – Prefiro usar TDD, pois ninguém usa DDT, que tem outro significado em português ● Junit ● XUnit
  4. 4. Pesquisa Informal ● Quem aqui desenvolve (empresa/estudos)? – Em Java? ● Quem já sabe o que é TDD? ● Quem sabe o que são métodos ágeis? ● Quem conhece e já usou o Junit? – Na versão 4.* ● Alguém usa porque é padrão da empresa?
  5. 5. O que é TDD?
  6. 6. Exemplo Primeiro ● Definições básicas: – Testes – Anotações ● Exemplo no Eclipse
  7. 7. Roteiro: dez minutos (ideais) na vida de um programador que usa TDD ● Escreve um teste :| ● Roda o teste para vê-lo falhar (barra vermelha) ou sequer compilar :( ● Escreve a funcionalidade que faz o teste passar :| ● Roda o teste e o teste passa (barra verde) :) ● Refatora o código :| ● Roda o teste e o teste passa (barra verde) :)
  8. 8. Exemplo: Calculadora ● Estupidamente simples, de modo que qualquer um possa entender o código. ● Calculadora que aceita apenas números inteiros e cujos resultados são inteiros. ● Operações: adição, multiplicação, divisão, subtração, exponenciação.
  9. 9. Primeiro teste ● Criar classe TestesCalculadora: public class TestesCalculadora
  10. 10. Primeiro teste ● Criar método testaAdicao: @Test public void testaAdicao(){ assertEquals("Resultado da soma de 3 e 4 é 7", 7, Calculadora.soma(3,4)); }
  11. 11. EXECUTAR O TESTE PARA VÊ-LO FALHAR!!!
  12. 12. Escrever código que faz passar no teste ● Criar classe Calculadora ● Criar método soma: public static int soma (int a, int b){ return a+b; }
  13. 13. EXECUTAR O TESTE E VÊ-LO DAR CERTO
  14. 14. Refatoração ● Analisar o código escrito (inclusive o código de teste) e ver se há necessidade de refatoração.
  15. 15. Segundo teste @Test public void testaMultiplicacao(){ assertEquals("Resultado da multiplicação de 3 e 4 é 12", 11, Calculadora.mult(3,4)); }
  16. 16. Código para o segundo teste public static int mult(int i, int j) { return i*j; }
  17. 17. Terceiro teste @Test public void testaDivisao(){ assertEquals("Resultado da divisão inteira de 4 por 3 é 1", 1, Calculadora.div(4,3)); }
  18. 18. Código para o terceiro teste public static int div(int i, int j) { return i/j; }
  19. 19. Quarto teste @Test(expected=ArithmeticException.class) public void testaDivisaoPorZero(){ assertEquals("Resultado da divisão inteira de 4 por 0 é indefinido", 0, Calculadora.div(4,0)); }
  20. 20. Código para o quarto teste ● Não é necessário. Após executar o quarto teste verifica-se que a funcionalidade já está implementada!
  21. 21. Quinto teste @Test public void testaSubtração(){ assertEquals("Resultado da subtração de 1 por 2 é -1", -1, Calculadora.sub(1,2)); }
  22. 22. Código para o quinto teste public static int sub(int i, int j) { return soma(i,-j); }
  23. 23. Código para o quinto teste (refatorado) public static int sub(int i, int j) { return i-j; }
  24. 24. Sexto teste @Test public void testaExponenciacao(){ assertEquals(1, Calculadora.exp(1,0)); }
  25. 25. Código para sexto teste public static Object exp(int i, int j) { return Math.pow(i, j); }
  26. 26. Código para sexto teste public static Object exp(int i, int j) { return Math.pow(i, j); } RESULTADO: ERRO! Math.pow retorna double.
  27. 27. Código para sexto teste (consertado) public static int exp(int i, int j) { return (int)Math.pow(i, j); }
  28. 28. Complementando o sexto teste @Test public void testaExponenciacao(){ assertEquals(1, Calculadora.exp(1,0)); assertEquals(4, Calculadora.exp(2,2)); assertEquals(27, Calculadora.exp(3,3)); assertEquals(0, Calculadora.exp(0,3)); }
  29. 29. Sétimo teste @Test(expected = ArithmeticException.class) public void testaExponenciacaoExpoentesNegativos() { assertEquals(0, Calculadora.exp(2, -3)); assertEquals(0, Calculadora.exp(0, -3)); }
  30. 30. Sétimo teste ● FALHA com o código atual! ● Não devemos permitir expoentes negativos.
  31. 31. Código para o sétimo (e último) teste public static int exp(int i, int j) { if (j >= 0) return (int) Math.pow(i, j); else throw new ArithmeticException("Expoentes negativos não são permitidos!"); }
  32. 32. FIM DO EXEMPLO
  33. 33. Origem ● Nasa – década de 1960 ● Manifesto Ágil (2001) ● Kent Beck (Extreme Programming) – Livros – SUnit (para Smalltalk) – Junit (para Java) – xUnit
  34. 34. Manifesto para Desenvolvimento Ágil de Software Estamos descobrindo maneiras melhores de desenvolver software, fazendo-o nós mesmos e ajudando outros a fazerem o mesmo. Através deste trabalho, passamos a valorizar: Indivíduos e interações mais que processos e ferramentas Software em funcionamento mais que documentação abrangente Colaboração com o cliente mais que negociação de contratos Responder a mudanças mais que seguir um plano continua...
  35. 35. Manifesto para Desenvolvimento Ágil de Software Ou seja, mesmo havendo valor nos itens à direita, valorizamos mais os itens à esquerda. Kent Beck, Mike Beedle, Arie van Bennekum, Alistair Cockburn, Ward Cunningham, Martin Fowler, James Grenning, Jim Highsmith, Andrew Hunt, Ron Jeffries, Jon Kern, Brian Marick, Robert C. Martin, Steve Mellor, Ken Schwaber, Jeff Sutherland, Dave Thomas © 2001, os autores acima esta declaração pode ser copiada livremente em qualquer formato, mas somente integralmente através desta declaração.
  36. 36. Frases ● “Nunca escreva uma linha de código funcional sem um caso de teste quebrado.” —Kent Beck ● “Codificação com testes-primeiro não é uma técnica de testes.” —Ward Cunningham
  37. 37. Observações ● É uma técnica ágil – Não obrigatoriamente deve ser feita em conjunto com uma metodologia ágil. ● É uma técnica de projeto (design)! – Não é uma técnica para fazer testes.
  38. 38. O PROCESSO EM IMAGENS
  39. 39. Fonte: http://upload.wikimedia.org/wikipedia/en/9/9c/Test-driven_development.PNG
  40. 40. The steps of Test-First Design TDD = Refactoring + TFD Fonte: http://www.agiledata.org/essays/tdd.html
  41. 41. Como fazer TDD com JUnit?
  42. 42. JUnit * ● O JUnit é um arcabouço livre para a criação de testes unitários. ● Dá apoio à criação de testes automatizados na linguagem de programação Java. ● Foi criado por Eric Gamma e Kent Beck. ● Licença: Common Public License v 1.0 ● Código-fonte no GitHub * Arcabouço = framework
  43. 43. Detalhes Junit 4.x ● Versão mais nova: 4.8.2 ● Disponível para Eclipse/Netbeans ● Usa anotações
  44. 44. Classe de Testes ● Uma classe exclusiva para testar – Contém apenas código de testes ● No Junit 4, não precisa estender nenhuma outra classe (no 3 precisava) ● Geralmente colocada numa pasta separada (por exemplo, test) da pasta do código de produção (src) – Não precisa ser usada na geração do jar para o cliente
  45. 45. Anotação @Test ● Colocar “@Test” antes da declaração do método – @org.junit.Test ● O método deve ser público ● Exemplo: @Test public void nomeDoTeste(){ ... }
  46. 46. Anotação @Test ● Escolher bons nomes para os métodos de teste – Significativos – Podem ser longos ● Exemplos: – putThenGet (Kent Beck) – testInvokeSuiteOnNonSubclassOfTestCase (JUnit)
  47. 47. Asserts ● Métodos que são acompanhados pelo JUnit ● Fazem a barra ficar verde ou vermelha ● import static org.junit.Assert.*; ● Dicionário Michaelis: ● assert vt 1 afirmar, declarar, asseverar. 2 insistir (em um ponto de vista), defender, vindicar, reivindicar, pugnar por. to assert oneself a) perseverar(-se). b) reivindicar seus direitos e exigir seu reconhecimento. c) vencer. d) comportar-se de modo a chamar a atenção.
  48. 48. AssertEquals ● 2 parâmetros obrigatórios: Valor esperado e Valor calculado ● 1 parâmetro opcional: mensagem ● Variações - 6 assinaturas – tipos dos parâmetros: – long – double – Object
  49. 49. Outros Asserts ● assertArrayEquals ● assertTrue e assertFalse ● assertNull e assertNotNull ● assertSame e assertNotSame ● assertThat
  50. 50. Anotações @Before e @After ● Usados quando temos muitos testes com os mesmos objetos ● Métodos com @Before são executados antes de todo método com @Test ● Métodos com @After são executados antes de todo método com @Test
  51. 51. Anotações @BeforeClass e @AfterClass ● “Às vezes vários testes precisam compartilhar uma configuração computacionalmente cara (por exemplo, logar-se num BD). ● Apesar disto poder comprometer a independência dos testes, pode ser uma otimização necessária.” ● Métodos com @BeforeClass são executados uma única vez antes de todos os métodos com @Test ● Métodos com @AfterClass são executados uma única vez depois de todos os métodos com @Test
  52. 52. Capturando exceções: expected ● Permite verificar se métodos corretamente lançam exceções em casos de erro ● @Test(expected=NomedaClassedaExceção.class) ● Exemplo: @Test(expected=ArithmeticException.class) public void testaDivisaoPorZero(){ assertEquals("Resultado da divisão inteira de 4 por 0 é indefinido", 0, Calculadora.div(4,0)); }
  53. 53. Verificando performance: timeout ● Permite verificar se um teste roda no tempo mínimo permitido ● @Test(timeout=<tempo_em_milisegundos>) ● Exemplo: @Test(timeout=6) public void testaDesempenho(){ for (int i=1; i<100000;i++){ Calculadora.mult(i, i); }}
  54. 54. Suítes de Testes ● Permitem executar várias classes de testes de uma vez só. ● Anotações: @RunWith: identifica a classe que executa suítes de testes @SuiteClasses: lista as classes de teste a serem incluídas na suíte
  55. 55. Suítes de Testes ● Exemplo: @RunWith(Suite.class) @SuiteClasses({TestesCalculadora.class, TestesPerformanceCalculadora.class}) public class SuiteTestesCalculadora { }
  56. 56. Mais ● Testes parametrizados – @RunWith(Parameterized.class) – @Parameters – Exemplo
  57. 57. Reflexões
  58. 58. Fluxo do Desenvolvimento ● (a) fluxo com testes por último (tradicional) ● (b) fluxo com testes antes (TDD)
  59. 59. Problemas ● Nem todo mundo que acha que faz TDD realmente está fazendo TDD – TDD diferente de testes unitários automatizados ● Nem todo mundo que faz TDD está fazendo TDD da melhor forma possível ● Não há nenhuma comprovação científica de que TDD melhore a qualidade do código ou a produtividade dos desenvolvedores (mas existem algumas evidências)
  60. 60. Concepções errôneas 1) “TDD é igual a testes automatizados” 2) “TDD significa (apenas) escrever todos os testes antes do código” 3)“Se faço TDD não preciso testar depois” 4)“Todo o projeto do software consiste nos testes” 5)“Apenas testes unitários são necessários”
  61. 61. Concepção correta ● "TDD’s primary purpose (...) is design" ● Mas no nome está “test ...” ● Talvez o nome devesse ser projeto dirigido por testes (test-driven design). – Daí surgiu a variação/evolução BDD (Behaviour-Driven Development)
  62. 62. Parte Final
  63. 63. Conclusões ● Por que fazer TDD? ● TDD realmente aumenta a produtividade? ● TDD realmente aumenta a qualidade do código? – Estude bem como se faz e faça o teste você mesmo ● Outros frameworks para TDD em Java ● TDD em outras linguagens
  64. 64. Mais sobre Métodos Ágeis ● http://adolfoneto.wikidot.com/metodologias-ageis – Ou adolfo neto métodos ágeis no Google ● Destaque: – http://agilcoop.org.br/ – Agile Brazil 2010 http://www.agilebrazil.com/2010/pt/index.html
  65. 65. Divulgação ● VII Semana de Informática da UTFPR – http://twitter.com/seminfo7utfpr ● Mestrado Profissional em Computação Aplicada – http://www.ppgca.ct.utfpr.edu.br – http://bit.ly/PPGCA
  66. 66. Divulgação ● Departamento Acadêmico de Informática – Sistemas de Informação – Engenharia de Computação ● 88 vagas anuais em cada curso (desde 2010 via SISU/ENEM) ● Vagas de transferência todo semestre (geralmente não ocupadas) – Especialização em Tecnologia Java – Especialização em Gestão de Tecnologia da Informação
  67. 67. Dúvidas, perguntas, sugestões? Adolfo Neto DAINF-UTFPR http://bit.ly/ADOLFO_NETO
  68. 68. Slides Extras
  69. 69. Testes mais complexos ● Lógica multi-valorada: – L3: 0: falso, 1/2, 1: verdadeiro – ¬(0)=1, ¬(1/2)=1/2, ¬(1)=0 – ∧(1,1)=1 – E resto da tabela-verdade do E?
  70. 70. Mais Frases ● “The act of writing a unit test is more an act of design than of verification. It is also more an act of documentation than of verification. The act of writing a unit test closes a remarkable number of feedback loops, the least of which is the one pertaining to verification of function”. ● Bob Martin
  71. 71. Development Flow ● Development flow: – (a) traditional test-last and – (b) test-driven development/test-first flow.
  72. 72. Blame ● Name should be “test-driven design.”
  73. 73. Concepções errôneas ● #1: TDD equals automated testing. ● #2: TDD means write all tests first.
  74. 74. Concepção correta ● "TDD’s primary purpose (...) is design"

×