SlideShare ist ein Scribd-Unternehmen logo
1 von 28
Downloaden Sie, um offline zu lesen
J820

Test-driven
Development
Helder da Rocha (helder@acm.org)

argonavis.com.br
TDD

argonavis.com.br

Metodologia de desenvolvimento guiada por testes
Objetivo: produzir "código limpo que funciona" [Beck]
Vantagens de produzir código desse tipo (precisa
enumerar?)
Você sabe quando terminou (e não precisa se preocupar
com uma longa fase de depuração de bugs): previsível!
Oportunidade de aprender todas as lições que o código
ensina (em vez de pegar a primeira solução que
aparecer e esquecer as outras)
Melhora as vidas dos usuários do seu software
Melhora as vidas dos membros da equipe
É bom escrever código limpo... mais ainda, se funciona!
2
Como escrever código limpo que funciona?
Várias forças nos afastam de código limpo e de código que
funciona. Como fugir delas?
Desenvolver com testes automáticos? TDD!

Em TDD...
Só se escreve uma nova linha de código se algum teste
automático falhar
Elimina-se duplicação o tempo todo

argonavis.com.br

Implicações
Design: código funcionando fornece feedback e orienta decisões
Temos que escrever nossos próprios testes: tempo
Ambiente de desenvolvimento usado deve responder rápido a
pequenas mudanças
Designs elaborados devem facilitar testes: componentes
pequenos, desacoplados, altamente coesos
3
Mantra TDD: Red/Green/Refactor
Ordem geral do desenvolvimento
Red: escreva um pequeno teste que não funciona (e
talvez nem compile)
Green: faça o teste rodar rapidamente, cometendo
quaisquer pecados necessários no processo
Refactor: elimine toda a duplicação criada em
meramente buscar o sucesso do teste

argonavis.com.br

Por que?
Ter trabalho adicional de escrever testes automáticos?
Trabalhar em pequenas etapas se você é capaz de dar
grandes saltos e resolver tudo rapidamente?

Coragem + comunicação + feedback + segurança
Qualidade, tempo, previsibilidade

4
Exemplo interativo de TDD

argonavis.com.br

Extraído do livro: "Test Driven Development", por Kent
Beck, parte I (páginas 3 a 87)
Estes slides apenas apresentam uma visão geral para
servir de base à demonstração em sala de aula
A demonstração será feita de forma interativa usando o
livro como guia, mas em "group programming",
portanto, pode ter resultados diferentes se a turma
seguir outro caminho
Use o livro para refazer o exemplo posteriormente e
explorar novas técnicas
Os slides mostram apenas os primeiros 3 (dos 17)
capítulos. A aula interativa irá um pouco além
5
Dinheiro em várias moedas
O problema
Lidar com uma aplicação que realiza operações em
dinheiro de moedas diferentes transparentemente

Exemplo (relatório de quotas de participação)
IBM
1000 quotas a
Novartis 400 quotas a
Total geral:

25 USD:
150 CHF*:

Total 25000 USD
Total 60000 CHF
65000 USD

argonavis.com.br

Para realizar as operações, precisamos ter uma taxa
de câmbio
1 USD = 2 CHF
Requisitos: anotados em nossa lista!
* CHF = Francos Suíços

6
Elaboração da lista de tarefas
Como solucionar este problema?
Que conjunto de testes irão demonstrar a presença do
código que irá gerar corretamente o relatório?

argonavis.com.br

Começamos anotando em nossa lista (to-do list)
Precisamos poder somar todas as quantidades em
moedas diferentes e converter o resultado dadas as
taxas de conversão de câmbio
Precisamos poder multiplicar uma quantidade (preço
por quota) por um número (quantidade de quotas) e
receber uma quantidade
Lista de tarefas
$5 + $10 CHF = $10 se taxa for 2:1
$5 * 2 = $10

Quando terminar uma, risque-a
Acrescente novas quando
necessário

7
Começaremos com a multiplicação
$5 + $10 CHF = $10 se taxa for 2:1
$5 * 2 = $10

Que objetos precisamos?
Não pense em objetos! Pense em testes!

Que testes precisamos?

argonavis.com.br

Pense em como a operação vai parecer pelo lado de
fora (conte uma estória)
Escreva o teste da forma mais simples
public void testMultiplication() {
Dollar five = new Dollar(5);
five.times(2);
assertEquals(10, five.amount);
}

Detectou problemas?
Não resolva agora. Coloque na lista!
...
Fazer "amount" private
Nao usar inteiros
Efeitos colaterais

8
O teste não compila!
Vamos consertar! Temos 4 erros
Não existe a classe Dollar
Não existe o construtor Dollar(int)
Não existe o método times(int)
Não existe o atributo amount

argonavis.com.br

Conserte um de cada vez, só para compilar (não
preencha métodos e construtores ainda)
class Dollar {
Dollar(int amount) {}
void times(int multiplier) {}
int amount;
}

Agora podemos rodar o teste e vê-lo falhar
9
A falha é um avanço!
Barra vermelha nos impele para buscar a barra verde!
Temos uma medida concreta de falha
O problema mudou de "Me dê uma solução para o
problema das múltiplas moedas!" para "Faça este teste
funcionar, e depois faça os outros funcionarem!"
Muito mais simples: reduzimos o "escopo do medo"

argonavis.com.br

Faça o teste passar!
A meta neste momento não é ter a resposta perfeita,
mas fazer o teste passar. Qual a menor mudança que
podemos fazer para alcançar isto?
class Dollar {
Dollar(int amount) {}
void times(int multiplier) {}
int amount = 10;
}

Trapaça! Mas funciona!
Temos uma barra verde!

10
Está verde, mas não está pronto!
Precisamos generalizar antes de prosseguir. O ciclo é o
seguinte

argonavis.com.br

