Cada vez mais é primordial que o desenvolvedor invista parte de seu tempo na construção de testes, se for utilizando TDD, melhor ainda. Uma boa suíte de teste nos dá segurança e confiança no momento de fazer um refactoring ou a correção de um bug. Também melhora significativamente o design do nosso código, pois, para pode testar de forma realmente unitária, nossas classes precisam ter baixo acoplamento, boa coesão, serem realmente testáveis.
Vou criar um exemplo de calculadora inspirado no padrão Builder seguindo os passos do TDD - Red, Green, Refactor. Primeiro vamos escrever a classe de teste, e está deverá falhar antes da implementação da calculadora em si.
type
TTestCalculadora = class(TTestCase)¹
private
published²
procedure SomaDe2Mais3DeveSer5;
end;
implementation
{ TTestCalculadora }
procedure TTestCalculadora.SomaDe2Mais3DeveSer5;
var
vCalculadora: TCalculadora;
begin
vCalculadora := TCalculadora.Create;
try
CheckEquals(5, FCalculadora.Soma(2).Soma(3).GetTotal);
finally
vCalculadora.Free;
end;
end;
initialization
RegisterTest('Calculadora', TTestCalculadora.Suite);³
¹A classe deve herdar de TTestCase, que faz parte do framework DUnit. ²Os métodos que implementam os testes devem ser declarados na seção published, para que possam ser lidos utilizando RTTI. ³A classe deve ser registrada.Vamos ver se o teste falha. Para os mais puristas, o código não compilar já é o suficiente para a fase Red, eu particularmente, gosto de fazer a implementação suficiente para compilar o código, de qualquer modo, é importante garantir que o teste falhe. Então vou criar a classe calculadora mais não vou implementar o método GetTotal e no método Soma apenas vou retornar a Calculadora para não obter um Access Violation.
type
TCalculadora = class
private
public
function Soma(const AValor: Double): TCalculadora;
function GetTotal: Double;
end;
implementation
{ TCalculadora }
function TCalculadora.GetTotal: Double;
begin
end;
function TCalculadora.Soma(const AValor: Double): TCalculadora;
begin
Result := Self;
end;
Rodando o teste, o mesmo vai falhar, pois o método retorna um valor qualquer atribuído em tempo de execução. Veja na imagem abaixo.Agora vamos implementar o método Soma e GetTotal e rodar o teste novamente.
type
TCalculadora = class
private
FValor: Double;
public
function Soma(const AValor: Double): TCalculadora;
function GetTotal: Double;
end;
function TCalculadora.GetTotal: Double;
begin
Result := FValor;
end;
function TCalculadora.Soma(const AValor: Double): TCalculadora;
begin
FValor := FValor + AValor;
Result := Self;
end;
O mesmo deve passar, como na imagem a seguir.Estamos indo bem, vamos escrever mais um teste, vamos criar um método para resetar o valor. Aqui está o nosso teste.
procedure TTestCalculadora.DeveResetarOValor; var vCalculadora: TCalculadora; begin vCalculadora := TCalculadora.Create; try vCalculadora.Reset; CheckEquals(0, vCalculadora.GetTotal, 'Não resetou o valor'); finally vCalculadora.Free; end; end;
Crie o método Reset na classe calculadora, mais não implemente.
function TCalculadora.Reset: TCalculadora; begin end;
Agora rode o teste e você pode ver que... o teste passa. Mesmo sem implementação, ele passa. Por isso é tão importante garantir que o teste falhe antes de implementar, só assim ele tem valor. Um teste que passa antes mesmo de implementar não testa nada, não agrega valor algum. Vamos corrigir isso de modo que o teste falhe.
procedure TTestCalculadora.DeveResetarOValor; var vCalculadora: TCalculadora; begin vCalculadora := TCalculadora.Create; try vCalculadora.Soma(1).Reset; CheckEquals(0, vCalculadora.GetTotal, 'Não resetou o valor'); finally vCalculadora.Free; end; end;
Rode o teste e veja que o mesmo vai falhar. Feito isso vamos implementar o método Reset adequadamente para que o teste passe.
function TCalculadora.Reset: TCalculadora; begin //Evitando número mágicos FValor := ZeroValue; Result := Self; end;
Ainda há vários recursos do DUnit a serem explorados mais vou deixar isso para um próximo post, onde mostrarei também como testar exceções conhecidas.
Não deixem de postar sobre dúvidas ou sugestões e escrevam testes. ;D
Abraços.


E ai Fabricio !
ResponderExcluirTudo bom ?
Que bom que você começou esse blog... Assim posso acompanhar o seu trabalho mesmo não estando mais trabalhando junto...
Já adicionei o feed no google readers...
Att,
Sakamoto
MyTraceLog - Registro de um DBA
http://mytracelog.blogspot.com
Obrigado por acompanhar.
ResponderExcluirVou me esforçar para manter uma frequência legal de posts e variar um pouco os temas.
Abraços