{
return 0;
}
}
Ainda não há uma repetição de código grande a ser eliminada, então podemos
ir para o próximo teste, que é o caso do carrinho conter apenas um produto. O teste:
51
5.1. O Problema do Carrinho de Compras
Casa do Código
[Test]
public void DeveRetornarValorDoItemSeCarrinhoCom1Elemento()
{
CarrinhoDeCompras carrinho = new CarrinhoDeCompras();
carrinho.Adiciona(new Item("Geladeira", 1, 900.0));
MaiorPreco algoritmo = new MaiorPreco();
double valor = algoritmo.Encontra(carrinho);
Assert.AreEqual(900.0, valor, 0.0001);
}
Para fazer esse teste passar, precisaremos escrever um pouco mais de código. Mas
não há muitas dúvidas sobre o algoritmo nesse momento: se o carrinho estiver vazio,
retorna 0. Caso contrário, retorna o valor do primeiro elemento desse carrinho:
public double Encontra(CarrinhoDeCompras carrinho)
{
if(carrinho.Itens.Count == 0) return 0;
return carrinho.Itens[0].ValorTotal;
}
Por fim, o cenário que resta: é necessário encontrar o item de maior valor caso o
carrinho contenha muitos itens:
[Test]
public void DeveRetornarMaiorValorSeCarrinhoContemMuitosElementos()
{
CarrinhoDeCompras carrinho = new CarrinhoDeCompras();
carrinho.Adiciona(new Item("Geladeira", 1, 900.0));
carrinho.Adiciona(new Item("Fogão", 1, 1500.0));
carrinho.Adiciona(new Item("Máquina de Lavar", 1, 750.0));
MaiorPreco algoritmo = new MaiorPreco();
double valor = algoritmo.Encontra(carrinho);
Assert.AreEqual(1500.0, valor, 0.0001);
}
52
Casa do Código
Capítulo 5. TDD e Design de Classes
Vamos à implementação. É necessário navegar pelos itens da coleção, procu-
rando pelo item de maior valor total. Para armazenar esse maior valor é necessário
um atributo da classe, batizado de maior":
public double Encontra(CarrinhoDeCompras carrinho)
{
if(carrinho.Itens.Count == 0) return 0;
double maior = carrinho.Itens[0].ValorTotal;
foreach(var item in carrinho.Itens) {
if(maior < item.ValorTotal) {
maior = item.ValorTotal;
}
}
return maior;
}
Com todos os testes passando, é hora de avaliá-los. Observe, por exemplo, o
último teste que escrevemos. Veja que o teste instancia a classe MaiorPreco, passa
para ela um carrinho e verifica o retorno desse método. Repare que todo o cená-
rio montado foi em cima da classe CarrinhoDeCompras; não fizemos nada na classe
MaiorPreco.
Isso pode ser um mau sinal. Sabemos que uma das vantagens da orientação a
objetos em relação a códigos mais procedurais é justamente a capacidade de unir
dados e comportamentos. A classe MaiorPreco parece estranha, já que não houve
necessidade de setar atributos ou qualquer outro dado nela.
Sabendo desse possível problema na classe, vamos ver seu código. Repare que o
método encontra() faz uso do carrinho praticamente o tempo todo, e não faz uso
de nada específico da sua própria classe.
A pergunta é: por que criamos essa classe? Por que o método encontra() não
está dentro da própria classe CarrinhoDeCompras ?
Vamos fazer essa mudança.
Se levarmos toda a lógica do método
encontra() para um método chamado, por exemplo, maiorValor() dentro do
CarrinhoDeCompras, a classe ficará assim:
public double MaiorValor()
{
if(Itens.Count == 0) return 0;
53
5.1. O Problema do Carrinho de Compras
Casa do Código
double maior = Itens[0].ValorTotal;
foreach(var item in Itens) {
if(maior < item.ValorTotal) {
maior
= item.ValorTotal;
}
}
return maior;
}
Já os testes ficarão assim:
[TestFixture]
public class CarrinhoDeComprasTest
{
[Test]
public void DeveRetornarZeroSeCarrinhoVazio()
{
CarrinhoDeCompras carrinho = new CarrinhoDeCompras();
Assert.AreEqual(0.0, carrinho.MaiorValor(), 0.0001);
}
[Test]
public void DeveRetornarValorDoItemSeCarrinhoCom1Elemento()
{
CarrinhoDeCompras carrinho = new CarrinhoDeCompras();
carrinho.Adiciona(new Item("Geladeira", 1, 900.0));
Assert.AreEqual(900.0, carrinho.MaiorValor(), 0.0001);
}
[Test]
public void DeveRetornarMaiorValorSeCarrinhoContemMuitosElementos()
{
CarrinhoDeCompras carrinho = new CarrinhoDeCompras();
carrinho.Adiciona(new Item("Geladeira", 1, 900.0));
carrinho.Adiciona(new Item("Fogão", 1, 1500.0));
carrinho.Adiciona(new Item("Máquina de Lavar", 1, 750.0));
54
Casa do Código
Capítulo 5. TDD e Design de Classes
Assert.AreEqual(1500.0, carrinho.MaiorValor(), 0.0001);
}
}
Veja agora que nosso teste está muito mais claro e elegante.
Os testes do
CarrinhoDeCompras instanciam um carrinho, montam o cenário desejado e invo-
cam um método do próprio carrinho. Agora o código dentro do teste parece melhor
e mais orientado a objetos. O comportamento está no lugar esperado. É justamente
isso que se espera de um código de qualidade.
Antes de continuarmos, vamos refletir um pouco sobre como descartamos a pri-
meira solução e chegamos à solução que melhor resolveu o problema.
5.2
Testes que influenciam no design de classes
O que nos fez optar pelo segundo caminho ao invés do primeiro? Em que momento
mudamos o rumo da implementação? Releia o texto acima. Repare que o que nos