Acrescente um pequeno teste
Rode todos os testes e assegure que falham
Faça uma pequena mudança
Rode todos os testes e assegure que passam
Refatore o código para remover duplicação (remover a
dependência entre o teste e o código - a duplicação é o
"sintoma" que indica essa dependência)

Onde está a duplicação?
Está nos dados! Não vê um 10 nos dois lugares (fora do
assert)?
11
Removendo duplicação
Se fizermos o seguinte
class Dollar {
Dollar(int amount) {}
void times(int multiplier) {}
int amount = 5 * 2;
}

O "10" some, revelando 5 e 2 duplicados no teste e no
código acima

Não há como remover a duplicação em uma etapa.

argonavis.com.br

Podemos começar movendo a definição do valor de
amount para o interior de times()
class Dollar {
int amount;
Dollar(int amount) {}
void times(int multiplier) {
amount = 5 * 2;
}
}

Os testes passam!
Barra verde!

12
Removendo duplicação (2)
E agora, como podemos conseguir um 5 e eliminar o 5
do interior de times()?
Este foi o valor passado ao construtor, no teste!
Podemos guardá-lo na variável de instância amount

argonavis.com.br

class Dollar {
int amount;
Dollar(int amount) {
this.amount = amount;
}
...

E o 2? Foi passado como parâmetro de times() no
teste, então está em multiplier
...
void times(int multiplier) {
amount = amount * multiplier;
}
}

13
Terminamos!
Rodamos o JUnit e... barra verde! Só para remover mais
um pouco de duplicação (variável amount), rescrevemos
a operação em times() para usar o operador *=

argonavis.com.br

class Dollar {
int amount;
Dollar(int amount) {
this.amount = amount;
}
void times(int multiplier) {
amount *= multiplier;
}
}

Rodamos o teste. Tudo OK. Agora podemos riscar um
item da lista!
$5 + $10 CHF = $10 se taxa for 2:1
$5 * 2 = $10
Fazer "amount" private
Nao usar inteiros
Efeitos colaterais

14
Conclusão
Vencemos uma etapa, mas há muito a fazer ainda
Começamos com duas tarefas na lista, acrescentamos
mais três, resolvemos uma. Saldo: faltam quatro!

argonavis.com.br

Para solucionar o teste, nós
Escrevemos uma história com um trecho de código que
dizia como esperávamos que funcionasse uma operação
Fizemos o teste compilar com stubs (métodos vazios)
Fizemos o teste rodar cometendo pecados terríveis
Gradualmente generalizamos o código, substituindo
constantes com variáveis
Adicionamos itens a nossa lista de tarefas em vez de
resolver tudo de uma vez
15
Por que ir tão devagar?
Por que não resolver todos os problemas de uma vez?
Se eu já sei fazer contas, por que escrever código a
conta-gotas?

argonavis.com.br

TDD não é sobre escrever código passos minúsculos! É
sobre ter a capacidade de escrever código em passos
minúsculos!
Você não vai escrever código no dia-a-dia com passos
tão pequenos, mas, se você pode dar passos tão
pequenos, pode dar passos maiores!
E, se a coisa ficar difícil, reduzir o tamanho dos passos
quando for necessário!
16
Resumo de um ciclo TDD
Escreva um teste
Escreva uma estória: pense em como você gostaria que uma
determinada operação funcionasse no seu código
Invente a interface que você gostaria de ter e inclua todos os
elementos necessários para contar sua estória

Faça o rodar

argonavis.com.br

Fazer a barra ficar verde é a atividade mais importante!
Se você já souber de uma solução limpa e óbvia, escreva! Se é obvia
mas vai levar um minuto, coloque-a na lista e volte ao problema
principal, que é fazer a barra ficar verde em alguns segundos

Faça direito
Agora que o sistema está funcionando, melhore o código,
removendo a duplicação introduzida para fazê-lo rodar
rapidamente, e faça-o ficar verde rapidamente
Objetivo: conseguir código limpo que funciona!

17
Objetos degenerados
Resolvemos um problema, mas há alguns efeitos
colaterais que persistem na nossa implementação
O estado do objeto persiste após a execução.
Dollar five = new Dollar(5); // five contém 5
five.times(2); // five agora contém 10
five.times(3); // resulta em 30, e não 15

argonavis.com.br

É possível descobrir isto acrescentando mais um teste,
que falha
public void testMultiplication() {
Dollar five = new Dollar(5);
five.times(2);
assertEquals(10, five.amount);
five.times(3);
assertEquals(15, five.amount);
}

Esta é a estória que estou
contando que mostra a forma
como eu gostaria que tudo
funcionasse.
Não está funcionando!

18
Solução
Uma solução seria sempre devolver um objeto novo de times().
public void testMultiplication() {
Dollar five = new Dollar(5);
Dollar product = five.times(2);
assertEquals(10, product.amount);
product = five.times(3);
assertEquals(15, product.amount);
}

argonavis.com.br

O teste sequer compila. É preciso mudar a interface da
implementação também
class Dollar {
...
Dollar times(int multiplier) {
amount *= multiplier;
return null;
}
}

Agora compila, e
falha. Ótimo!
19
Barra verde
Para fazer o teste rodar, precisamos que ele retorne
um objeto Dollar com o resultado correto
class Dollar {
...
Dollar times(int multiplier) {
return new Dollar(amount *= multiplier);
}
}

argonavis.com.br

Com isto, eliminamos mais um item da lista
$5 + $10 CHF = $10 se taxa for 2:1
$5 * 2 = $10
Fazer "amount" private
Nao usar inteiros (arredondamento)
Efeitos colaterais

20
Implementação "óbvia"

argonavis.com.br

