Original em Vinicius Quaiato: http://viniciusquaiato.com/blog/index.php/tdd-test-drive…ent-c-parte-ii/
TDD – Test-driven Development – Parte I
TDD – Test-driven Development – Parte III
Após o que foi apresentado no primeiro post da série, faremos nesta segunda parte um exemplo prático de TDD.
Para efeito didático este será um exemplo bem simples e trivial, para que possamos focar nas práticas de TDD.
Antes de começarmos gostaria de mencionar o “mantra do TDD”:
“Red, green, refactoring“
Ou seja, escreva um teste que falhe, na verdade um teste que nem compila (vermelho). Escreva um código que compile e faça o teste passar (verde), mesmo que seja um código ruim. Então, após o teste passar melhoramos o código, com a finalidade de deixá-lo mais claro, coeso e simples (refactoring).
Tendo isso em mente, vamos para o nosso caso de uso em C#:
Desenvolver uma aplicação bancária que controle saques, depósitos e transferências.
Como eu disse o caso de uso é simples, para que foquemos no TDD.
Vamos criar uma nova solution no Visual Studio. Aqui já começa a mudança de pensamento. Antes de criar o projeto da conta bancária, eu começo criando o projeto de testes da conta bancária. Eu gosto de pensar assim para ir me acostumando com a idéia do Test First.

TDD - criando projeto de testes
Agora que estamos com o projeto criado, vamos escrever nosso primeiro teste. Vocês vão perceber que a prática do TDD nos leva a pensar melhor em nossas classes. Vamos ver.
Bom, em nosso primeiro teste vamos nos assegurar de que quando uma conta seja criada ela obrigatóriamente necessite de um depósito inicial:
[TestMethod]
public void Deve_Criar_Conta_Com_Deposito_Inicial()
{
ContaBancaria conta = new ContaBancaria(50.0m);
Assert.AreEqual(50, conta.SaldoAtual);
}
Como podemos ver, este teste nem irá compilar, afinal, estamos criando o teste antes mesmo de criarmos a classe ContaBancaria.
public class ContaBancaria
{
public decimal SaldoAtual { get; set; }
public ContaBancaria(decimal depositoInicial) { }
}
Assi podemos executar nosso teste. Eu gosto de utilizar dois atalhos CTRL + R + T (executa o teste corrente em modo debug) ou CTRL + R + A (executa todos os testes da solution em modo debug).
Teremos o resultado como abaixo:

TDD - executando primeiro teste
Este teste falhou. Ótimo! Obtemos um red e sabemos que estamos no caminho certo. Aconteceu que estávamos esperando um saldo de 50 e o saldo obtido foi 0.
Agora devemos voltar ao código e fazer o teste passar:
public class ContaBancaria
{
public decimal SaldoAtual { get; set; }
public ContaBancaria(decimal depositoInicial)
{
this.SaldoAtual += depositoInicial;
}
}
Neste caso nossa mudança é bem pequena. Agora vamos executar o mesmo teste e ver o que acontece:

TDD - executando primeiro teste verde
Pronto! Obtivemos um verde, e isso quer dizer que podemos prosseguir, escrevendo os próximos testes. Antes disso acontecer, devemos lembrar do próximo passo: refactoring!
Vamos voltar ao nosso código e entender o que pode ser refatorado.
Me parece que a propriedade SaldoAtual não deveria ter um setter público, desta forma vamos torná-lo privado:
public class ContaBancaria
{
public decimal SaldoAtual { get; private set; }
public ContaBancaria(decimal depositoInicial)
{
this.SaldoAtual += depositoInicial;
}
}
Agora devemos novamente executar nossos testes, para termos certeza de que não acabamos estragando nada.
Agora precisamos garantir que o depósito inicial seja um depósito válido. Ou seja, o que acontece com um depósito inicial igual a 0? E se for menor que 0?
De acordo com a regra de negócio que eu inventei, uma conta sempre deve ser criada com um depósito inicial. Quando quisermos carregar uma conta específica, utilizaremos outra notina e não o construtor público.
Assim, vamos criar um deste que garanta que o depósito inicial seja válido.
Vamos usar um atributo(attribute) do framework de testes do visual studio que nos permite testar se um determinado teste lança uma exceção – ExpectedException:
[TestMethod]
[ExpectedException(typeof(DepositoInicialInvalidoException))]
public void Deve_Lancar_Excecao_Deposito_Inicial_Invalido()
{
ContaBancaria conta = new ContaBancaria(0);
}
Para que este teste compile, vamos criar uma Exception:
public class DepositoInicialInvalidoException : Exception
{
public DepositoInicialInvalidoException()
: base("Depósito inicial deve ser um valor maior que 0(Zero)!") { }
}
Agora vamos rodar nosso test. Pumba! Obtivemos um red. Afinal, não estamos validando o depósito inicial. Vamos fazer o código passar:
public ContaBancaria(decimal depositoInicial)
{
if (depositoInicial <= 0)
throw new DepositoInicialInvalidoException();
this.SaldoAtual += depositoInicial;
}
Agora já podemos executar nossos testes (sim, devemos executar todos os testes, para ter certeza que nada quebrou no meio do caminho). Pronto, temos um verde. Vamos para o refactoring. A validação dentro do construtor não ficou muito elegante. Afinal, no futuro podemos ter outros tipos de validações, desta forma vamos refatorar:

TDD - refatorando
Assim o visual studio criará para nós um método, e ficaremos com a seguinte estrutura:
public ContaBancaria(decimal depositoInicial)
{
Validar(depositoInicial);
this.SaldoAtual += depositoInicial;
}
private void Validar(decimal depositoInicial)
{
if (depositoInicial <= 0)
throw new DepositoInicialInvalidoException();
}
É importante que a cada refatoring, cada mudança de código, executemos novamente os testes. Mesmo que achemos que a mudança é pouca e pequena, isso nos fará ter o hábito de sempre executar os testes, e no futuro faremos isso para mudanças mais drásticas e severas.
Bom pessoal, nesta segunda parte espero ter mostrado o início do TDD utilizando C# + Visual Studio.
Na próxima parte deste artigo criaremos os testes para depósitos e saques.
Abraços,
Vinicius Quaiato.