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

Немного об использовании DUnit

Тут мы говорили о шаблонах и примесях:
http://18delphi.blogspot.com/2013/03/blog-post_29.html

Теперь я расскажу о простейшем использовании фреймворка DUnit.

ЗАЧЕМ нужны тесты я немного написал вот тут - http://18delphi.blogspot.com/2013/03/blog-post.html

Думаю, что со временем приведу примеры "из жизни".

Пока рассмотрим лишь технику на абстрактном примере.

Буду описаться на классы полученные в предыдущем примере.

Как всегда начнём с диаграммы:
Теперь, что получаем на Delphi:

SandBox.dpr:

program SandBoxTest;
 
uses
  TestFrameWork
  GUITestRunner,
  IntStack,
  IntStackTest,
  StringStack,
  StringStackTest;
 
 
begin
 GUITestRunner.RunRegisteredTests;
end.

----------------------------------
IntStackTest.pas:

unit IntStackTest;
 
interface
 
uses
  TestFrameWork
 
  ;
 
type
 TIntStackTest = {final} class(TTestCase)
 published
 // published methods
   procedure DoIt;
 end;//TIntStackTest
 
implementation
 
uses
  IntStack,
  SysUtils
  ;
 
// start class TIntStackTest
 
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
 
initialization
 TestFramework.RegisterTest(TIntStackTest.Suite);
 
end.


----------------------------------
StringStackTest.pas:

unit StringStackTest;
 
interface
 
uses
  TestFrameWork
  ;
 
type
 TStringStackTest = class(TTestCase)
 published
 // published methods
   procedure DoIt;
 end;//TStringStackTest
 
implementation
 
uses
  StringStack,
  SysUtils
  ;
 
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
 
 
initialization
 TestFramework.RegisterTest(TStringStackTest.Suite);
 
end.


-- получили тесты работоспособности наших классов :-)

По-моему - здорово. Особенно если тесты КАЖДЫЙ день гонять :-) Если гоняем каждый день, то оперативно видим - чего сломали.

Не говорите только - "это ОЧЕНЬ просто" :-) Дьявол - он всегда в деталях.

Более сложные примеры "из жизни" - я постараюсь позже привести.

Главное, что для многих проектных классов - тесты это очень простой путь отладки - чтобы не поднимать полномасштабное приложение, которое компилируется 10 мин. Не разворачивать сервер БД и т.п. Придумали "данные из головы", написали тест - и всё - можно отлаживать. Данный конкретный класс.

Понятно, что ИМЕННО НА ЭТИХ данных. Но ничто не мешает - постепенно пополнять базу тестов и базу "данных из головы".

Позже я напишу - как я пользуюсь mock'ами. На основе файлов эталонов.

Что это такое пока читайте тут:

Если вы скажете - "покажите тестирование форм и GUI", то я отвечу вам - "покажу. Непременно. У меня - богатый опыт".

А пока - сосредоточьтесь на том факте, что формы как раз - "не страшно трогать". Ибо они "торчат наружу юзеру". А вот базовые классы - страшно. Особенно если их использует несколько десятков форм. Разных. Особенно если они написаны "тем парнем который пять лет назад уволился". Особенно если нет тестов. И чем более "базовый" класс. И чем больше в нём найдено ошибок, тем больше для него будет написано тестов. Со временем. Если вы будете прислушиваться к моим рекомендациям. И тем более стабильным - он станет.

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

Следующая серия тут:

Комментариев нет:

Отправить комментарий