🧪 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. 🏁


⬅️ Capítulo Anterior | Próximo Capítulo ➡️