Вопрос

Обычно DUnit работает следующим образом: вы пишете несколько опубликованных методов, а DUnit запускает их в качестве тестов.Я хочу сделать немного другое.Я хочу создавать тесты во время выполнения на основе данных.Я пытаюсь протестировать конкретный модуль, который обрабатывает входные файлы для создания выходных файлов.У меня есть набор тестовых входных файлов с соответствующими заведомо исправными выходными файлами.Идея состоит в том, чтобы динамически создавать тесты, по одному для каждого входного файла, которые обрабатывают входные данные и проверяют выходные данные на соответствие заведомо исправным.

Однако фактический источник данных здесь не важен.Трудность заключается в том, чтобы заставить DUnit работать на основе данных.Для решения этой задачи предположим, что источником данных является просто генератор случайных чисел.Вот пример конкретной проблемы, которая затрагивает суть проблемы:

Создайте несколько тестовых объектов (TTestCase или что-то еще) во время выполнения, скажем, 10 из них, где каждый

  1. Именуется во время выполнения из случайно сгенерированного целого числа.(Под «именем» я подразумеваю имя теста, которое появляется в дереве выполнения тестов.)
  2. Проходит или не проходит на основе случайного целого числа.Сдать за четное, провалить за нечетное.

Судя по дизайну DUnit, это выглядит как будто он был разработан с достаточной гибкостью, чтобы сделать такие вещи возможными.Хотя я не уверен, что это так.Я попытался создать свой собственный тестовый класс, унаследовав его от TAbstractTest и ITest, но некоторые важные методы были недоступны.Я также пытался наследовать от TTestCase, но этот класс тесно связан с идеей запуска опубликованных методов (а тесты названы в честь методов, поэтому я не мог просто назвать один, скажем, «go», потому что тогда все мои тесты будут называться «go», и я хочу, чтобы все мои тесты имели индивидуальное имя).

Или, альтернативно, есть ли какая-то альтернатива DUnit, которая могла бы делать то, что я хочу?

Это было полезно?

Решение

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.

Другие советы

Я бы сказал, что вам по сути нужна одна функция «супертеста», которая затем вызывает другие тесты, по одному для каждого файла данных.Это то, что мы делаем с одним из наших тестов DUnit.Вы просто загружаете каждый доступный файл по очереди в цикле и запускаете тест с помощью Check, если это необходимо.

Альтернатива, которую мы также используем в том же проекте для тестирования окончательного приложения, загрузки и анализа его данных, заключается в использовании чего-то вроде FinalBuilder для цикла приложения (предположительно, вы также можете зациклить приложение DUnit и использовать параметр) с различные файлы данных.Затем приложение запускается, выполняет анализ и закрывается после сохранения.Затем другое приложение сравнивает полученные данные с идеальными и при необходимости сообщает об ошибке.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top