Pergunta

A forma DUnit normalmente funciona é você escrever alguns métodos publicados, e DUnit corre-los como testes. O que eu quero fazer é um pouco diferente. Eu quero criar testes em tempo de execução com base em dados. Eu estou tentando testar um módulo específico que processa arquivos de entrada para cria arquivos de saída. Eu tenho um conjunto de arquivos de entrada de teste com bons arquivos de saída conhecidos correspondente. A ideia é criar dinamicamente testes, um para cada arquivo de entrada, que processam as entradas e verificar as saídas contra os bons conhecidos.

A fonte real de dados aqui, porém, não é importante. A dificuldade está fazendo DUnit comportar de uma maneira orientada a dados. Por causa deste problema, suponha que a fonte de dados eram apenas um gerador de números aleatórios. Aqui está um exemplo de problema concreto que chega ao coração da dificuldade:

Crie alguns objetos de teste (TTestCase ou qualquer outro) em tempo de execução, dizem 10 deles, onde cada um

  1. é chamado em tempo de execução de um número inteiro gerado aleatoriamente. (Por 'nome' quero dizer o nome do teste que aparece na árvore de test-Runner.)
  2. passa ou falha com base em um número inteiro aleatório. Passe para mesmo, falhar por estranho.

A partir do projeto de DUnit, ele aparência como ele foi projetado com flexibilidade suficiente em mente para fazer essas coisas possíveis. Eu não tenho certeza de que é embora. Tentei criar minha própria classe de teste por herança de TAbstractTest e ITest, mas alguns métodos cruciais não eram acessíveis. Eu também tentei herdando de TTestCase, mas que a classe está intimamente ligada à idéia de executar métodos publicados (e os testes são nomeados após os métodos, então eu não poderia ter apenas uma única chamada, digamos, 'go', porque então todos os meus testes seria chamado de 'go', e eu quero todos os meus testes para ser nomeado individualmente).

Ou, alternativamente, existe alguma alternativa para DUnit que poderia fazer o que eu quero?

Foi útil?

Solução

program UnitTest1;

{$IFDEF CONSOLE_TESTRUNNER}
{$APPTYPE CONSOLE}
{$ENDIF}

uses
  Forms, Classes, SysUtils,
  TestFramework,
  GUITestRunner,
  TextTestRunner;

{$R *.RES}

type
  TIntTestCase = class(TTestCase)
  private
    FValue: Integer;
  public
    constructor Create(AValue: Integer); reintroduce;
    function GetName: string; override;
  published
    procedure Run;
  end;

{ TIntTestCase }

constructor TIntTestCase.Create(AValue: Integer);
begin
  inherited Create('Run');
  FValue := AValue;
end;

function TIntTestCase.GetName: string;
begin
  Result := Format('Run_%.3d', [FValue]);
end;

procedure TIntTestCase.Run;
begin
  Check(FValue mod 2 = 0, Format('%d is not an even value', [FValue]));
end;

procedure RegisterTests;
const
  TestCount = 10;
  ValueHigh = 1000;
var
  I: Integer;
begin
  Randomize;
  for I := 0 to TestCount - 1 do
    RegisterTest(TIntTestCase.Create(Random(ValueHigh) + 1));
end;

begin
  Application.Initialize;
  RegisterTests;
  if IsConsole then
    TextTestRunner.RunRegisteredTests
  else
    GUITestRunner.RunRegisteredTests;
end.

Outras dicas

Eu diria que basicamente quer ter uma função única "super-test", que em seguida, chama outros testes, um para cada arquivo de dados. Isso é o que fazemos com um de nossos testes DUnit. Você acabou de carregar cada arquivo disponível, por sua vez em um loop, e executar o teste com da Check conforme o caso.

A alternativa, que também usamos no mesmo projeto para testar o aplicativo final e sua carga e análise de dados, é usar algo como FinalBuilder para fazer um loop sobre a aplicação (presumivelmente você poderia loop no aplicativo DUnit muito e usar um parâmetro) com os vários arquivos de dados diferentes. O aplicativo, em seguida, corre, faz uma análise, em seguida, sai depois de salvar. Outro aplicativo, em seguida, compara os dados resultantes com os dados ideal, e relata uma falha se for o caso.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top