DUnit
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.

There's an English version of this document here
½Ķ�G������
�ɮפ��e
�_�B
�A���Ĥ@�Ӵ��ձM��
SetUp �P TearDown
���ծM��
�v�B�إߴ��ծM��
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
�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 |
�������ϧ��ɮ� |
|
|
Time2Help ���ͪ� API ��� |
||||
|
|
Contrib |
��L�H�^�m���Ҳ� |
||
|
|
�@ |
�@�ӥ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�^ |
|
|
|
�@ |
��´���յ{���X���覡 |
||
|
|
�@ |
�@ |
diffunit |
����ծרҩ�b�W�ߪ��椸�̭� |
|
|
�@ |
�@ |
sameunit |
����ծרҩM�Q���ժ��{���X��b�P�@�ӳ椸�̭� |
|
�@�B�B�ЧA�إߤ@�Ӧs�� Registry ���u��Ψ���ծר� |
||||
| �@ | embeddable | �ܽd�p��N GUITestRunner �O�J�ܨ�L������ | ||
|
|
�@ |
(...) |
|
|
|
�@ |
�@ |
TListTest |
�� Delphi �� Classes.TList ����ϥΪ����ծר� |
|
�ؿ� src �]�t�U�C�ɮ�
| �ɮצW�� | ���� |
|---|---|
|
�ج[���� |
|
|
�i�Ψ��X�R���ծרҪ� Decorator ���O |
|
|
�ΨӴ��ըϥΪ̤����]�����P��ܲ��^�����O |
|
|
�b�D���x�Ҧ��U������ժ��禡 |
|
|
���ج[���ϧΤƨϥΪ̤��� |
|
|
GUITestRunner Form |
framework �ؿ����]�t�H�W�U�椸�sĶ�L�������A�H�ΥΨӳs�� .BPL �� .DCP �ɮס]������ .BPL �ɮצs�b bin �ؿ��̡^�]Ķ��1�^�C
�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
�t�@�ذ��k�A�O�N DUnit ���|�[��w�]���M�ﶵ�Ϊ̯S�w���M�ﶵ�̡A�b IDE ���I�� Project | Options�G
�إߤ@�ӷ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
�ڭ̳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;
���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);
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
�@
���ɭԡ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
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 ���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 ���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~