🧪 2.2 Mudando a maneira de desenvolver
Desta vez, inverteremos o fluxo: Começaremos pelos Testes. O objetivo é aplicar o estilo “KISS” (Keep It Simple, Stupid): pensar no cenário mais simples, escrever o teste que falha e implementar apenas o código necessário para vê-lo “verde”.
🔴 Passo 1: O Teste que Falha (Red)
Iniciamos com a regra: um usuário não pode dar dois lances seguidos.
@Test
void naoDeveAceitarDoisLancesSeguidosDoMesmoUsuario() {
var leilao = new Leilao("Macbook Pro 16");
var steveJobs = new Usuario("Steve Jobs");
leilao.propoe(new Lance(steveJobs, 2000));
leilao.propoe(new Lance(steveJobs, 3000));
assertThat(leilao.getLances()).hasSize(1);
assertThat(leilao.getLances().get(0).getValor()).isEqualTo(2000.0);
}🟢 Passo 2: A Implementação Mais Simples (Green)
Modificamos o método propoe() apenas o suficiente para passar o teste:
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);
}🔵 Passo 3: Refatoração (Refactor)
Com o teste garantindo o comportamento, podemos limpar a regra de “5 lances máximos” de forma segura:
@Test
void naoDeveAceitarMaisDoQue5LancesDeUmMesmoUsuario() {
var leilao = new Leilao("Macbook Pro 16");
var steveJobs = new Usuario("Steve Jobs");
var billGates = new Usuario("Bill Gates");
// Intercalamos os lances para respeitar a regra de sequência
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));
// O 11º lance (6º do Steve) deve ser ignorado
leilao.propoe(new Lance(steveJobs, 12000));
assertThat(leilao.getLances()).hasSize(10);
assertThat(leilao.getLances().get(9).getValor()).isEqualTo(11000.0);
}
---
## 🏗️ Refatoração de Elite
O código resultante utiliza métodos auxiliares privados para manter a clareza da intenção de negócio:
public void propoe(Lance lance) {
if (podeDarLance(lance.getUsuario())) {
lances.add(lance);
}
}
private boolean podeDarLance(Usuario usuario) {
return lances.isEmpty() || (!ultimoLanceDado().getUsuario().equals(usuario) && qtdDeLancesDo(usuario) < 5);
}
private int qtdDeLancesDo(Usuario usuario) {
return (int) lances.stream()
.filter(l -> l.getUsuario().equals(usuario))
.count();
}O Ciclo Infinito da Qualidade ⚡
No TDD, o código de produção evolui guiado pela necessidade real dos testes. Isso evita a “Super-engenharia” e garante que 100% da lógica implementada tenha um propósito validado. 🏁