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