Upload
internet
View
121
Download
0
Embed Size (px)
Citation preview
Test Driven DevelopmentTest Driven DevelopmentEloi Rocha Neto, 06/10/2007
3
Introdução• Por que precisamos testar?
– Como saber se o que fizemos está correto ou não?
– Como garantir se o que está compilado funciona?
– Será que é possível um projeto estar concluído se não tiver sido testado?
4
Introdução• Como testamos nosso código?
– testes manuais? – e quando o código fica muito grande?– e quando fazemos mudanças no nosso
código, teremos que testar tudo novamente?
• podemos esquecer de testar algo importante!!!
– e quando encontramos um bug, o que isso significa?
5
Introdução• O que queremos?
– queremos fazer alterações em nosso código, e saber, ao final, se inserimos algum bug no código
– não queremos perder conhecimento importante sobre como testar o código
– queremos testes automáticos– queremos um botão mágico que roda todos
os testes automaticamente e informa se eles passaram ou não!
6
Introdução• Por que testes automáticos são
importantes?– dão coragem para mudar (podem ser
alterados sem medo)– códigos frequentemente testados são mais
confiáveis– testes representam patrimônio da empresa– testes podem ser interpretados como uma
parte da documentação
7
Introdução• Por que testes automáticos são
importantes? (cont.)– se todos os requisitos do sistema forem
transformados em testes, então o projeto estará pronto, quando todos os testes passarem
8
Introdução• Existem vários tipos de testes
– Testes de Unidade– Testes de Regressão– Testes de Integração– Testes Funcionais
• Foco: Testes de Unidade
9
Introdução• Do que precisamos para começar?
– Um ferramenta que nos auxilie a desenvolver e testar nossos testes de unidade
10
JUnit
• Um framework para construção / execução de testes de unidade em Java
• Como funciona?– Criamos uma classe e escrevemos um conjunto
de métodos contendo verificações– Cada verificação avalia se o comportamento do
código sendo testado é o esperado• Exemplo: se o resultado de um método que realizada
a soma de “3 + 4” é igual a “7”.
JUnit• Como funciona? (cont.)
• Requisitos que um teste deve atender:– Cada método de teste deve possuir a anotação
@Test
– Quando for fazer uma asserção dentro do método, utilizar um conjunto de métodos disponibilizados pelo JUnit; entre eles:
» assertTrue, assertFalse, assertSame, assertNull, assertNotNull, …
Esses métodos devem ser importados estaticamente de org.junit.Assert.*
12
JUnit• Seja a seguinte classe:public class Calculadora {
public int somar(int a,int b) {return a + b;
}}
13
JUnit• Seja um teste para a classe Calculadora:...import static org.junit.Assert.assertEquals;import static org.junit.Assert.assertTrue;
public class MeuPrimeiroTeste {@Test public void somar() {
Calculadora calc = new Calculadora();assertTrue( calc.somar(3,45) == 48 );assertEquals( 9, calc.dividir(18,2) );
}...@Test public void ...
}
JUnit• Outras anotações que também podem ser
utilizadas em um método de teste:– @Before– @After– @BeforeClass– @AfterClass– @Test (expected=Exception.class)– @Test (timeout=int)– @Ignore
JUnit• Exemplo:
...@Test(expected=DivisaoPorZeroException.class) public void dividirPorZero() {
int n = 2 / 0; }@Before public void zerarConta() {
conta = new Conta(); } @After public void fecharConexao() {
conexao.close(); }
...
16
JUnit• Comentários importantes
– quando testamos, não podemos ter pena do código
• o cliente não terá!
– precisamos esquecer um pouco do nosso afeto ao bebê!!!
– precisamos testar:• entradas erradas / inconsistentes / nulas• precisamos avaliar todas as facetas do código!!!• Idealmente, monte um fluxograma contendo tudo
a ser testado!
17
JUnit• Lembrem que da mesma forma que
queremos nosso código limpo, nossos testes também devem estar
• Código limpo é mais fácil de entender
• Um teste seguindo boas práticas de programação fica mais claro, permite testar mais com menos linhas de código
18
JUnit• Como rodamos um teste?
– Precisamos executar o TestRunner• executa todos os métodos que possuem a
anotação @Test• se existir um método com a anotação
@Before/@After, ele será executado antes/depois de cada teste
• se existir um método com a anotação @BeforeClass/@AfterClass, ele será executado no início/final do teste (só será executado uma vez)
19
JUnit• Usando linha de comando:
– java -cp junit-4.4.jar;. junit.swingui.Test MeuTest
20
JUnit• Pergunta: quando escrever os testes?
– Escrever o código todo e depois testar?– Escrever o código e testar ao mesmo tempo?– Escrever os testes e depois codificar?!?
21
TDD• Test Driven Development (TDD) é uma
técnica de desenvolvimento de software cujo mantra consiste em escrever um teste, escrever um código simples para fazer o teste passar e, ao final, refatorar o código.
22
TDD• Mantra do
TDD:– Escrever um
teste
– Codificar o mínimo o possível para o teste passar
– Refatorar
23
TDD
• Testes devem ser feitos em pequenos passos
• Nunca se codifica sem ter um teste antes!– se não, ele volta e pega você!
• Quando encontrar um bug, crie um teste antes que prove a existência do bug, depois corrija-o.
24
TDD• Testes: documentação executável!
– Execute-os periodicamente– Use nomes apropriados– Mantenha-os simples
• Todas as asserções do JUnit possui um argumento para descrever o que está sendo testado– assertEquals( “Saldo não é zero!”, 0,
conta.getSaldo() );– assertNull( “Conta não é Null!” , conta );
25
TDD• Quando escrevemos um teste antes de
codificar estamos pensando em:– design– teste– documentação
TDD• Problema: deseja-se construir um sorteador com
os seguintes requisitos:– Um jogador poderá fazer diversas apostas (cada aposta
consiste de quatro números)• Custo de uma aposta para o jogador: R$ 10,00
• Não pode existir números repetidos na aposta
• Intervalo de números possíveis: [1, 2, 3, ..., 20]
– Saldo inicial do sorteador é R$100,00
– Quando o jogador é sorteado, isto é, o quarteto apostado é o sorteado, todo dinheiro do sorteador passa a ser do jogador.
– Caso mais de um jogador seja sorteado, o prêmio é dividido.
27
TDD• Quando estamos escrevendo testes, o
que nós realmente queremos?– testes bem focados: queremos testes partes
específicas de nossas aplicações;– testes independentes: queremos que nossos
testes rodem em qualquer ordem e a qualquer momento;
– testes rápidos: queremos que nossos testes sejam rodados frequentemente.
28
TDD• Infelizmente, o mundo é cruel e nossas
vontades se deparam com as seguintes dificuldades:– testes bem focados implicam em uma grande
quantidade de testes;– torná-los independentes necessite de uma forma
eficiente de limpar os objetos utilizados (uma vez que esses objetos podem ser utilizados por outros testes);
– testar partes isoladas de aplicações complexas não é uma tarefa trivial
29
TDD• Mock Objects tem o objetivo de simplificar ou
amenizar esta problemática.• Mock Objects são utilizados quando é difícil ou
impossível criar um determinado estado do sistema sendo testado, ou quando o acesso ao recurso é limitado.
• O princípio básico atrás de mocks é criar objetos leves e controláveis para simplificar a construção de seus testes.
30
TDD• Devemos criar mocks nas seguintes
situações:– Deixar os testes mais focados– Fazer com que os testes rodem mais rápidos– Simplificar o desenvolvimento de aplicações que
conversam com hardware, dispositivos remotos, ou mesmo, com outras aplicações.
31
TDD• Devemos criar mocks nas seguintes
situações (cont.):– Promover um desenvolvimento baseado em uma
interface– Encorajar o uso de composição em vez de
herança– Testar situações incomuns
Muito obrigado pela atenção!