DUnit logoDUnit
Delphi ���׷����դu��

by Will Watts
edited by Juanco Añez
Copyright © 1999 Will Watts. All rights reserved.
Later versions are © 2000-2001 The DUnit Group. All rights reserved.
This text may be distributed freely as long as it's reproduced in its entirety.
US flag
There's an English version of this document here

½Ķ�G������

���e

�ĥ� DUnit �i��椸����

�ɮפ��e
�_�B
�A���Ĥ@�Ӵ��ձM��
SetUp �P TearDown
���ծM��
�v�B�إߴ��ծM��

��L�\��

�b�D���x�Ҧ��U�������
�X�R�\��

�ѦҸ��

�ĥ� DUnit �i��椸���� 

DUnit �O�@�����O�ج[�A�ت��O�n�䴩 XP ���n����դ�k�C���䴩 Delphi 4 �H�᪺�����C

�䷧�����A���A�b�}�o�έק�{���X�ɡA�A�N�n�P�ɶ}�o�X�ۺ٪����յ{���A�Ӥ��O�⥦�̩������ն��q�C�Y���H�ɧ�s���յ{���åB�g�`���Цa���楦�̡A�A�N����󻴩��a���ͥi�a���{���X�A�ӥB�b�i��ק�P����]refactorings�^�ɧ󦳧ⴤ���|�}�a�즳���{���X�A��O�A���ε{�����󦳤F�ۧڴ��ժ���O�C

DUnit ���ѤF�@�����O�H�K��´�P����o�Ǵ��աCDUnit ���Ѩ�ذ�����ժ��覡�G

DUnit ���F�P���� JUnit �ج[�A�Ӯج[�O�� Kent Beck �P Erich Gamma �� Java �{���y���ҳ]�p���A���O DUnit �w�g�v���o�i���¤O��j�� Delphi �M�ݤu��C�̦��O�� Juanco Añez �]�p�� Delphi �������A�ثe�h�O�� SourceForge �� DUnit Group �Һ��@�C

�ɮפ��e

�H�� DUnit �M��ҵo�����ɮ����Ӧs��b�@���ݩ�ۤv���ؿ��U�A�H�K�O�d���㪺�ؿ����c�G

�ؿ��W�� ����

DUnit

 

�@

framework

�ƥ��sĶ�n���ج[�Ҳ�

 

src

�禡�w��l�X

 

doc

���U�����ɡA�����P MPL ���v�\�i

 

�@

images

�������ϧ��ɮ�





API

Time2Help ���ͪ� API ���

 

Contrib

��L�H�^�m���Ҳ�

 

�@

XPGen

�@�ӥi�H�۰ʲ��ʹ��ծרҡ]test cases�^���u��

 

tests

���o�Ӯج[�����ҨϥΪ����ծר�

 

bin

�ƥ��sĶ�n�A�i�H��W���檺 GUI ���յ{��

 

examples

 

�@ �@ cmdline �ܽd�p��b�R�O�C���ҤU�ϥ� DUnit

 

�@

collection

�@������ Java �����X�]collections�^��@�H�Υ��� DUnit ���ծר�

 

�@

registration

�ϥδ��ծרҵ��U�t�Ρ]registration system�^�]Ķ���G�ܽd�X�ص��U���ծרҪ���k�^

 

�@

structure

��´���յ{���X���覡

 

�@

�@

diffunit

����ծרҩ�b�W�ߪ��椸�̭�

 

�@

�@

sameunit

����ծרҩM�Q���ժ��{���X��b�P�@�ӳ椸�̭�





registry

�@�B�B�ЧA�إߤ@�Ӧs�� Registry ���u��Ψ���ծר�

  �@ embeddable �ܽd�p��N GUITestRunner �O�J�ܨ�L������

 

�@

(...)

 

�@

�@

TListTest

�� Delphi �� Classes.TList ����ϥΪ����ծר�

�ؿ� src �]�t�U�C�ɮ�

�ɮצW�� ����

TestFramework.pas

�ج[����

TestExtensions.pas

�i�Ψ��X�R���ծרҪ� Decorator ���O

GUITesting.pas

�ΨӴ��ըϥΪ̤����]�����P��ܲ��^�����O

TextTestRunner.pas

�b�D���x�Ҧ��U������ժ��禡

GUITestRunner.pas

���ج[���ϧΤƨϥΪ̤���

GUITestRunner.dfm

GUITestRunner Form

framework �ؿ����]�t�H�W�U�椸�sĶ�L�������A�H�ΥΨӳs�� .BPL �� .DCP �ɮס]������ .BPL �ɮצs�b bin �ؿ��̡^�]Ķ��1�^�C

�_�B

�b�}�l�ϥ� DUnit ���e�ADelphi ���椸�j�M���|�̥����]�t DUnit ����l�X�νsĶ�᪺�ɮ׸��| �C�A�i�H�b Delphi IDE ���I�� Tools | Environment Options | Library�A�M��� DUnit ���|�[��즳�����|�M��̡G

Delphi's environment options dialog

�t�@�ذ��k�A�O�N DUnit ���|�[��w�]���M�׿ﶵ�Ϊ̯S�w���M�׿ﶵ�̡A�b IDE ���I�� Project | Options�G

Delphi's project options dialog

�A���Ĥ@�Ӵ��ձM��

�إߤ@�ӷs�����ε{���A�M������ Delphi ���A�۰ʲ��ͪ� Unit1.pas �åB���n�x�s�C�x�s�o�ӷs���M�ס]�b�A�Q�n���ժ����ε{�����ۦP�ؿ��U�� 'real life' �ؿ��^�åB�R�W�� Project1Test.dpr�C

�I�� File | New | Unit �H�إߤ@�ӷs���]�S�� form ���^�椸�A�ѩ�ڭ̷|�����ծר��g�b�o���ɮ׸̭��A�ҥH�x�s���ɭԴN��  Project1TestCases �������ɮצW�١A���ۦb interface �� uses �l�y�̥[�J TestFramework�C

�ŧi�@�� TTestCaseFirst ���O�A�����O�~�Ӧ� TTestCase�A�M���@�@�Ӧp�U�ҥܪ� TestFirst ��k�]��M�a�A�o�Ӥp�d�ҥu�O���F���A���Q�_�B�^�A�`�N�̫᪺ initialization �Ϭq�ATTestCaseFirst ���O�N�O�b�o�̧������U���C

unit Project1TestCases;

interface

uses
  TestFrameWork;

type
  TTestCaseFirst = class(TTestCase)
  published
    procedure TestFirst;
  end;

implementation

procedure TTestCaseFirst.TestFirst;
begin
  Check(1 + 1 = 2, 'Catastrophic arithmetic failure!');
end;

initialization
  TestFramework.RegisterTest(TTestCaseFirst.Suite);
end.

���ժ����G�O�m��ҩI�s�� Check ��k�̭��A�o�̧ګܵL��a�Q�n�T�{ 1 + 1 �O�_���� 2�CTestFramework.RegisterTest �{�Ƿ|��ǤJ�����ծרҪ�����U�즹�ج[�����U�t�θ̡C

�b����o�ӱM�ץH�e�A�I��D��檺 Project | View Source �H�}�ұM�ת���l�X�A�� TestFrameWork �H�� GUITestRunner �[�� uses �l�y�̡A�M�Ჾ���w�]�� Application �{���X�A�åH�U�����{���X���N�G

program Project1Test;

uses
 Forms,
 TestFrameWork,
 GUITestRunner,
 Project1TestCases in 'Project1TestCases.pas';

{$R *.RES}

begin
 Application.Initialize;
 GUITestRunner.RunRegisteredTests;
end.

�{�b�յ۰���{���A�p�G�@�����`�A�A���ӷ|�ݨ� DUnit �� GUITestRunner �����A�̭����@�Ӿ𪬤�����ܥi�Ϊ����ա]�ثe�u�� TestFirst�^�A�I�@�U Run ���s�Y�i������աC�e���W���֨�����i�H���A�H���h���覡��ܱ����ժ����ءA�٦��B�~�����s�H�K�������ն��ةξ�Ӥ��䪺������A�C

�Y�n�[�J��h�����աA�u��²��a�b TTestCaseFirst �̥[�J�s�����դ�k�ATTestCase.Suite ���O��k�|�z�L RTTI�]RunTime Type Information�A����ɴ����A��T�^�۰ʦa�M��åB�I�s���̡A�o�Ǵ��դ�k�����ŦX��ӱ���G

�`�N DUnit �|�����ҧ�쪺�C�Ӥ�k�U�۫إߤ@�����O������]instance�^�A�ҥH���դ�k�������i�@�ɹ��骺��ơC

�{�b�n�A�[�J��Ӵ��դ�k�GTestSecond �P TestThird�A��ŧi�p�U�G

TTestCaseFirst = class(TTestCase)
published
  procedure TestFirst;
  procedure TestSecond;
  procedure TestThird;
 end;

...

procedure TTestCaseFirst.TestSecond;
begin
  Check(1 + 1 = 3, 'Deliberate failure');
end;
procedure TTestCaseFirst.TestThird;
var
  i: Integer;
begin
  i := 0;
  Check(1 div i = i, 'Deliberate exception');
end;

�p�G�A���s����o�ӵ{���A�A�N�|�ݨ� TestSecond ���ե��ѤF�]���䦳�@�Ӥp���������ء^�A�� TestThird �|��X�@�Ӳ��`�]���䪺��جO���⪺�^�A�q�L���ժ���ط|�O��⪺�A�ӨS�����檺���իh�O�Ǧ⪺�C���Ѫ����ղM��|�Q�C�b�U�誺���O�W�A���A�h�I�復�̴N�i�H�b���������O�W�ݨ쥦�̪��ԲӸ�ơC

�p�G�A�b IDE �̭�����{���A�A�|�o�{�C���{���o�Ϳ��~�ɴN�|�Ȱ��A���A�� DUnit �i����ծɡA�o�˪��欰�i�ण�O�A�Q�n���A�A�i�H�ӤU�����B�J�N IDE ���o���\�������G�I�� Tools | Debugger Options�A�M��� Language Exceptions ������ Stop on Delphi Exceptions ���ب����C

Setup �P TearDown

�ڭ̳q�`�|�b����@�մ��դ��e�i��@�몺�dzƤu�@�A�æb�ƫ�i��M�z�C��p���A�b���դ@�����O���ɭԡA�A�]�\�|�Q�n�إ߸����O������A�M��復�I��@���ˬd�A�̫�A�N������A�p�G���ն��ثܦh���ܡA�A�N�K���F�b�C�@�Ӵ��դ�k�̭����g���ƪ��{���X�CDUnit �惡���X���ѨM��׬O�A�b�C�@�Ӵ��դ�k�Q���椧�e�M������O�h�I�s TTestCase ��������k Setup �P TearDown�A�H�׷����ժ���ܨӻ��A�ѳo��Ӥ�k�Ӵ��Ѵ��իe�����n�B�z�N�٬��@�� fixture�]Ķ�� 2�^�C

�H�U�d���X�R�F TTestCaseFirst �üW�[�X�Ӵ��� Delphi ���X���O TStringList ����k�G

interface

uses
 TestFrameWork,
 Classes;  // needed for TStringList

type
 TTestCaseFirst = class(TTestCase)
 private
   Fsl: TStringList;
 protected
   procedure SetUp; override;
   procedure TearDown; override;
 published
   procedure TestFirst;
   procedure TestSecond;
   procedure TestThird;
   procedure TestPopulateStringList;
   procedure TestSortStringList;
 end;

...

procedure TTestCaseFirst.SetUp;
begin
 Fsl := TStringList.Create;
end;

procedure TTestCaseFirst.TearDown;
begin
  Fsl.Free;
end;

procedure TTestCaseFirst.TestPopulateStringList;
var
 i: Integer;
begin
 Check(Fsl.Count = 0);
 for i := 1 to 50 do    // Iterate
   Fsl.Add('i');
 Check(Fsl.Count = 50);
end;

procedure TTestCaseFirst.TestSortStringList;
begin
  Check(Fsl.Sorted = False);
  Check(Fsl.Count = 0);
  Fsl.Add('You');
  Fsl.Add('Love');
  Fsl.Add('I');
  Fsl.Sorted := True;
  Check(Fsl[2] = 'You');
  Check(Fsl[1] = 'Love');
  Check(Fsl[0] = 'I');
end;

���ծM���]Test suites�^

���A�b���դ@�ӯu�����Ϊ��]non-trivial�^���ε{���ɡA�A�|�Q�n�إߤ@�ӥH�W�� TTestCase �l�����O�A���N�o�����O�[��W�h�`�I�A�A�u�ݦb initialization �l�y�̭����U���̴N��F�A�g�k��W�����d�Ҥ@�ˡC���ɭԡA�A�i��Q�n��M���a�w�q���ծרҤ��������c���Y�A���� DUnit ���ѤF�إ����ծM�����\��A���i�H���A�b���ծרҤ��]�t��L�����ծרҩδ��ծM��]�ϥ� Composite �˦��^�C

�p�P�b TTestCaseFirst ���ծרҤ�����ܪ��A����N�B�⪺���դ�k����ɡASetUp �M TearDown ��k���M���Q�I�s�������S������ơC�䤤����ӳB�z�r���C����k�A�̦n��N���̤������W�ߪ����ծM��A���k�O���� TTestCaseFirst �������O�A���O�O TTestArithmetic �P TTestStringList�G

type
  TTestArithmetic = class(TTestCase)
  published
    procedure TestFirst;
    procedure TestSecond;
    procedure TestThird;
  end;

 TTestStringlist = class(TTestCase)
 private
   Fsl: TStringList;
 protected
   procedure SetUp; override;
   procedure TearDown; override;
 published
   procedure TestPopulateStringList;
   procedure TestSortStringList;
 end;

�]���M�աA�A�]�o��s�o�Ǥ�k����@�~��^

�M��� inistailization ���{���X�令�o�ˡG

RegisterTest('Simple suite', TTestArithmetic.Suite);
RegisterTest('Simple suite', TTestStringList.Suite);

�v�B�إߴ��ծM��

TestFramework �椸�� TTestSuite ���O��@�F���ծM��A�ҥH�A�i�H�Χ���㪺�覡�إߴ��ն��h�G

�U���� UnitTests �禡�|�إߤ@�Ӵ��ծM��A�åB�b�䤤�[�J��Ӵ������O�G

function UnitTests: ITestSuite;
var
  ATestSuite: TTestSuite;
begin
  ATestSuite := TTestSuite.Create('Some trivial tests');
  ATestSuite.AddTests(TTestArithmetic.Suite);
  ATestSuite.AddTests(TTestStringlist.Suite);
  Result := ATestSuite;
end;

�٦��t�@�ؼg�k�A��W�����@�Τ]�O�����ۦP���G

function UnitTests: ITestSuite;
begin
  Result := TTestSuite.Create('Some trivial tests',
                         [                 
                          TTestArithmetic.Suite,
                          TTestStringlist.Suite
                          ]);
end;

�W�����d�ҬO�b�I�s TTestSuite ���غc���ɡA��n�[�J�����դ@�ֳz�L�}�C�ǻ��L�h�C

�ϥΤW�z���@�ؤ覡�إߪ����ծM��A����U�覡��A���e���U�ӧO���ծרҪ��覡�O�ۦP���G

initialization
  RegisterTest('Simple Test', UnitTests);
end.

�����յ{������ɡA�A�N�|�b GUITestRunner �����W�ݨ�s���𪬶��h�C

�@

��L�\��

�b�D���x�Ҧ��U�������

���ɭԡA�ڭ̷|�Q�n�b�D���x�Ҧ��U������ծM��A��p�����A�Q�n�Τ@�� Makefile �����媺���աA�o�ɭԥD���x�Ҧ��N�ܦ��ΡC�p�n�b�D���x�Ҧ��U������աA���e�b DPR �ɮ׸̭��� uses �l�y���� GUITestRunner �N�n�令 TextTestRunner�A�åB�[�J����sĶ {$APPTYPE CONSOLE} �Ϊ̦b IDE ���I�� Project | Options | Linker | Generate console application �ﶵ�C

�H�U�d�� Project1TestConsole.dpr ���M�׭�l�X�G

{$APPTYPE CONSOLE}

program Project1TestConsole;
uses
 TestFrameWork,
 TextTestRunner,
 Project1TestCases in 'Project1TestCases.pas';

{$R *.RES}

begin
  TextTestRunner.RunRegisteredTests;
end.

�{�����檺��X���G�|���o�ˡG

--
DUnit: Testing.
..F.E..
Time: 0.20
FAILURES!!!
Test Results:
Run: 5
Failures: 1
Errors: 1

There was 1 error:
1) TestThird: EDivByZero: Division by zero

There was 1 failure:
1) TestSecond

�`�N�ĤT�檺 '..F.E..' �r��A�䤤�C�@�ӥy�I�].�^�N���@������L�~�����աA'F' ���ܴ��ե��ѡ]failed�^�A�� 'E' ���ܵo�Ͳ��`�]exception�^�C

�p�G�A�Ʊ�����ե��ѮɡA�� TextTestRunner �������åB�Ǧ^�@�ӫD�s�������X�A�A�i�H�ǤJ�@��rxbHaltOnFailures �ѼƭȡA���o�ˡG

TextTestRunner.RunRegisteredTests(rxbHaltOnFailures);

���A�ϥ� Makefile �Ӱ�����ծM�󪺮ɭԡA�o�Ǧ^�Ǫ������X�|�ܦ��γB�C

�X�R�\��

The TextExtensions �椸�������O�O�Ψ��X�R DUnit �ج[���\��A�j���������O�ϥΤF�u�|�H���v�]GoF, Gang of Four�^�� "Design Patterns" �Ѥ��ҩw�q�� decorator �˦��C

TRepeatedTest

TRepeatedTest ���O����A���Ƹ˹������ճ\�h���A�Ҧp�A���ư��� TestFirst ���ծרҤ��� TTestArithmetic 10 ���A�A���{���i�H�o��g�G

uses
 TestFrameWork,
 TestExtensions, // needed for TRepeatedTest
 Classes;        // needed for TStringList

...

function UnitTests: ITest;
var
  ATestArithmetic : TTestArithmetic;
begin
  ATestArithmetic := TTestArithmetic.Create('TestFirst');
  Result := TRepeatedTest.Create(ATestArithmetic, 10);
end;

�Ъ`�N TTestArithmetic ���غc���G

ATestArithmetic := TTestArithmetic.Create('TestFirst');

�o�̧ڧ�n���ư��檺���դ�k���W�ٶǻ����غc���A���M�o�ӦW�٤@�w����g���A�_�h�H�����ɥu��o��O�H���檺���G�C

�p�G�A�Q�n���ƴ��� TTestArithmetic ��������k�A�A�i�H�⥦�̩�b�@�ӮM��̡G

function UnitTests: ITest;
begin
  Result := TRepeatedTest.Create(ATestArithmetic.Suite, 10);
end;

TTestSetup

TTestSetup ���O�i�H���A���@�Ӵ��ծר����O�i��ߤ@�@������l�Ƴ]�w�]Setup �P TearDown ��k�O�C��������դ�k�ɴN�|�Q�I�s�^�C�Ҧp�A�p�G�A���b���g�@�մ��եH���ҬY�Ǧs����Ʈw���{���X�A�A�i��|�q TTestSetup �l�ͤ@�����O�A�åB�Q�Υ��Ӷ}�ҩM������Ʈw�C

�@

�ѦҸ��

��� SourceForge �� DUnit �����]https://sourceforge.net/projects/dunit/�^�A���̷s����l�X�A�l���׾¡A�ݵ���...���C

Delphi ���׷����դu�� �] http://www.suigeneris.org/juanca/writings/1999-11-29.html�^�AJuancarlo Añez �b�o�g�峹�̤��ФF�L�]�p�� DUnit ���O�A����̪줽�G�� Borland �}�o�H�����s�����C

JUnit Test Infected: Programmers Love Writing Tests (http://www.junit.org/junit/doc/testinfected/testing.htm)�A�o�O�@�g���� JUnit ���n�峹�A DUnit �N�O�H���ج[����¦�ӵo�i�X�Ӫ��C

Simple Smalltalk Testing: With Patterns�]http://www.xprogramming.com/testfram.htm�^�AKent Beck �̦������A����A�X���x Smalltalk ���H�\Ū�C

~o~

��

  1. �����ɮץؿ��b�s�����̭��w�g���s�b�F�A�Ҧp�Gframework�A�G���H�x�����X���̷s�����ؿ����c���ǡC
  2. Fixture �O XP �N�y�C�b�@�� Test Case �̭��A�t�d��l�ƤβM�z���ʧ@�A�������@�W�N�O SetUp �P TearDown �o��ӵ�����k�C�C��������ծɡA�|�ƥ��I�s�Ҧ��� fixture �� Setup ��k�A�åB�b���յ����e�I�s TearDown�A�ڷQ�]�N�]���o�ǬO�T�w�n���檺�ʧ@�A�ҥH����W�� fixture�A�Y�nĶ������A�]�\�i�H�����u�T�w�˸m�v�Ρu�T�w����v�C fixture ���嫬�Ϊk�O�b Setup ��k�̭��t�m�귽�A�åB�b TearDown �̭�����귽�A�p�G�A���b���զs����Ʈw���{���A�åB�Ʊ���ժ��L�{���|���ܸ�Ʈw�����e�A�]�i�H�b TearDown �̭��N�Ҧ�������M�^�A�Ϊ̼��g������v���{���X�C