Тут мы говорили о шаблонах и примесях:
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", то я отвечу вам - "покажу. Непременно. У меня - богатый опыт".
А пока - сосредоточьтесь на том факте, что формы как раз - "не страшно трогать". Ибо они "торчат наружу юзеру". А вот базовые классы - страшно. Особенно если их использует несколько десятков форм. Разных. Особенно если они написаны "тем парнем который пять лет назад уволился". Особенно если нет тестов. И чем более "базовый" класс. И чем больше в нём найдено ошибок, тем больше для него будет написано тестов. Со временем. Если вы будете прислушиваться к моим рекомендациям. И тем более стабильным - он станет.
Попробуйте - может быть вам понравится.
Следующая серия тут: