Upload
fernando-carvalho
View
216
Download
3
Embed Size (px)
DESCRIPTION
Exercícios sobre TDD apresentados em sala de aula.A técnica de TDD representa uma inovação trazida pelos métodos ágeis, e que vem melhorar muito a qualidade dos projetos de desenvolvimento de software.
Citation preview
PastasEm java é comum usar pastas para código de produção no source folder.
Criar um segundo source folder para testes
criar a mesma estrutura de pastas para os testes, espelhando a produção.
Anatomia do método de testeO nome deve refletir um comportamento esperadonão pode ser estáticonão deve receber parâmetros
@Testusar a anotação antes do método de teste
deve ser:@Testpublic void deve_apresentar_um_comportamento_especifico() {
...}
Anatomia de um Teste- Constroi Cenário
Quais elementos externos são necessários paraexercitar o comportamento
- Executa açãoinvoca o comportamento que se deseja testar
- Verifica saídaEstabelece expectativas do comportamentoQuais são as pós condições?
AssertExpectativa de igualdade
assertEquals(esperado, recebido);
import static org.junit.Assert.assertEquals;import org.junit.*;
para valores doubleassertEquals(esperado, recebido, delta=0.0001);
@Before e @After ...@Before
método a ser executado antes de todos os testes
@Aftermétodo a ser executado depois de todos os testes
@BeforeClassmétodo a ser executado antes da classe de testes
@AfterClassmétodo a ser executado após a classe de testes
Lancepackage br.com.caelum.leilao.dominio;public class Lance {
private Usuario usuario;private double valor;
public Lance(Usuario usuario, double valor) {this.usuario = usuario;this.valor = valor;
}
public double getValor() {return this.valor;
}
public String toString() {return usuario.getNome()+"("+valor+")";
}}
Leilaopackage br.com.caelum.leilao.dominio;import java.util.ArrayList;import java.util.List;public class Leilao {
private String produto;private List<Lance> lances;
public Leilao(String produto) {this.produto = produto;this.lances = new ArrayList<Lance>();
}public void propoe(Lance lance) {
if(lance.getValor() <= 0)throw new RuntimeException("Valor não pode ser negativo ou zero");
this.lances.add(lance);}public List<Lance> getLances() {
return lances;}
}
Usuariopackage br.com.caelum.leilao.dominio;
public class Usuario {private String nome;
public Usuario(String nome) {this.nome = nome;
}
public String getNome() {return nome;
}
public String toString() {return nome;
}}
ExercícioDado um leilão, devemos saber qual o maior lance que foi dado.
Criar uma classe AvaliadorCriar um método avalia(Leilao)
Criar um método getMaiorLance()Criar uma classe AvaliadorTest (pacote leilao.test)adicionar 3 lances avaliar se o maiorLance está coerente
Estratégia1. Dado um leilao, é preciso que um Avaliador possa avaliar o leilao, pois deve ser possível consultar ao Avaliador qual foi o maior lance:teste:
no pacote: leilao.teste a classe AvaliadorTestecriar 3 Usuárioscriar 1 Leilaocriar 3 lances (300, 400, 250)criar um Avaliador: leiloeiroexecutar leiloeiro.avalia()testar se o maiorLance() funciona
Resultado@Testpublic void deve_saber_qual_o_maior_lance_dado() {
// parte 1: contextoAvaliador leiloeiro = new Avaliador();Usuario joao = new Usuario("Joao");Usuario jose = new Usuario("Jose");Usuario maria = new Usuario("Maria");
Leilao leilao = new Leilao("Playstation 3 Novo");leilao.propoe(new Lance(joao, 250.0));leilao.propoe(new Lance(jose, 300.0));leilao.propoe(new Lance(maria, 400.0));
// parte 2: açãoleiloeiro.avalia(leilao);
// parte 3: validacaoassertEquals(400.0, leiloeiro.getMaiorLance(), 0.00001);
}
ProduçãoNo pacote: leilao.servico
Avaliador.avalia()maior = Double.NEGATIVE_INFINITY;calcula o maior de todos;
getMaiorLance()
@Beforeprivate Avaliador leiloeiro;private Usuario joao;private Usuario jose;private Usuario maria;
@Beforepublic void criaAvaliador() {
this.leiloeiro = new Avaliador();joao = new Usuario("Joao");jose = new Usuario("Jose");maria = new Usuario("Maria");
}
Resultado@Testpublic void deve_saber_qual_o_maior_lance_dado() {
// parte 1: contextoLeilao leilao = new Leilao("Celular Usado");leilao.propoe(new Lance(joao, 250.0));leilao.propoe(new Lance(jose, 300.0));leilao.propoe(new Lance(maria, 400.0));
// parte 2: açãoleiloeiro.avalia(leilao);
// parte 3: validacaoassertEquals(400.0, leiloeiro.getMaiorLance(), 0.00001);
}
ExercícioDado um leilão, devemos saber qual o menor lance que foi dado.
Criar um método getMenorLance()
Criar uma classe AvaliadorTest (pacote leilao.test)
Resultado@Testpublic void deve_saber_qual_o_menor_lance_dado() {
// parte 1: contextoLeilao leilao = new Leilao("Playstation 3 Novo");leilao.propoe(new Lance(joao, 250.0));leilao.propoe(new Lance(jose, 300.0));leilao.propoe(new Lance(maria, 400.0));
// parte 2: açãoleiloeiro.avalia(leilao);
// parte 3: validacaoassertEquals(250.0, leiloeiro.getMenorLance(), 0.00001);
}
Resultado@Testpublic void deveEntenderLancesForaDeOrdem() {
// parte 1: contextoLeilao leilao = new Leilao("Playstation 3 Novo");leilao.propoe(new Lance(joao, 250.0));leilao.propoe(new Lance(jose, 400.0));leilao.propoe(new Lance(maria, 300.0));
// parte 2: açãoleiloeiro.avalia(leilao);
// parte 3: validacaoassertThat(leiloeiro.getMenorLance(), equalTo(250.0));assertThat(leiloeiro.getMaiorLance(), equalTo(400.0));
}
Resultado@Testpublic void deve_saber_qual_a_media_dos_lances() {
// parte 1: contextoLeilao leilao = new Leilao("Playstation 3 Novo");leilao.propoe(new Lance(joao, 250.0));leilao.propoe(new Lance(jose, 300.0));leilao.propoe(new Lance(maria, 400.0));
// parte 2: açãoleiloeiro.avalia(leilao);
// parte 3: validacaoassertEquals(316.666, leiloeiro.getMedia(), 0.001);
}
Produçãoclass Avaliador {private double maiorDeTodos = Double.NEGATIVE_INFINITY;private double menorDeTodos = Double.POSITIVE_INFINITY;private double media = 0;
public void avalia(Leilao leilao) {double total = 0;for(Lance lance : leilao.getLances()) {
if(lance.getValor() > maiorDeTodos) maiorDeTodos = lance.getValor();if(lance.getValor() < menorDeTodos) menorDeTodos = lance.getValor();total += lance.getValor();
}media = total / leilao.getLances().size();
}
public double getMaiorLance() { return maiorDeTodos; }public double getMenorLance() { return menorDeTodos; }public double getMedia() { return media; }}
Classes de equivalênciaVários teste mudando os valores vale a pena?
Ordem CrescenteOrdem DecrescenteOrdem RandômicaCom apenas um lanceSem lancesLance Negativo
Resultado@Testpublic void deveEntenderLeilaoComApenasUmLance() {
Leilao leilao = new Leilao("Playstation");
leilao.propoe(new Lance(joao, 1000.0));
leiloeiro.avalia(leilao);
assertEquals(1000, leiloeiro.getMaiorLance(), 0.0001);assertEquals(1000, leiloeiro.getMenorLance(), 0.0001);
}
Resultado@Testpublic void deveEncontrarOsTresMaioresLances() {
Leilao leilao = new Leilao("Playstation 3 Novo");leilao.propoe(new Lance(joao, 100.0));leilao.propoe(new Lance(maria, 200.0));leilao.propoe(new Lance(joao, 300.0));leilao.propoe(new Lance(maria, 400.0));
leiloeiro.avalia(leilao);
List<Lance> maiores = leiloeiro.getTresMaiores();assertEquals(3, maiores.size());
assertThat(maiores.size(), equalTo(3));
assertEquals(400.0, maiores.get(0).getValor(), 0.00001);assertEquals(300.0, maiores.get(1).getValor(), 0.00001);assertEquals(200.0, maiores.get(2).getValor(), 0.00001);
}
Resultado@Testpublic void deveDevolverTodosLancesCasoNaoHajaNoMinimo3() {
Leilao leilao = new Leilao("Playstation 3 Novo");leilao.propoe(new Lance(joao, 300.0));leilao.propoe(new Lance(maria, 400.0));
leiloeiro.avalia(leilao);
List<Lance> maiores = leiloeiro.getTresMaiores();assertEquals(3, maiores.size());
assertThat(maiores.size(), equalTo(2));
assertEquals(400.0, maiores.get(0).getValor(), 0.00001);assertEquals(300.0, maiores.get(1).getValor(), 0.00001);
}
Resultado@Testpublic void deveDevolverTodosLancesCasoNaoHajamLances() {
Leilao leilao = new Leilao("Playstation 3 Novo");
leiloeiro.avalia(leilao);
List<Lance> maiores = leiloeiro.getTresMaiores();assertEquals(0, maiores.size());assertThat(maiores.size(), equalTo(0));
}
Produçãopublic List<Lance> getTresMaiores() {
List<Lance> maiores;maiores = new ArrayList<Lance>(leilao.getLances());Collections.sort(maiores, new Comparator<Lance>() {
public int compare(Lance o1, Lance o2) {if(o1.getValor() < o2.getValor()) return 1;if(o1.getValor() > o2.getValor()) return -1;return 0;
}});maiores = maiores.subList(0, 3);// maiores = maiores.subList(0, maiores.size() > 3
? 3 : maiores.size());return maiores;
}
ExercícioCrie um Leilao e proponha Lance com valores randômicos, como por exemplo, 200, 450, 120, 700, 630, 230. Ao final, verifique que o menor é 120 e o maior é 700.
Resultado@Testpublic void deveEntenderLeilaoComLancesEmOrdemRandomica() {
Usuario joao = new Usuario("Joao");Usuario maria = new Usuario("Joao");Leilao leilao = new Leilao("Playstation 3 Novo");
leilao.propoe(new Lance(joao,200.0));leilao.propoe(new Lance(maria,450.0));leilao.propoe(new Lance(joao,120.0));leilao.propoe(new Lance(maria,700.0));leilao.propoe(new Lance(joao,630.0));leilao.propoe(new Lance(maria,230.0));
Avaliador leiloeiro = new Avaliador();leiloeiro.avalia(leilao);
assertEquals(700.0, leiloeiro.getMaiorLance(), 0.0001);assertEquals(120.0, leiloeiro.getMenorLance(), 0.0001);
}
Exercícioclass MatematicaMaluca {
public int contaMaluca(int numero) {if(numero > 30) return numero * 4;else if(numero > 10) return numero * 3;else return numero * 2;
}}
Resultadoclass MatematicaMalucaTest {
@Testpublic void deveMultiplicarNumerosMaioresQue30() {
MatematicaMaluca matematica = new MatematicaMaluca();assertEquals(50*4, matematica.contaMaluca(50));
}
@Testpublic void deveMultiplicarNumerosMaioresQue10EMenoresQue30() {
MatematicaMaluca matematica = new MatematicaMaluca();assertEquals(20*3, matematica.contaMaluca(20));
}
@Testpublic void deveMultiplicarNumerosMenoresQue10() {
MatematicaMaluca matematica = new MatematicaMaluca();assertEquals(5*2, matematica.contaMaluca(5));
}}
Exercícioclass FiltroDeLances {
public List<Lance> filtra(List<Lance> lances) {ArrayList<Lance> resultado = new ArrayList<Lance>();
for(Lance lance : lances) {if(lance.getValor() > 1000 && lance.getValor() < 3000)
resultado.add(lance);else if(lance.getValor() > 500 && lance.getValor() < 700)
resultado.add(lance);else if(lance.getValor() > 5000)
resultado.add(lance);}return resultado;
}}
Resultadoclass FiltroDeLancesTest {
@Testpublic void deveSelecionarLancesEntre1000E3000() {
Usuario joao = new Usuario("Joao");
FiltroDeLances filtro = new FiltroDeLances();List<Lance> resultado = filtro.filtra(Arrays.asList(
new Lance(joao,2000),new Lance(joao,1000),new Lance(joao,3000),new Lance(joao, 800)));
assertEquals(1, resultado.size());assertEquals(2000, resultado.get(0).getValor(), 0.00001);
}
Resultado@Testpublic void deveSelecionarLancesEntre500E700() {
Usuario joao = new Usuario("Joao");
FiltroDeLances filtro = new FiltroDeLances();List<Lance> resultado = filtro.filtra(Arrays.asList(
new Lance(joao,600),new Lance(joao,500),new Lance(joao,700),new Lance(joao, 800)));
assertEquals(1, resultado.size());assertEquals(600, resultado.get(0).getValor(), 0.00001);
}}
Resultados@Testpublic void deveSelecionarLancesMaioresQue5000() {
Usuario joao = new Usuario("Joao");
FiltroDeLances filtro = new FiltroDeLances();List<Lance> resultado = filtro.filtra(Arrays.asList(
new Lance(joao, 10000),new Lance(joao, 800)));
assertEquals(1, resultado.size());assertEquals(10000, resultado.get(0).getValor(), 0.00001);
}
Resultados@Testpublic void deveEliminarMenoresQue500() {
Usuario joao = new Usuario("Joao");
FiltroDeLances filtro = new FiltroDeLances();List<Lance> resultado = filtro.filtra(Arrays.asList(
new Lance(joao, 400),new Lance(joao, 300)));
assertEquals(0, resultado.size());}
Resultados@Testpublic void deveEliminarEntre3000E5000() {
Usuario joao = new Usuario("Joao");
FiltroDeLances filtro = new FiltroDeLances();List<Lance> resultado = filtro.filtra(Arrays.asList(
new Lance(joao, 4000),new Lance(joao, 3500)));
assertEquals(0, resultado.size());}
Resultado@Testpublic void deve_receber_um_lance() {
Leilao leilao = new Leilao("MacBook Pro 15");assertEquals(0, leilao.getLances().size());
leilao.propoe(new Lance(new Usuario("Steve Jobs"), 2000));
assertEquals(1, leilao.getLances().size());assertEquals(2000.0, leilao.getLances().get(0).getValor(), 0.0001);
}
Resultado@Testpublic void deve_receber_varios_lances() {
Leilao leilao = new Leilao("MacBook Pro 15");leilao.propoe(new Lance(new Usuario("Steve Jobs"), 2000));leilao.propoe(new Lance(new Usuario("Steve Woznick"), 3000));
assertEquals(1, leilao.getLances().size());assertEquals(2000.0, leilao.getLances().get(0).getValor(), 0.0001);assertEquals(3000.0, leilao.getLances().get(1).getValor(), 0.0001);
}
Resultado@Testpublic void nao_deve_receber_um_segundo_lance_do_mesmo_usuario() {
Leilao leilao = new Leilao("MacBook Pro 15");leilao.propoe(new Lance(new Usuario("Steve Jobs"), 2000));leilao.propoe(new Lance(new Usuario("Steve Jobs"), 3000));
assertEquals(1, leilao.getLances().size());assertEquals(2000.0, leilao.getLances().get(0).getValor(), 0.0001);
}
Usuario equals @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; Usuario other = (Usuario) obj; if (id != other.id) return false; if (nome == null) { if (other.nome != null) return false; } else if (!nome.equals(other.nome)) return false; return true; }
produção public void propoe(Lance lance) { if(lances.isEmpty() || !ultimoLanceDado(). getUsuario().equals(lance.getUsuario())) { lances.add(lance); } }
private Lance ultimoLanceDado() { return lances.get(lances.size()-1); }
Resultado @Test public void naoDeveAceitarMaisDoQue5LancesDeUmMesmoUsuario() { Leilao leilao = new Leilao("Macbook Pro 15"); Usuario steveJobs = new Usuario("Steve Jobs"); Usuario billGates = new Usuario("Bill Gates"); leilao.propoe(new Lance(steveJobs, 2000)); leilao.propoe(new Lance(billGates, 3000)); leilao.propoe(new Lance(steveJobs, 4000)); leilao.propoe(new Lance(billGates, 5000)); leilao.propoe(new Lance(steveJobs, 6000)); leilao.propoe(new Lance(billGates, 7000)); leilao.propoe(new Lance(steveJobs, 8000)); leilao.propoe(new Lance(billGates, 9000)); leilao.propoe(new Lance(steveJobs, 10000)); leilao.propoe(new Lance(billGates, 11000)); // deve ser ignorado leilao.propoe(new Lance(steveJobs, 12000)); assertEquals(10, leilao.getLances().size()); int ultimo = leilao.getLances().size() - 1; Lance ultimoLance = leilao.getLances().get(ultimo); assertEquals(11000.0, ultimoLance.getValor(), 0.00001); }
produçãopublic void propoe(Lance lance) {
int total = 0; for(Lance l : lances) { if(l.getUsuario().equals(lance.getUsuario())) total++; }
if(lances.isEmpty() || (!ultimoLanceDado().getUsuario().equals(lance.getUsuario()) && total < 5)) { lances.add(lance); } }
produção public void propoe(Lance lance) { if(lances.isEmpty() || ( !ultimoLanceDado().getUsuario().equals(lance.getUsuario()) && qtdDelancesDo(lance.getUsuario()) < 5)) { lances.add(lance); } }
private int qtdDelancesDo(Usuario usuario) { int total = 0; for(Lance lance : lances) { if(lance.getUsuario().equals(usuario)) total++; } return total; }
produção public void propoe(Lance lance) { if(lances.isEmpty() || podeDarLance(lance.getUsuario())) { lances.add(lance); } }
private boolean podeDarLance(Usuario usuario) { return !ultimoLanceDado().getUsuario().equals(usuario) && qtdDelancesDo(usuario) < 5; }
ExercícioConstruir o método criadorDeLeilao: (Test Data Builder)
@Test public void deveEncontrarOsTresMaioresLances() { Leilao leilao = new CriadorDeLeilao().para("Playstation 3 Novo") .lance(joao, 100.0) .lance(maria, 200.0) .lance(joao, 300.0) .lance(maria, 400.0) .constroi(); leiloeiro.avalia(leilao);
List<Lance> maiores = leiloeiro.getTresMaiores(); assertEquals(3, maiores.size()); assertEquals(400.0, maiores.get(0).getValor(), 0.00001); assertEquals(300.0, maiores.get(1).getValor(), 0.00001); assertEquals(200.0, maiores.get(2).getValor(), 0.00001); }}
Resultadopublic class CriadorDeLeilao {
private Leilao leilao;
public CriadorDeLeilao() { }
public CriadorDeLeilao para(String descricao) { this.leilao = new Leilao(descricao); return this; }
public CriadorDeLeilao lance(Usuario usuario, double valor) { leilao.propoe(new Lance(usuario, valor)); return this; }
public Leilao constroi() { return leilao; }}
ExercícioEnviar uma exceção ao avaliar um leilão com zero lances
public void avalia(Leilao leilao) { // lancando a excecao if(leilao.getLances().size() ==0) throw new RuntimeException("Não é possível avaliar um leilão sem lances");
Para tratar pode-se usar try catch
Resultado
@Testpublic void naoDeveAvaliarLeiloesSemNenhumLanceDado() { try { Leilao leilao = new CriadorDeLeilao() .para("Playstation 3 Novo") .constroi();
leiloeiro.avalia(leilao); Assert.fail(); } catch(RuntimeException e) { // deu certo! }}
Resultado
Pode-se usar a anotaço @Test(expected= exceção.class)
@Test(expected=RuntimeException.class)public void naoDeveAvaliarLeiloesSemNenhumLanceDado() { Leilao leilao = new CriadorDeLeilao() .para("Playstation 3 Novo") .constroi();
leiloeiro.avalia(leilao);}
ExercícioassertThat (calculado , matcher(expectativa)
class AvaliadorTest {
@Test public void deveEntenderLancesEmOrdemCrescente() {
Leilao leilao = new CriadorDeLeilao() .para("Playstation 3 Novo") .lance(joao, 250) .lance(jose, 300) .lance(maria, 400) .constroi();
leiloeiro.avalia(leilao);
assertThat(leiloeiro.getMenorLance(), equalTo(250.0)); assertEquals(400.0, leiloeiro.getMaiorLance(), 0.00001); }}
ExercícioHamcrest
http://code.google.com/p/hamcrest/downloads/detail?name=hamcrest-all-1.3.0RC1.jar
http://code.google.com/p/hamcrest/wiki/Tutorial
Exercício @Test public void deveEncontrarOsTresMaioresLances() { Leilao leilao = new CriadorDeLeilao() .para("Playstation 3 Novo") .lance(joao, 100) .lance(maria, 200) .lance(joao, 300) .lance(maria, 400) .constroi();
leiloeiro.avalia(leilao);
List<Lance> maiores = leiloeiro.getTresMaiores(); assertEquals(3, maiores.size());
assertEquals(400.0, maiores.get(0).getValor(), 0.00001); assertEquals(300.0, maiores.get(1).getValor(), 0.00001); assertEquals(200.0, maiores.get(2).getValor(), 0.00001); }
ExercícioassertThat(maiores, hasItems( new Lance(maria, 400), new Lance(joao, 300), new Lance(maria, 200) ));