Para resolver o primeiro teste da lista, começamos
com uma implementação falsa e gradualmente
chegamos à implementação real
Neste teste, digitamos o que achávamos ser a solução
e "rezamos" enquanto os testes rodaram. Por que
tivemos sorte e os testes rodaram, seguimos adiante
Usamos duas estratégias para rapidamente alcançar a
barra verde
"Fake it" - retorne uma constante e gradualmente a
substitua com variáveis até ter o código real
"Obvious Implementation" - arrisque uma
implementação correta (se falhar, volte ao "Fake It")
21
Value Object
O objeto Dollar deve ser tratado como um valor, ou
seja, se for criado um Dollar(5), esperamos que ele
seja igual a outro Dollar(5)

argonavis.com.br

Podemos implementar Dollar como um objeto de valor,
ou Value Object
Para isto, precisamos implementar equals()
Se formos colocar Dollars em um HashMap,
precisariamos implementar hashCode() também
$5 + $10 CHF = $10 se taxa for 2:1
$5 * 2 = $10
Fazer "amount" private
Nao usar inteiros (arredondamento)
Efeitos colaterais
equals()
hashCode()

22
Implementar equals()
Como implementar equals()
Não pense nisto! Pense como testar a igualdade entre
dois Dollars. Pense no teste!
public void testEquality() {
assertTrue(new Dollar(5).equals(new Dollar(5)));
}

argonavis.com.br

O teste falha. Criamos uma implementação falsa só
para obter a barra verde
public boolean equals(Object obj) {
return true;
}

23
Triangulação
Poderíamos resolver o problema com implementação
óbvia, mas vamos fazer uma triangulação
Esperamos que $5 seja igual a $5, mas também que $5
seja diferente de $6. Colocamos isto no teste

argonavis.com.br

public void testEquality() {
assertTrue(new Dollar(5).equals(new Dollar(5)));
assertFalse(new Dollar(6).equals(new Dollar(5)));
}

O teste falha! Agora somos forçados a uma
implementação genérica!
public boolean equals(Object obj) {
Dollar dollar = (Dollar)obj;
return amount == dollar.amount;
}

24
Mais tarefas
Enquanto pensamos no teste de igualdade, outras
perguntas surgem na mente
Como comparar Dollars com outros objetos (Francos,
por exemplo)
Como comparar com null?

argonavis.com.br

Não resolva isto agora. Coloque na lista!
$5 + $10 CHF = $10 se taxa for 2:1
$5 * 2 = $10
Fazer "amount" private
Nao usar inteiros (arredondamento)
Efeitos colaterais
equals()
hashCode()
Igualdade com null
Igualdade com objetos

25
Exercícios
Algumas sugestões para ir além (seguindo mais ou
menos o roteiro do livro)

argonavis.com.br

Comparar Dollars com Dollars e fazer amount private
Suportar operações com Francos
Lidar com Dollars e Francs como objetos similares
Comparar Francs com Dollars
Lidar com câmbio
Multiplicação, soma e subtração em comum
Abstração e generalização

26
Fontes

argonavis.com.br

[Beck] Kent Beck, "Test-Driven Development by
Example", Addison-Wesley, 2003

27
Curso J820
Produtividade e Qualidade em Java:
Ferramentas e Metodologias
Revisão 1.1

© 2002, 2003, Helder da Rocha
(helder@acm.org)

argonavis.com.br

Weitere ähnliche Inhalte

Was ist angesagt?

Programação Estruturada 2 - Curso Completo
Programação Estruturada 2 - Curso CompletoProgramação Estruturada 2 - Curso Completo
Programação Estruturada 2 - Curso Completothomasdacosta
 
C curso - notas de aula
C   curso - notas de aulaC   curso - notas de aula
C curso - notas de aulaLoAlves21
 
As cinco etapas da programação
As cinco etapas da programaçãoAs cinco etapas da programação
As cinco etapas da programaçãoClausia Antoneli
 
mod1-algoritmia
mod1-algoritmiamod1-algoritmia
mod1-algoritmiadiogoa21
 
Introdução a JavaScript
Introdução a JavaScriptIntrodução a JavaScript
Introdução a JavaScriptBruno Catão
 
Conceitos e técnicas de programação introdução
Conceitos e técnicas de programação introduçãoConceitos e técnicas de programação introdução
Conceitos e técnicas de programação introduçãoRobson Ferreira
 
M5-Desenvolvimento-Paginas-Web
M5-Desenvolvimento-Paginas-WebM5-Desenvolvimento-Paginas-Web
M5-Desenvolvimento-Paginas-Webdiogoa21
 
Programação Estruturada 2 - Aula 01
Programação Estruturada 2 - Aula 01Programação Estruturada 2 - Aula 01
Programação Estruturada 2 - Aula 01thomasdacosta
 
Maratona de Programação
Maratona de ProgramaçãoMaratona de Programação
Maratona de ProgramaçãoMarcos Castro
 
Algoritmos e Técnicas de Programação - Aula 04
Algoritmos e Técnicas de Programação - Aula 04Algoritmos e Técnicas de Programação - Aula 04
Algoritmos e Técnicas de Programação - Aula 04thomasdacosta
 
Manual-de-php
Manual-de-phpManual-de-php
Manual-de-phpdiogoa21
 
Apostila de Introdução aos Algoritmos - usando o Visualg
Apostila de Introdução aos Algoritmos - usando o VisualgApostila de Introdução aos Algoritmos - usando o Visualg
Apostila de Introdução aos Algoritmos - usando o VisualgRegis Magalhães
 
Lidando com o Caos: Testando Código PLSQL em um Projeto Critico
Lidando com o Caos: Testando Código PLSQL em um Projeto CriticoLidando com o Caos: Testando Código PLSQL em um Projeto Critico
Lidando com o Caos: Testando Código PLSQL em um Projeto CriticoRafael Ponte
 
Visualg introdução aos algoritmos
Visualg introdução aos algoritmosVisualg introdução aos algoritmos
Visualg introdução aos algoritmosLuciano Júnior
 
