За мотивами GUIRunner

Сьогодні дописав посада про те, як ми вирішили написати свій GUIRunner для FireMonkey. В коментарі до посту в одній з соцмереж Олексій Тимохін звернув мою увагу на інший відомий фреймворк для тестування — DUnitX.
Я намагався знайти альтернативу, використовувати консольний варіант, але Олександр був невблаганний. Коли ж зайшовши в репозиторій я побачив готовий GUIRunner під FireMonkey, зовсім поник.

Однак.

Після першого запуску першим моїм повідомленням Олександру було — " lol. Там «галочок» немає." Так що проблему вирішував не дарма. Після більш уважного вивчення склалося враження, що чоловік, який писав цю форму, теж почасти «позирав» Original GUIRunner.

В цілому я б дуже зрадів такому подарунку з місяць тому, поки шишки FireMonkey ще не набилися. Ну а сьогодні мені було просто цікаво, як вирішував цю ж задачу інший програміст.

Ряд помилок ми допустили практично однакових. У пості я писав про те, як ми пов'язуємо» тести і гілки і в кінці закінчив пропозицією про рефакторинге з використанням TDictionary. Нагадаю, як в оригіналі:

l_Test.GUIObject := aNode.Items[l_Index];
...
l_TreeViewItem.Tag := FTests.Add(aTest);

Розробник DUnitX надійшов приблизно також, правда, він зробили обгортку над TTreeViewItem (в майбутньому додам до себе):

type
TTestNode = class(TTreeViewItem)
strict private
FFullName: String;
FImage: TImage;
public
constructor Create(Owner: TComponent; Text: String; TestFullName: String); reintroduce;
destructor Destroy; override;
property FullName: String read FFullName;
procedure SetResultType(resultType: TTestResultType);
procedure Reload;
end;

І пов'язав кожен тест з гілкою по імені тесту.

function TGUIXTestRunner.GetNode(FullName: String): TTreeViewItem;
var
i: Integer;
begin
Result := nil;
i := 0;
repeat begin
if (TestTree.ItemByGlobalIndex(i) as TTestNode).FullName = FullName then
Result := TestTree.ItemByGlobalIndex(i);
Inc(i);
end
until Assigned(Result) or (i >= TestTree.GlobalCount);
end;

Здивувало мене інше:

FFailedTests: TDictionary<String, ITestResult>;

Вгадайте, навіщо нам ключ String? Правильно, щоб по ньому дістатися до гілки і повідомити про її стан після результату тесту. Як на мене, перемудрили.

Окремої згадки заслуговує клас TTreeNode. Він в собі зберігає «посилання» на тест і картинку, яка буде змінювати стан гілки. Так як клас успадкований від TreeViewItem, такий код живе відмінно:

var
testNode : TTreeViewItem; 
...
testNode := CreateNode(TestTree, test.Name, test.Fixture.FullName + '.' + test.Name);
...

function TGUIXTestRunner.CreateNode(Owner: TComponent; Text: String; TestFullName: String): TTreeViewItem;
begin
Result := TTestNode.Create(Owner, Text, TestFullName);
end;
...
constructor TTestNode.Create(Owner: TComponent; Text, TestFullName: String);
begin
inherited Create(Owner);
Self.Text := Text;
FFullName := TestFullName;
FImage := TImage.Create(Owner);
FImage.Parent := Self;
{$IFDEF DELPHI_XE6_UP}
FImage.Align := TAlignLayout.Right;
{$ELSE}
FImage.Align := TAlignLayout.alRight;
{$ENDIF}
FImage.Bitmap.Create(15, 15);
FImage.Bitmap.Clear(TAlphaColorRec.Gray);
FImage.SendToBack;
end; 

В цілому DUnitX справив на мене гарне враження. Фреймворк здається набагато солідніше свого старшого брата. Інтерфейси і архітектуру хлопці переглянули і, думаю, навіть поліпшили. Весь код дуже акуратний. Коментарів більше в рази. Буду придивлятися і порівнювати.

Посилання

Репозиторій Delphi-Mocks. Необхідний для компілювання фреймворку;
Репозиторій DUnitX.

Джерело: Хабрахабр

0 коментарів

Тільки зареєстровані та авторизовані користувачі можуть залишати коментарі.