desenvolvimento dirigido por testes com junit

Post on 29-Nov-2014

6.199 Views

Category:

Education

6 Downloads

Preview:

Click to see full reader

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

TRANSCRIPT

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/

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

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

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?

O que é TDD?

Exemplo Primeiro

● Definições básicas:– Testes

– Anotações

● Exemplo no Eclipse

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

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.

Primeiro teste

● Criar classe TestesCalculadora:

public class TestesCalculadora

Primeiro teste

● Criar método testaAdicao:

@Test

public void testaAdicao(){

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

}

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

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;

}

EXECUTAR O TESTE E VÊ-LO DAR CERTO

Refatoração

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

Segundo teste

@Test

public void testaMultiplicacao(){

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

}

Código para o segundo teste

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

return i*j;

}

Terceiro teste

@Test

public void testaDivisao(){

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

}

Código para o terceiro teste

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

return i/j;

}

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

}

Código para o quarto teste

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

Quinto teste

@Test

public void testaSubtração(){

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

}

Código para o quinto teste

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

return soma(i,-j);

}

Código para o quinto teste (refatorado)

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

return i-j;

}

Sexto teste

@Test

public void testaExponenciacao(){

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

}

Código para sexto teste

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

return Math.pow(i, j);

}

Código para sexto teste

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

return Math.pow(i, j);

}

RESULTADO: ERRO!

Math.pow retorna double.

Código para sexto teste (consertado)

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

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

}

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

}

Sétimo teste

@Test(expected = ArithmeticException.class)

public void testaExponenciacaoExpoentesNegativos() {

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

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

}

Sétimo teste

● FALHA com o código atual!

● Não devemos permitir expoentes negativos.

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

}

FIM DO EXEMPLO

Origem

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

– Livros

– SUnit (para Smalltalk)

– Junit (para Java)

– xUnit

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

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.

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

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.

O PROCESSO EM IMAGENS

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

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

The steps of Test-First Design

TDD = Refactoring + TFD

Como fazer TDD 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

Detalhes Junit 4.x

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

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

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

...

}

Anotação @Test

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

– Podem ser longos

● Exemplos:– putThenGet (Kent Beck)– testInvokeSuiteOnNonSubclassOfTestCase (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.

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

Outros Asserts

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

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

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

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

}

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

}}

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

Suítes de Testes

● Exemplo:

@RunWith(Suite.class)

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

public class SuiteTestesCalculadora {

}

Mais

● Testes parametrizados– @RunWith(Parameterized.class)

– @Parameters

– Exemplo

Reflexões

Fluxo do Desenvolvimento

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

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)

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”

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)

Parte Final

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

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

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

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

Dúvidas, perguntas, sugestões?

Adolfo NetoDAINF-UTFPR

http://bit.ly/ADOLFO_NETO

Slides Extras

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?

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

Development Flow

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

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

Blame

● Name should be “test-driven design.”

Concepções errôneas

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

Concepção correta

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

top related