Curso de Java (Parte 3)
 Curso de Java (Parte 3) Curso de Java (Parte 3)
Curso de Java (Parte 3)Mario Sergio
 

Was ist angesagt? (20)

Programação Estruturada 2 - Curso Completo
Programação Estruturada 2 - Curso CompletoProgramação Estruturada 2 - Curso Completo
Programação Estruturada 2 - Curso Completo
 
Code Smells
Code SmellsCode Smells
Code Smells
 
C curso - notas de aula
C   curso - notas de aulaC   curso - notas de aula
C curso - notas de aula
 
Codigo limpo
Codigo limpoCodigo limpo
Codigo limpo
 
As cinco etapas da programação
As cinco etapas da programaçãoAs cinco etapas da programação
As cinco etapas da programação
 
Apostila Visualg
Apostila VisualgApostila Visualg
Apostila Visualg
 
mod1-algoritmia
mod1-algoritmiamod1-algoritmia
mod1-algoritmia
 
Introdução a JavaScript
Introdução a JavaScriptIntrodução a JavaScript
Introdução a JavaScript
 
Conceitos e técnicas de programação introdução
Conceitos e técnicas de programação introduçãoConceitos e técnicas de programação introdução
Conceitos e técnicas de programação introdução
 
M5-Desenvolvimento-Paginas-Web
M5-Desenvolvimento-Paginas-WebM5-Desenvolvimento-Paginas-Web
M5-Desenvolvimento-Paginas-Web
 
Programação Estruturada 2 - Aula 01
Programação Estruturada 2 - Aula 01Programação Estruturada 2 - Aula 01
Programação Estruturada 2 - Aula 01
 
Maratona de Programação
Maratona de ProgramaçãoMaratona de Programação
Maratona de Programação
 
Algoritmos e Técnicas de Programação - Aula 04
Algoritmos e Técnicas de Programação - Aula 04Algoritmos e Técnicas de Programação - Aula 04
Algoritmos e Técnicas de Programação - Aula 04
 
Java primeiros-passos
Java primeiros-passosJava primeiros-passos
Java primeiros-passos
 
Manual-de-php
Manual-de-phpManual-de-php
Manual-de-php
 
Apostila de Introdução aos Algoritmos - usando o Visualg
Apostila de Introdução aos Algoritmos - usando o VisualgApostila de Introdução aos Algoritmos - usando o Visualg
Apostila de Introdução aos Algoritmos - usando o Visualg
 
Lidando com o Caos: Testando Código PLSQL em um Projeto Critico
Lidando com o Caos: Testando Código PLSQL em um Projeto CriticoLidando com o Caos: Testando Código PLSQL em um Projeto Critico
Lidando com o Caos: Testando Código PLSQL em um Projeto Critico
 
Modulo02
Modulo02Modulo02
Modulo02
 
Visualg introdução aos algoritmos
Visualg introdução aos algoritmosVisualg introdução aos algoritmos
Visualg introdução aos algoritmos
 
Curso de Java (Parte 3)
 Curso de Java (Parte 3) Curso de Java (Parte 3)
Curso de Java (Parte 3)
 

Andere mochten auch (20)

Akskybova
AkskybovaAkskybova
Akskybova
 
documento
documentodocumento
documento
 
Articulo tercero. de educacion
Articulo tercero. de educacionArticulo tercero. de educacion
Articulo tercero. de educacion
 
RACK SLIDE-top
RACK SLIDE-topRACK SLIDE-top
RACK SLIDE-top
 
Campana Teka DBB 90
Campana Teka DBB 90Campana Teka DBB 90
Campana Teka DBB 90
 
Aprendizaje Visual- Cevallos- 20150427
Aprendizaje Visual- Cevallos- 20150427Aprendizaje Visual- Cevallos- 20150427
Aprendizaje Visual- Cevallos- 20150427
 
Campana Teka DF 90
Campana Teka DF 90Campana Teka DF 90
Campana Teka DF 90
 
RACK SLIDE-base
RACK SLIDE-baseRACK SLIDE-base
RACK SLIDE-base
 
Malvin the boss
Malvin the bossMalvin the boss
Malvin the boss
 
Presente con éxito en 2 minutos
Presente con éxito en 2 minutosPresente con éxito en 2 minutos
Presente con éxito en 2 minutos
 
Edihar G2L1 15011
Edihar G2L1 15011Edihar G2L1 15011
Edihar G2L1 15011
 
Common Content Marketing Mistakes
Common Content Marketing MistakesCommon Content Marketing Mistakes
Common Content Marketing Mistakes
 
New Product Develpoment- e band
New Product Develpoment- e band New Product Develpoment- e band
New Product Develpoment- e band
 
Travelling words - Presentation of Bulgaria
Travelling words - Presentation of BulgariaTravelling words - Presentation of Bulgaria
Travelling words - Presentation of Bulgaria
 
Navigation Using Audio Jack
Navigation Using Audio JackNavigation Using Audio Jack
Navigation Using Audio Jack
 
RACK SLIDE-sections
RACK SLIDE-sectionsRACK SLIDE-sections
RACK SLIDE-sections
 
Grooming
GroomingGrooming
Grooming
 
Iturgaiz Navarra
Iturgaiz NavarraIturgaiz Navarra
Iturgaiz Navarra
 
Aprendizaje segun Perspectiva Conductista
Aprendizaje segun Perspectiva ConductistaAprendizaje segun Perspectiva Conductista
Aprendizaje segun Perspectiva Conductista
 
Hola que mas
Hola que masHola que mas
Hola que mas
 

Ähnlich wie Test-driven Development

TDD: A Essência do Mantra
TDD: A Essência do MantraTDD: A Essência do Mantra
TDD: A Essência do MantraDionatan default
 
