Test Driven Development Eloi Rocha Neto, 06/10/2007

Preview:

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

<eloi.rocha@gmail.com>

Muito obrigado pela atenção!