78
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/

Desenvolvimento Dirigido por Testes com Junit

Embed Size (px)

DESCRIPTION

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/).

Citation preview

Page 1: Desenvolvimento Dirigido por Testes com Junit

Desenvolvimento Dirigido por Testes com JUnit

Adolfo NetoDAINF-UTFPR

http://bit.ly/ADOLFO_NETO

Apresentado naVII SEMINFO

Semana Acadêmica de Informática da UTFPRhttp://seminfo7.dainf.ct.utfpr.edu.br/

Page 2: Desenvolvimento Dirigido por Testes com Junit

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/).

Page 3: Desenvolvimento Dirigido por Testes com Junit

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

Page 4: Desenvolvimento Dirigido por Testes com Junit

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?

Page 5: Desenvolvimento Dirigido por Testes com Junit

O que é TDD?

Page 6: Desenvolvimento Dirigido por Testes com Junit

Exemplo Primeiro

● Definições básicas:– Testes

– Anotações

● Exemplo no Eclipse

Page 7: Desenvolvimento Dirigido por Testes com Junit

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) :)

Page 8: Desenvolvimento Dirigido por Testes com Junit

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.

Page 9: Desenvolvimento Dirigido por Testes com Junit

Primeiro teste

● Criar classe TestesCalculadora:

public class TestesCalculadora

Page 10: Desenvolvimento Dirigido por Testes com Junit

Primeiro teste

● Criar método testaAdicao:

@Test

public void testaAdicao(){

assertEquals("Resultado da soma de 3 e 4 é 7", 7, Calculadora.soma(3,4));

}

Page 11: Desenvolvimento Dirigido por Testes com Junit

EXECUTAR O TESTE PARA VÊ-LO FALHAR!!!

Page 12: Desenvolvimento Dirigido por Testes com Junit
Page 13: Desenvolvimento Dirigido por Testes com Junit

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;

}

Page 14: Desenvolvimento Dirigido por Testes com Junit

EXECUTAR O TESTE E VÊ-LO DAR CERTO

Page 15: Desenvolvimento Dirigido por Testes com Junit
Page 16: Desenvolvimento Dirigido por Testes com Junit

Refatoração

● Analisar o código escrito (inclusive o código de teste) e ver se há necessidade de refatoração.

Page 17: Desenvolvimento Dirigido por Testes com Junit

Segundo teste

@Test

public void testaMultiplicacao(){

assertEquals("Resultado da multiplicação de 3 e 4 é 12", 11, Calculadora.mult(3,4));

}

Page 18: Desenvolvimento Dirigido por Testes com Junit

Código para o segundo teste

public static int mult(int i, int j) {

return i*j;

}

Page 19: Desenvolvimento Dirigido por Testes com Junit

Terceiro teste

@Test

public void testaDivisao(){

assertEquals("Resultado da divisão inteira de 4 por 3 é 1", 1, Calculadora.div(4,3));

}

Page 20: Desenvolvimento Dirigido por Testes com Junit

Código para o terceiro teste

public static int div(int i, int j) {

return i/j;

}

Page 21: Desenvolvimento Dirigido por Testes com Junit

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));

}

Page 22: Desenvolvimento Dirigido por Testes com Junit

Código para o quarto teste

● Não é necessário. Após executar o quarto teste verifica-se que a funcionalidade já está implementada!

Page 23: Desenvolvimento Dirigido por Testes com Junit

Quinto teste

@Test

public void testaSubtração(){

assertEquals("Resultado da subtração de 1 por 2 é -1", -1, Calculadora.sub(1,2));

}

Page 24: Desenvolvimento Dirigido por Testes com Junit

Código para o quinto teste

public static int sub(int i, int j) {

return soma(i,-j);

}

Page 25: Desenvolvimento Dirigido por Testes com Junit

Código para o quinto teste (refatorado)

public static int sub(int i, int j) {

return i-j;

}

Page 26: Desenvolvimento Dirigido por Testes com Junit

Sexto teste

@Test

public void testaExponenciacao(){

assertEquals(1, Calculadora.exp(1,0));

}

Page 27: Desenvolvimento Dirigido por Testes com Junit

Código para sexto teste

public static Object exp(int i, int j) {

return Math.pow(i, j);

}

Page 28: Desenvolvimento Dirigido por Testes com Junit

Código para sexto teste

public static Object exp(int i, int j) {

return Math.pow(i, j);

}

RESULTADO: ERRO!

Math.pow retorna double.

Page 29: Desenvolvimento Dirigido por Testes com Junit

Código para sexto teste (consertado)

public static int exp(int i, int j) {

return (int)Math.pow(i, j);

}

Page 30: Desenvolvimento Dirigido por Testes com Junit

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));

}

Page 31: Desenvolvimento Dirigido por Testes com Junit

Sétimo teste

@Test(expected = ArithmeticException.class)

public void testaExponenciacaoExpoentesNegativos() {

assertEquals(0, Calculadora.exp(2, -3));

assertEquals(0, Calculadora.exp(0, -3));

}

Page 32: Desenvolvimento Dirigido por Testes com Junit

Sétimo teste

● FALHA com o código atual!

● Não devemos permitir expoentes negativos.

Page 33: Desenvolvimento Dirigido por Testes com Junit

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!");

}