Lógica de Programação - Unimep/Pronatec - Aula08
Lógica de Programação - Unimep/Pronatec - Aula08Lógica de Programação - Unimep/Pronatec - Aula08
Lógica de Programação - Unimep/Pronatec - Aula08André Phillip Bertoletti
 
Não existe feedback melhor do que o do seu código
Não existe feedback melhor do que o do seu códigoNão existe feedback melhor do que o do seu código
Não existe feedback melhor do que o do seu códigoRenan Carvalho
 
Curso de introdução ao ruby
Curso de introdução ao rubyCurso de introdução ao ruby
Curso de introdução ao rubyFrancis Wagner
 
Programação Orientada a Testes
Programação Orientada a TestesProgramação Orientada a Testes
Programação Orientada a TestesGregorio Melo
 
Introdução ao Test Driven Development (TDD)
Introdução ao Test Driven Development (TDD)Introdução ao Test Driven Development (TDD)
Introdução ao Test Driven Development (TDD)Lucas Nery
 
Introdução a programação
Introdução a programaçãoIntrodução a programação
Introdução a programaçãoEdu Queiroz
 
Vamos falar de Clean Code, Refatoração e TDD
Vamos falar de Clean Code, Refatoração e TDDVamos falar de Clean Code, Refatoração e TDD
Vamos falar de Clean Code, Refatoração e TDDDomingos Teruel
 
Clean Code - Fork In Tuba
Clean Code - Fork In TubaClean Code - Fork In Tuba
Clean Code - Fork In TubaRafael Paz
 
Domain Driven Design (DDD) - DevIsland, BH
Domain Driven Design (DDD) - DevIsland, BHDomain Driven Design (DDD) - DevIsland, BH
Domain Driven Design (DDD) - DevIsland, BHGiovanni Bassi
 

Ähnlich wie Test-driven Development (20)

Programação Orientada a Objetos - 001
Programação Orientada a Objetos - 001Programação Orientada a Objetos - 001
Programação Orientada a Objetos - 001
 
Debugging node
Debugging nodeDebugging node
Debugging node
 
Java - Primeiros passos
Java - Primeiros passosJava - Primeiros passos
Java - Primeiros passos
 
Código limpo
Código limpoCódigo limpo
Código limpo
 
TDD: A Essência do Mantra
TDD: A Essência do MantraTDD: A Essência do Mantra
TDD: A Essência do Mantra
 
Ap algoritmosglauco
Ap algoritmosglaucoAp algoritmosglauco
Ap algoritmosglauco
 
Lógica de Programação - Unimep/Pronatec - Aula08
Lógica de Programação - Unimep/Pronatec - Aula08Lógica de Programação - Unimep/Pronatec - Aula08
Lógica de Programação - Unimep/Pronatec - Aula08
 
Não existe feedback melhor do que o do seu código
Não existe feedback melhor do que o do seu códigoNão existe feedback melhor do que o do seu código
Não existe feedback melhor do que o do seu código
 
Curso de introdução ao ruby
Curso de introdução ao rubyCurso de introdução ao ruby
Curso de introdução ao ruby
 
Aula 3-lógica.pptx
Aula 3-lógica.pptxAula 3-lógica.pptx
Aula 3-lógica.pptx
 
Programação Orientada a Testes
Programação Orientada a TestesProgramação Orientada a Testes
Programação Orientada a Testes
 
Java e orientação a objetos
Java e orientação a objetosJava e orientação a objetos
Java e orientação a objetos
 
Introdução ao Test Driven Development (TDD)
Introdução ao Test Driven Development (TDD)Introdução ao Test Driven Development (TDD)
Introdução ao Test Driven Development (TDD)
 
FC-Logic
FC-LogicFC-Logic
FC-Logic
 
Introdução a programação
Introdução a programaçãoIntrodução a programação
Introdução a programação
 
Macro br
Macro brMacro br
Macro br
 
Vamos falar de Clean Code, Refatoração e TDD
Vamos falar de Clean Code, Refatoração e TDDVamos falar de Clean Code, Refatoração e TDD
Vamos falar de Clean Code, Refatoração e TDD
 
Clean Code - Fork In Tuba
Clean Code - Fork In TubaClean Code - Fork In Tuba
Clean Code - Fork In Tuba
 
Refactoring - Design no Código
Refactoring - Design no CódigoRefactoring - Design no Código
Refactoring - Design no Código
 
Domain Driven Design (DDD) - DevIsland, BH
Domain Driven Design (DDD) - DevIsland, BHDomain Driven Design (DDD) - DevIsland, BH
Domain Driven Design (DDD) - DevIsland, BH
 

Mehr von Denis L Presciliano

Como construir aplicações gráficas e applets
Como construir aplicações gráficas e appletsComo construir aplicações gráficas e applets
Como construir aplicações gráficas e appletsDenis L Presciliano
 
Coleções Propriedade, Resources e Strings
Coleções Propriedade, Resources e StringsColeções Propriedade, Resources e Strings
Coleções Propriedade, Resources e StringsDenis L Presciliano
 
Funcamentos de Programação Concorrente
Funcamentos de Programação ConcorrenteFuncamentos de Programação Concorrente
Funcamentos de Programação ConcorrenteDenis L Presciliano
 
Reuso com Herança e Composição
Reuso com Herança e ComposiçãoReuso com Herança e Composição
Reuso com Herança e ComposiçãoDenis L Presciliano
 
Gerenciamento de projetos com o Apache Ant
Gerenciamento de projetos com o Apache AntGerenciamento de projetos com o Apache Ant
Gerenciamento de projetos com o Apache AntDenis L Presciliano
 
Tipos, literais, operadoes e controle de fluxo
Tipos, literais, operadoes e controle de fluxoTipos, literais, operadoes e controle de fluxo
Tipos, literais, operadoes e controle de fluxoDenis L Presciliano
 
Como usar a documentação da API Java 2
Como usar a documentação da API Java 2Como usar a documentação da API Java 2
Como usar a documentação da API Java 2Denis L Presciliano
 
