пятница, 29 марта 2013 г.

Шаблоны и тесты DUnit

Предыдущая серия была тут:
http://18delphi.blogspot.com/2013/03/dunit_29.html

Будем развивать идею тестирования TIntStack и TStringStack. Только сделаем это ОДНОЙ примесью. Убрав дубликаты вида:

procedure TIntStackTest.DoIt;
const
 cEtalons : array [0..3] of integer = (10, 20, 3, 5);
var
 l_S : TIntStack;
 l_I : Integer;
begin
 l_S := TIntStack.Create;
 try
  for l_I := Low(cEtalons) to High(cEtalons) do
   l_S.Push(cEtalons[l_I]);
  for l_I := High(cEtalons) downto Low(cEtalons) do
   Check(l_S.Pop = cEtalons[l_I]);
 finally
  FreeAndNil(l_S);
 end;//try..finally
end;//TIntStackTest.DoIt


и:

procedure TStringStackTest.DoIt;
const
 cEtalons : array [0..3] of String = ('мыма', 'мыла', 'раму', 'весело');
var
 l_S : TStringStack;
 l_I : Integer;
begin
 l_S := TStringStack.Create;
 try
  for l_I := Low(cEtalons) to High(cEtalons) do
   l_S.Push(cEtalons[l_I]);
  for l_I := High(cEtalons) downto Low(cEtalons) do
   Check(l_S.Pop = cEtalons[l_I]);
 finally
  FreeAndNil(l_S);
 end;//try..finally
end;//TStringStackTest.DoIt


Нарисуем следующую диаграмму:

Получаем следующий код:

SandBox.dpr:
 
program SandBoxTest;
 
uses
  TestFrameWork
  GUITestRunner,
  IntStack,
  IntStackTest,
  StringStack,
  StringStackTest,
  IntStackTestViaMixIn,
  StringStackTestViaMixIn
  ;
 
begin
 GUITestRunner.RunRegisteredTests;
end.

----------------------------------

StackTest.imp.pas:

{$IfNDef StackTest_imp}
 
{$Define StackTest_imp}
 TEtalonData = ItemsHolder;
 
 _StackTest_ = {mixin} class(TTestCase)
 published
   procedure DoIt;
 protected
 // protected methods
   function GetEtalonData: TEtalonData; virtual; abstract;
   function ArrayToEtalon(const aData: array of _ItemType_): TEtalonData;
     {* Вспомогательная функция появившаяся оттого, что динамические массивы умеет к открытым приводиться автоматом, а обратно - нет }
 end;//_StackTest_
 
{$Else StackTest_imp}
 
procedure _StackTest_.DoIt;
var
 l_Etalons : TEtalonData;
 l_S : _StackType_;
 l_I : Integer;
begin
 l_S := _StackType_.Create;
 try
  l_Etalons := GetEtalonData;
  for l_I := Low(l_Etalons) to High(l_Etalons) do
   l_S.Push(l_Etalons[l_I]);
  for l_I := High(l_Etalons) downto Low(l_Etalons) do
   Check(l_S.Pop = l_Etalons[l_I]);
 finally
  FreeAndNil(l_S);
 end;//try..finally
end;
 
function _StackTest_.ArrayToEtalon(const aData: array of _ItemType_): TEtalonData;
var
 l_I : Integer;
begin
 SetLength(Result, Length(aData));
 for l_I := Low(aData) to High(aData) do
  Result[l_I] := aData[l_I];
end;
 
{$EndIf StackTest_imp}

--------------------------------------
IntStackTestViaMixIn.pas:

unit IntStackTestViaMixIn;
 
interface
 
uses
  IntStack,
  TestFrameWork
  ;
 
type
 _StackType_ = TIntStack;
 {$Include StackTest.imp.pas}
 TIntStackTestViaMixIn = class(_StackTest_)
 protected
 // realized methods
   function GetEtalonData: TEtalonData; override;
 end;//TIntStackTestViaMixIn
 
implementation
 
uses
  SysUtils
  ;
 
{$Include StackTest.imp.pas}
 
function TIntStackTestViaMixIn.GetEtalonData: TEtalonData;
begin
 Result := ArrayToEtalon([10, 20, 3, 5, 6, 19, 21]);
end;
 
initialization
 TestFramework.RegisterTest(TIntStackTestViaMixIn.Suite);
 
end.


--------------------------------------
StringStackTestViaMixIn.pas:

unit StringStackTestViaMixIn;
 
interface
 
uses
  StringStack,
  TestFrameWork
  ;
 
type
 _StackType_ = TStringStack;
 {$Include StackTest.imp.pas}
 TStringStackTestViaMixIn = class(_StackTest_)
 protected
 // realized methods
   function GetEtalonData: TEtalonData; override;
 end;//TStringStackTestViaMixIn
 
implementation
 
uses
  SysUtils
  ;
 
{$Include StackTest.imp.pas}
 
function TStringStackTestViaMixIn.GetEtalonData: TEtalonData;
begin
 Result := ArrayToEtalon(['мама', 'мыла', 'раму', 'весело', 'и', 'споро']);
end;
 
initialization
 TestFramework.RegisterTest(TStringStackTestViaMixIn.Suite);
 
end.

---------------------------------
Получаем тесты:

По-моему - здорово :-)
Попробуйте. Может быть вам понравится.

Понятно, что то же самое можно проделать и с родными Generic'ами.

-- а потом мы может быть поучимся размножать тесты параметризуя их по входным данным. Ну или отдельным постом. Посмотрим...

1 комментарий:

  1. Может быть у кого-нибудь уже есть предложения - как это сделать на примесях? :-) Было бы КРАЙНЕ интересно.

    ОтветитьУдалить