Page 34: Desenvolvimento Dirigido por Testes com Junit

FIM DO EXEMPLO

Page 35: Desenvolvimento Dirigido por Testes com Junit

Origem

● Nasa – década de 1960● Manifesto Ágil (2001)● Kent Beck (Extreme Programming)

– Livros

– SUnit (para Smalltalk)

– Junit (para Java)

– xUnit

Page 36: Desenvolvimento Dirigido por Testes com Junit

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...

Page 37: Desenvolvimento Dirigido por Testes com Junit

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.

Page 38: Desenvolvimento Dirigido por Testes com Junit

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

Page 39: Desenvolvimento Dirigido por Testes com Junit

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.

Page 40: Desenvolvimento Dirigido por Testes com Junit

O PROCESSO EM IMAGENS

Page 41: Desenvolvimento Dirigido por Testes com Junit

Fonte: http://upload.wikimedia.org/wikipedia/en/9/9c/Test-driven_development.PNG

Page 42: Desenvolvimento Dirigido por Testes com Junit

Fonte: http://www.agiledata.org/essays/tdd.html

The steps of Test-First Design

TDD = Refactoring + TFD

Page 43: Desenvolvimento Dirigido por Testes com Junit
Page 44: Desenvolvimento Dirigido por Testes com Junit

Como fazer TDD com JUnit?

Page 45: Desenvolvimento Dirigido por Testes com Junit

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

Page 46: Desenvolvimento Dirigido por Testes com Junit

Detalhes Junit 4.x

● Versão mais nova: 4.8.2● Disponível para Eclipse/Netbeans● Usa anotações

Page 47: Desenvolvimento Dirigido por Testes com Junit

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

Page 48: Desenvolvimento Dirigido por Testes com Junit

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(){

...

}

Page 49: Desenvolvimento Dirigido por Testes com Junit

Anotação @Test

● Escolher bons nomes para os métodos de teste– Significativos

– Podem ser longos

● Exemplos:– putThenGet (Kent Beck)– testInvokeSuiteOnNonSubclassOfTestCase (JUnit)

Page 50: Desenvolvimento Dirigido por Testes com Junit

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.

Page 51: Desenvolvimento Dirigido por Testes com Junit

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

Page 52: Desenvolvimento Dirigido por Testes com Junit

Outros Asserts

● assertArrayEquals● assertTrue e assertFalse● assertNull e assertNotNull● assertSame e assertNotSame● assertThat

Page 53: Desenvolvimento Dirigido por Testes com Junit

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

Page 54: Desenvolvimento Dirigido por Testes com Junit

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

Page 55: Desenvolvimento Dirigido por Testes com Junit

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));

}

Page 56: Desenvolvimento Dirigido por Testes com Junit

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);

}}

Page 57: Desenvolvimento Dirigido por Testes com Junit

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

Page 58: Desenvolvimento Dirigido por Testes com Junit

Suítes de Testes

● Exemplo:

@RunWith(Suite.class)

@SuiteClasses({TestesCalculadora.class, TestesPerformanceCalculadora.class})

public class SuiteTestesCalculadora {

}

Page 59: Desenvolvimento Dirigido por Testes com Junit

Mais

● Testes parametrizados– @RunWith(Parameterized.class)

– @Parameters

– Exemplo

Page 60: Desenvolvimento Dirigido por Testes com Junit

Reflexões

Page 61: Desenvolvimento Dirigido por Testes com Junit

Fluxo do Desenvolvimento

● (a) fluxo com testes por último (tradicional)● (b) fluxo com testes antes (TDD)

Page 62: Desenvolvimento Dirigido por Testes com Junit

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)

Page 63: Desenvolvimento Dirigido por Testes com Junit

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”

Page 64: Desenvolvimento Dirigido por Testes com Junit

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)

Page 65: Desenvolvimento Dirigido por Testes com Junit
Page 66: Desenvolvimento Dirigido por Testes com Junit

Parte Final

Page 67: Desenvolvimento Dirigido por Testes com Junit

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

Page 68: Desenvolvimento Dirigido por Testes com Junit

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 2010http://www.agilebrazil.com/2010/pt/index.html

Page 69: Desenvolvimento Dirigido por Testes com Junit

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

Page 70: Desenvolvimento Dirigido por Testes com Junit

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

Page 71: Desenvolvimento Dirigido por Testes com Junit

Dúvidas, perguntas, sugestões?

Adolfo NetoDAINF-UTFPR

http://bit.ly/ADOLFO_NETO

Page 72: Desenvolvimento Dirigido por Testes com Junit

Slides Extras

Page 73: Desenvolvimento Dirigido por Testes com Junit

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?

Page 74: Desenvolvimento Dirigido por Testes com Junit

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

Page 75: Desenvolvimento Dirigido por Testes com Junit

Development Flow

● Development flow: – (a) traditional test-last and

– (b) test-driven development/test-first flow.

Page 76: Desenvolvimento Dirigido por Testes com Junit

Blame

● Name should be “test-driven design.”

Page 77: Desenvolvimento Dirigido por Testes com Junit

Concepções errôneas

● #1: TDD equals automated testing. ● #2: TDD means write all tests first.

Page 78: Desenvolvimento Dirigido por Testes com Junit

Concepção correta

● "TDD’s primary purpose (...) is design"