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/).
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. 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. 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. 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?
6. Exemplo Primeiro
● Definições básicas:
– Testes
– Anotações
● Exemplo no Eclipse
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. 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. Primeiro teste
● Criar classe TestesCalculadora:
public class TestesCalculadora
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));
}
27. Código para sexto teste
public static Object exp(int i, int j) {
return Math.pow(i, j);
}
28. Código para sexto teste
public static Object exp(int i, int j) {
return Math.pow(i, j);
}
RESULTADO: ERRO!
Math.pow retorna double.
29. Código para sexto teste
(consertado)
public static int exp(int i, int j) {
return (int)Math.pow(i, j);
}
30. 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));
}
31. Sétimo teste
@Test(expected = ArithmeticException.class)
public void
testaExponenciacaoExpoentesNegativos() {
assertEquals(0, Calculadora.exp(2, -3));
assertEquals(0, Calculadora.exp(0, -3));
}
32. Sétimo teste
● FALHA com o código atual!
● Não devemos permitir expoentes negativos.
33. 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!");
}
35. Origem
● Nasa – década de 1960
● Manifesto Ágil (2001)
● Kent Beck (Extreme Programming)
– Livros
– SUnit (para Smalltalk)
– Junit (para Java)
– xUnit
36. 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...
38. 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
39. 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.
45. 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
46. Detalhes Junit 4.x
● Versão mais nova: 4.8.2
● Disponível para Eclipse/Netbeans
● Usa anotações
47. 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
48. 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(){
...
}
49. Anotação @Test
● Escolher bons nomes para os métodos de teste
– Significativos
– Podem ser longos
● Exemplos:
– putThenGet (Kent Beck)
– testInvokeSuiteOnNonSubclassOfTestCase (JUnit)
50. 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.
51. 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
52. Outros Asserts
● assertArrayEquals
● assertTrue e assertFalse
● assertNull e assertNotNull
● assertSame e assertNotSame
● assertThat
53. 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
54. 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
55. 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));
}
56. 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);
}}
57. 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
58. Suítes de Testes
● Exemplo:
@RunWith(Suite.class)
@SuiteClasses({TestesCalculadora.class,
TestesPerformanceCalculadora.class})
public class SuiteTestesCalculadora {
}
61. Fluxo do Desenvolvimento
● (a) fluxo com testes por último (tradicional)
● (b) fluxo com testes antes (TDD)
62. 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)
63. 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”
64. 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)
67. 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
68. 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
69. 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
70. 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
73. 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?
74. 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
75. Development Flow
● Development flow:
– (a) traditional test-last and
– (b) test-driven development/test-first flow.