Configuração do ambiente JEdit + Ant
Configuração do ambiente JEdit + AntConfiguração do ambiente JEdit + Ant
Configuração do ambiente JEdit + AntDenis L Presciliano
 
Programação Orientada a objetos em Java
Programação Orientada a objetos em JavaProgramação Orientada a objetos em Java
Programação Orientada a objetos em JavaDenis L Presciliano
 

Mehr von Denis L Presciliano (20)

Funmentos de Objetos Remotos
Funmentos de Objetos RemotosFunmentos de Objetos Remotos
Funmentos de Objetos Remotos
 
Fundamentos de JDBC
Fundamentos de JDBCFundamentos de JDBC
Fundamentos de JDBC
 
Como construir aplicações gráficas e applets
Como construir aplicações gráficas e appletsComo construir aplicações gráficas e applets
Como construir aplicações gráficas e applets
 
Classes internas
Classes internasClasses internas
Classes internas
 
Entrada e Saída
Entrada e SaídaEntrada e Saída
Entrada e Saída
 
Coleções Propriedade, Resources e Strings
Coleções Propriedade, Resources e StringsColeções Propriedade, Resources e Strings
Coleções Propriedade, Resources e Strings
 
Funcamentos de Programação Concorrente
Funcamentos de Programação ConcorrenteFuncamentos de Programação Concorrente
Funcamentos de Programação Concorrente
 
Testes de Unidade com JUnit
Testes de Unidade com JUnitTestes de Unidade com JUnit
Testes de Unidade com JUnit
 
Erros, exceções e asserções
Erros, exceções e asserçõesErros, exceções e asserções
Erros, exceções e asserções
 
Interfaces e Porlimosfismo
Interfaces e PorlimosfismoInterfaces e Porlimosfismo
Interfaces e Porlimosfismo
 
Reuso com Herança e Composição
Reuso com Herança e ComposiçãoReuso com Herança e Composição
Reuso com Herança e Composição
 
Gerenciamento de projetos com o Apache Ant
Gerenciamento de projetos com o Apache AntGerenciamento de projetos com o Apache Ant
Gerenciamento de projetos com o Apache Ant
 
Pacotes e Encapsulamento
Pacotes e EncapsulamentoPacotes e Encapsulamento
Pacotes e Encapsulamento
 
Como criar classes e objetos
Como criar classes e objetosComo criar classes e objetos
Como criar classes e objetos
 
Tipos, literais, operadoes e controle de fluxo
Tipos, literais, operadoes e controle de fluxoTipos, literais, operadoes e controle de fluxo
Tipos, literais, operadoes e controle de fluxo
 
Como usar a documentação da API Java 2
Como usar a documentação da API Java 2Como usar a documentação da API Java 2
Como usar a documentação da API Java 2
 
Configuração do ambiente JEdit + Ant
Configuração do ambiente JEdit + AntConfiguração do ambiente JEdit + Ant
Configuração do ambiente JEdit + Ant
 
Programação Orientada a objetos em Java
Programação Orientada a objetos em JavaProgramação Orientada a objetos em Java
Programação Orientada a objetos em Java
 
Introdução a tecnologia Java
Introdução a tecnologia JavaIntrodução a tecnologia Java
Introdução a tecnologia Java
 
Fundamentos de Sockets
Fundamentos de SocketsFundamentos de Sockets
Fundamentos de Sockets
 

