Base de Conhecimento

Desenvolvimento Orientado a Testes

O que é Desenvolvimento Orientado por Testes?

O Desenvolvimento Orientado por Testes (TDD) é um processo de desenvolvimento de software introduzido por Kent Beck como parte da metodologia de programação extrema. No TDD, os testes unitários são escritos primeiro antes de quaisquer implementações serem desenvolvidas.

Os requisitos são capturados como casos de teste. Como novos requisitos são acrescentados ao software, o mesmo acontece com os novos casos de teste. À medida que o sistema é desenvolvido, construímos uma imagem maior dos requisitos e aumentamos a cobertura dos testes unitários.

O processo TDD

O processo recomendado pela TDD é o seguinte:

  1. Escrever um teste de reprovação.
  2. Execute os testes, que devem ser reprovados.
  3. Escreva o código mais simples possível para que o novo teste seja aprovado.
  4. Execute os testes, assegurando que eles agora passem.
  5. Refatorar conforme necessário, executando os testes posteriormente para garantir que a funcionalidade seja preservada.
  6. Repita o processo para novos requisitos.

Um ponto-chave aqui é que os testes são adicionados primeiro antes de qualquer desenvolvimento ser feito para implementar a funcionalidade. Escrever a solução mais simples permite que o teste seja aprovado, depois isto pode ser refinado por refatoração. Os testes então garantem que qualquer refatoração não tenha introduzido nenhum defeito.

Benefícios

O desenvolvimento orientado por testes geralmente produz códigos de melhor qualidade e reduz a margem para defeitos. Ele encoraja o uso de pequenas iterações ao desenvolver software.

Um efeito colateral útil é que os testes servem como uma forma de documentação para as exigências do software.

O código desenvolvido sob TDD pode levar a um código flexível e extensível. Isto porque os desenvolvedores muitas vezes têm que pensar em termos de unidades menores que podem ser testadas isoladamente e integradas em conjunto. Como apenas a quantidade mínima de código é adicionada para que os testes sejam aprovados, é mais provável que os próprios testes cubram todos os caminhos do código no software.

Quando usado em conjunto com um sistema de controle de fonte, em caso de falha nos testes, o código pode ser revertido para a última versão que teve um conjunto completo de testes que passaram.

Limitações

Embora seja fácil de usar o TDD com novos projetos, é difícil de aplicar aos sistemas existentes ou herdados. Se um novo código for adicionado ao software antigo, então claramente estas novas partes podem ser desenvolvidas com TDD, mas adicionar testes ao código antigo pode ser difícil e demorado.

Alguns processos são difíceis de testar, tais como processos de Interface de Usuário ou conectividade com banco de dados.

Um grande número de testes de aprovação pode oferecer uma falsa sensação de segurança, levando a testes insuficientes de outras atividades.

Desenvolver e manter uma grande quantidade de testes pode ser um processo demorado.

Implementando o TDD com Delphi

O desenvolvimento orientado a testes pode ser facilmente realizado usando DUnitX, a estrutura de teste da unidade que é fornecida com Delphi. Usando o assistente integrado no Delphi, é fácil criar um projeto de teste DUnitX, completo com uma unidade de teste e alguns testes de amostra.

Escrever um teste de falha pode ser tão simples quanto escrever um teste vazio que não chama nenhuma funcionalidade:

unit Tests.VATCalculator;

interface

uses
  DUnitX.TestFramework;

type
  [TestFixture]
  TTestVATCalculator = class
  public
    [Test]
    [TestCase ('100_Pounds', '100,20')]
    procedure TestGetVATAmount(const NetAmount: Currency; const ExpectedAmount: Currency);
  end;

implementation

procedure TTestVATCalculator.TestGetVATAmount(const NetAmount: Currency; const ExpectedAmount: Currency);
begin
  var ReturnValue: Currency;
  // No implementation
  Assert.AreEqual(ExpectedAmount, ReturnValue);
end;

initialization

  TDUnitX.RegisterTestFixture(TTestVATCalculator);

end.


A execução deste teste resultará na falha do teste. Implementar a funcionalidade para o teste com o código mais simples possível:

unit VAT.Calculator.Interfaces;

interface

type
  IVATCalculator = interface
    ['{1576AC66-A116-47EB-9C6A-23D4E2C21B2C}']
    function GetVAT(const NetAmount: Currency): Currency;
  end;

implementation

end.

 

unit VAT.Calculator;

interface

uses
  VAT.Calculator.Interfaces;

type
  TVATCalculator = class(TInterfacedObject, IVATCalculator)
  public
    function GetVAT(const NetAmount: Currency): Currency;
  end;

implementation

function TVATCalculator.GetVAT(const NetAmount: Currency): Currency;
begin
  Result := NetAmount * 20 / 100;
end;

end.

 

unit Tests.VATCalculator;

interface

uses
  DUnitX.TestFramework,
  VAT.Calculator.Interfaces;

type
  [TestFixture]
  TTestVATCalculator = class
  private
    FVATCalculator: IVATCalculator;
  public
    [Setup]
    procedure Setup;

    [Test]
    [TestCase ('100_Pounds', '100,20')]
    procedure TestGetVATAmount(const NetAmount: Currency; const ExpectedAmount: Currency);
  end;

implementation

uses
  VAT.Calculator;

procedure TTestVATCalculator.Setup;
begin
  FVATCalculator := TVATCalculator.Create;
end;

procedure TTestVATCalculator.TestGetVATAmount(const NetAmount: Currency; const ExpectedAmount: Currency);
var
  ReturnValue: Currency;
begin
  ReturnValue := FVATCalculator.GetVAT(NetAmount);

  Assert.AreEqual(ExpectedAmount, ReturnValue);
end;

initialization

  TDUnitX.RegisterTestFixture(TTestVATCalculator);

end.

Os testes agora serão aprovados e o processo pode ser continuado para acrescentar mais requisitos e refatorar conforme necessário.

Conclusão

O desenvolvimento orientado a testes é uma ferramenta poderosa para capturar os requisitos e garantir que os testes sejam desenvolvidos ao mesmo tempo que o software. É melhor utilizado para novos projetos ou para adicionar novos módulos a projetos existentes. Embora possa ser demorado, os testes fornecem um mecanismo valioso para garantir que qualquer nova adição ao software não quebre nenhuma funcionalidade existente. Ele continua sendo uma ferramenta muito útil na caixa de ferramentas de um desenvolvedor de software.

 

Written by James Goodger
Diretor, UK

Contato

Deixe-nos ajudá-lo a realizar seus sonhos.