Test-driven Development

  • 1. J820 Test-driven Development Helder da Rocha (helder@acm.org) argonavis.com.br
  • 2. TDD argonavis.com.br Metodologia de desenvolvimento guiada por testes Objetivo: produzir "código limpo que funciona" [Beck] Vantagens de produzir código desse tipo (precisa enumerar?) Você sabe quando terminou (e não precisa se preocupar com uma longa fase de depuração de bugs): previsível! Oportunidade de aprender todas as lições que o código ensina (em vez de pegar a primeira solução que aparecer e esquecer as outras) Melhora as vidas dos usuários do seu software Melhora as vidas dos membros da equipe É bom escrever código limpo... mais ainda, se funciona! 2
  • 3. Como escrever código limpo que funciona? Várias forças nos afastam de código limpo e de código que funciona. Como fugir delas? Desenvolver com testes automáticos? TDD! Em TDD... Só se escreve uma nova linha de código se algum teste automático falhar Elimina-se duplicação o tempo todo argonavis.com.br Implicações Design: código funcionando fornece feedback e orienta decisões Temos que escrever nossos próprios testes: tempo Ambiente de desenvolvimento usado deve responder rápido a pequenas mudanças Designs elaborados devem facilitar testes: componentes pequenos, desacoplados, altamente coesos 3
  • 4. Mantra TDD: Red/Green/Refactor Ordem geral do desenvolvimento Red: escreva um pequeno teste que não funciona (e talvez nem compile) Green: faça o teste rodar rapidamente, cometendo quaisquer pecados necessários no processo Refactor: elimine toda a duplicação criada em meramente buscar o sucesso do teste argonavis.com.br Por que? Ter trabalho adicional de escrever testes automáticos? Trabalhar em pequenas etapas se você é capaz de dar grandes saltos e resolver tudo rapidamente? Coragem + comunicação + feedback + segurança Qualidade, tempo, previsibilidade 4
  • 5. Exemplo interativo de TDD argonavis.com.br Extraído do livro: "Test Driven Development", por Kent Beck, parte I (páginas 3 a 87) Estes slides apenas apresentam uma visão geral para servir de base à demonstração em sala de aula A demonstração será feita de forma interativa usando o livro como guia, mas em "group programming", portanto, pode ter resultados diferentes se a turma seguir outro caminho Use o livro para refazer o exemplo posteriormente e explorar novas técnicas Os slides mostram apenas os primeiros 3 (dos 17) capítulos. A aula interativa irá um pouco além 5
  • 6. Dinheiro em várias moedas O problema Lidar com uma aplicação que realiza operações em dinheiro de moedas diferentes transparentemente Exemplo (relatório de quotas de participação) IBM 1000 quotas a Novartis 400 quotas a Total geral: 25 USD: 150 CHF*: Total 25000 USD Total 60000 CHF 65000 USD argonavis.com.br Para realizar as operações, precisamos ter uma taxa de câmbio 1 USD = 2 CHF Requisitos: anotados em nossa lista! * CHF = Francos Suíços 6
  • 7. Elaboração da lista de tarefas Como solucionar este problema? Que conjunto de testes irão demonstrar a presença do código que irá gerar corretamente o relatório? argonavis.com.br Começamos anotando em nossa lista (to-do list) Precisamos poder somar todas as quantidades em moedas diferentes e converter o resultado dadas as taxas de conversão de câmbio Precisamos poder multiplicar uma quantidade (preço por quota) por um número (quantidade de quotas) e receber uma quantidade Lista de tarefas $5 + $10 CHF = $10 se taxa for 2:1 $5 * 2 = $10 Quando terminar uma, risque-a Acrescente novas quando necessário 7
  • 8. Começaremos com a multiplicação $5 + $10 CHF = $10 se taxa for 2:1 $5 * 2 = $10 Que objetos precisamos? Não pense em objetos! Pense em testes! Que testes precisamos? argonavis.com.br Pense em como a operação vai parecer pelo lado de fora (conte uma estória) Escreva o teste da forma mais simples public void testMultiplication() { Dollar five = new Dollar(5); five.times(2); assertEquals(10, five.amount); } Detectou problemas? Não resolva agora. Coloque na lista! ... Fazer "amount" private Nao usar inteiros Efeitos colaterais 8
  • 9. O teste não compila! Vamos consertar! Temos 4 erros Não existe a classe Dollar Não existe o construtor Dollar(int) Não existe o método times(int) Não existe o atributo amount argonavis.com.br Conserte um de cada vez, só para compilar (não preencha métodos e construtores ainda) class Dollar { Dollar(int amount) {} void times(int multiplier) {} int amount; } Agora podemos rodar o teste e vê-lo falhar 9
  • 10. A falha é um avanço! Barra vermelha nos impele para buscar a barra verde! Temos uma medida concreta de falha O problema mudou de "Me dê uma solução para o problema das múltiplas moedas!" para "Faça este teste funcionar, e depois faça os outros funcionarem!" Muito mais simples: reduzimos o "escopo do medo" argonavis.com.br Faça o teste passar! A meta neste momento não é ter a resposta perfeita, mas fazer o teste passar. Qual a menor mudança que podemos fazer para alcançar isto? class Dollar { Dollar(int amount) {} void times(int multiplier) {} int amount = 10; } Trapaça! Mas funciona! Temos uma barra verde! 10
  • 11. Está verde, mas não está pronto! Precisamos generalizar antes de prosseguir. O ciclo é o seguinte argonavis.com.br Acrescente um pequeno teste Rode todos os testes e assegure que falham Faça uma pequena mudança Rode todos os testes e assegure que passam Refatore o código para remover duplicação (remover a dependência entre o teste e o código - a duplicação é o "sintoma" que indica essa dependência) Onde está a duplicação? Está nos dados! Não vê um 10 nos dois lugares (fora do assert)? 11
  • 12. Removendo duplicação Se fizermos o seguinte class Dollar { Dollar(int amount) {} void times(int multiplier) {} int amount = 5 * 2; } O "10" some, revelando 5 e 2 duplicados no teste e no código acima Não há como remover a duplicação em uma etapa. argonavis.com.br Podemos começar movendo a definição do valor de amount para o interior de times() class Dollar { int amount; Dollar(int amount) {} void times(int multiplier) { amount = 5 * 2; } } Os testes passam! Barra verde! 12
  • 13. Removendo duplicação (2) E agora, como podemos conseguir um 5 e eliminar o 5 do interior de times()? Este foi o valor passado ao construtor, no teste! Podemos guardá-lo na variável de instância amount argonavis.com.br class Dollar { int amount; Dollar(int amount) { this.amount = amount; } ... E o 2? Foi passado como parâmetro de times() no teste, então está em multiplier ... void times(int multiplier) { amount = amount * multiplier; } } 13
  • 14. Terminamos! Rodamos o JUnit e... barra verde! Só para remover mais um pouco de duplicação (variável amount), rescrevemos a operação em times() para usar o operador *= argonavis.com.br class Dollar { int amount; Dollar(int amount) { this.amount = amount; } void times(int multiplier) { amount *= multiplier; } } Rodamos o teste. Tudo OK. Agora podemos riscar um item da lista! $5 + $10 CHF = $10 se taxa for 2:1 $5 * 2 = $10 Fazer "amount" private Nao usar inteiros Efeitos colaterais 14
  • 15. Conclusão Vencemos uma etapa, mas há muito a fazer ainda Começamos com duas tarefas na lista, acrescentamos mais três, resolvemos uma. Saldo: faltam quatro! argonavis.com.br Para solucionar o teste, nós Escrevemos uma história com um trecho de código que dizia como esperávamos que funcionasse uma operação Fizemos o teste compilar com stubs (métodos vazios) Fizemos o teste rodar cometendo pecados terríveis Gradualmente generalizamos o código, substituindo constantes com variáveis Adicionamos itens a nossa lista de tarefas em vez de resolver tudo de uma vez 15
  • 16. Por que ir tão devagar? Por que não resolver todos os problemas de uma vez? Se eu já sei fazer contas, por que escrever código a conta-gotas? argonavis.com.br TDD não é sobre escrever código passos minúsculos! É sobre ter a capacidade de escrever código em passos minúsculos! Você não vai escrever código no dia-a-dia com passos tão pequenos, mas, se você pode dar passos tão pequenos, pode dar passos maiores! E, se a coisa ficar difícil, reduzir o tamanho dos passos quando for necessário! 16
  • 17. Resumo de um ciclo TDD Escreva um teste Escreva uma estória: pense em como você gostaria que uma determinada operação funcionasse no seu código Invente a interface que você gostaria de ter e inclua todos os elementos necessários para contar sua estória Faça o rodar argonavis.com.br Fazer a barra ficar verde é a atividade mais importante! Se você já souber de uma solução limpa e óbvia, escreva! Se é obvia mas vai levar um minuto, coloque-a na lista e volte ao problema principal, que é fazer a barra ficar verde em alguns segundos Faça direito Agora que o sistema está funcionando, melhore o código, removendo a duplicação introduzida para fazê-lo rodar rapidamente, e faça-o ficar verde rapidamente Objetivo: conseguir código limpo que funciona! 17
  • 18. Objetos degenerados Resolvemos um problema, mas há alguns efeitos colaterais que persistem na nossa implementação O estado do objeto persiste após a execução. Dollar five = new Dollar(5); // five contém 5 five.times(2); // five agora contém 10 five.times(3); // resulta em 30, e não 15 argonavis.com.br É possível descobrir isto acrescentando mais um teste, que falha public void testMultiplication() { Dollar five = new Dollar(5); five.times(2); assertEquals(10, five.amount); five.times(3); assertEquals(15, five.amount); } Esta é a estória que estou contando que mostra a forma como eu gostaria que tudo funcionasse. Não está funcionando! 18
  • 19. Solução Uma solução seria sempre devolver um objeto novo de times(). public void testMultiplication() { Dollar five = new Dollar(5); Dollar product = five.times(2); assertEquals(10, product.amount); product = five.times(3); assertEquals(15, product.amount); } argonavis.com.br O teste sequer compila. É preciso mudar a interface da implementação também class Dollar { ... Dollar times(int multiplier) { amount *= multiplier; return null; } } Agora compila, e falha. Ótimo! 19
  • 20. Barra verde Para fazer o teste rodar, precisamos que ele retorne um objeto Dollar com o resultado correto class Dollar { ... Dollar times(int multiplier) { return new Dollar(amount *= multiplier); } } argonavis.com.br Com isto, eliminamos mais um item da lista $5 + $10 CHF = $10 se taxa for 2:1 $5 * 2 = $10 Fazer "amount" private Nao usar inteiros (arredondamento) Efeitos colaterais 20
  • 21. Implementação "óbvia" argonavis.com.br Para resolver o primeiro teste da lista, começamos com uma implementação falsa e gradualmente chegamos à implementação real Neste teste, digitamos o que achávamos ser a solução e "rezamos" enquanto os testes rodaram. Por que tivemos sorte e os testes rodaram, seguimos adiante Usamos duas estratégias para rapidamente alcançar a barra verde "Fake it" - retorne uma constante e gradualmente a substitua com variáveis até ter o código real "Obvious Implementation" - arrisque uma implementação correta (se falhar, volte ao "Fake It") 21
  • 22. Value Object O objeto Dollar deve ser tratado como um valor, ou seja, se for criado um Dollar(5), esperamos que ele seja igual a outro Dollar(5) argonavis.com.br Podemos implementar Dollar como um objeto de valor, ou Value Object Para isto, precisamos implementar equals() Se formos colocar Dollars em um HashMap, precisariamos implementar hashCode() também $5 + $10 CHF = $10 se taxa for 2:1 $5 * 2 = $10 Fazer "amount" private Nao usar inteiros (arredondamento) Efeitos colaterais equals() hashCode() 22
  • 23. Implementar equals() Como implementar equals() Não pense nisto! Pense como testar a igualdade entre dois Dollars. Pense no teste! public void testEquality() { assertTrue(new Dollar(5).equals(new Dollar(5))); } argonavis.com.br O teste falha. Criamos uma implementação falsa só para obter a barra verde public boolean equals(Object obj) { return true; } 23
  • 24. Triangulação Poderíamos resolver o problema com implementação óbvia, mas vamos fazer uma triangulação Esperamos que $5 seja igual a $5, mas também que $5 seja diferente de $6. Colocamos isto no teste argonavis.com.br public void testEquality() { assertTrue(new Dollar(5).equals(new Dollar(5))); assertFalse(new Dollar(6).equals(new Dollar(5))); } O teste falha! Agora somos forçados a uma implementação genérica! public boolean equals(Object obj) { Dollar dollar = (Dollar)obj; return amount == dollar.amount; } 24
  • 25. Mais tarefas Enquanto pensamos no teste de igualdade, outras perguntas surgem na mente Como comparar Dollars com outros objetos (Francos, por exemplo) Como comparar com null? argonavis.com.br Não resolva isto agora. Coloque na lista! $5 + $10 CHF = $10 se taxa for 2:1 $5 * 2 = $10 Fazer "amount" private Nao usar inteiros (arredondamento) Efeitos colaterais equals() hashCode() Igualdade com null Igualdade com objetos 25
  • 26. Exercícios Algumas sugestões para ir além (seguindo mais ou menos o roteiro do livro) argonavis.com.br Comparar Dollars com Dollars e fazer amount private Suportar operações com Francos Lidar com Dollars e Francs como objetos similares Comparar Francs com Dollars Lidar com câmbio Multiplicação, soma e subtração em comum Abstração e generalização 26
  • 27. Fontes argonavis.com.br [Beck] Kent Beck, "Test-Driven Development by Example", Addison-Wesley, 2003 27
  • 28. Curso J820 Produtividade e Qualidade em Java: Ferramentas e Metodologias Revisão 1.1 © 2002, 2003, Helder da Rocha (helder@acm.org) argonavis.com.br