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
vBإߴծM

L\

bDxҦU
XR\

ѦҸ

ĥ DUnit i椸 

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

䷧AAb}oέק{XɡAANnPɶ}oXۺ٪յ{AӤO⥦̩նqCYHɧsյ{åBg`Цa楦̡AAN󻴩aͥia{XAӥBbiקP]refactorings^ɧ󦳧ⴤ|}a즳{XAOAε{󦳤FۧڴժOC

DUnit ѤF@OHK´PoǴաCDUnit Ѩذժ覡G

DUnit FP JUnit ج[AӮج[O Kent Beck P Erich Gamma Java {yҳ]pAO DUnit wgvoi¤Oj Delphi MݤuC̦O Juanco Añez ]p Delphi AثehO SourceForge DUnit Group Һ@C

ɮפe

H DUnit MҵoɮӦsb@ݩۤvؿUAHKOd㪺ؿcG

ؿW

DUnit

 

@

framework

ƥsĶnج[Ҳ

 

src

禡wlX

 

doc

UɡAP MPL v\i

 

@

images

ϧɮ





API

Time2Help ͪ API

 

Contrib

LH^mҲ

 

@

XPGen

@ӥiH۰ʲʹծרҡ]test cases^u

 

tests

oӮج[ҨϥΪծר

 

bin

ƥsĶnAiHW檺 GUI յ{

 

examples

 

@ @ cmdline ܽdpbROCҤUϥ DUnit

 

@

collection

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

 

@

registration

ϥδծרҵUtΡ]registration system^]ĶGܽdXصUծרҪk^

 

@

structure

´յ{X覡

 

@

@

diffunit

ծרҩbWߪ椸̭

 

@

@

sameunit

ծרҩMQժ{XbP@ӳ椸̭





registry

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

  @ embeddable ܽdpN GUITestRunner OJܨL

 

@

(...)

 

@

@

TListTest

Delphi Classes.TList ϥΪծר

ؿ src ]tUCɮ

ɮצW

TestFramework.pas

ج[

TestExtensions.pas

iΨXRծרҪ Decorator O

GUITesting.pas

ΨӴըϥΪ̤]Pܲ^O

TextTestRunner.pas

bDxҦUժ禡

GUITestRunner.pas

ج[ϧΤƨϥΪ̤

GUITestRunner.dfm

GUITestRunner Form

framework ؿ]tHWU椸sĶLAHΥΨӳs .BPL .DCP ɮס] .BPL ɮצsb bin ؿ̡^]Ķ1^C

_B

b}lϥ DUnit eADelphi 椸jM|̥]t DUnit lXνsĶ᪺ɮ׸| CAiHb Delphi IDE I Tools | Environment Options | LibraryAM DUnit |[즳|M̡G

Delphi's environment options dialog

t@ذkAON DUnit |[w]M׿ﶵΪ̯SwM׿ﶵ̡Ab IDE I Project | OptionsG

Delphi's project options dialog

AĤ@ӴձM

إߤ@ӷsε{AM Delphi A۰ʲͪ Unit1.pas åBnxsCxsoӷsMס]bAQnժε{ۦPؿU 'real life' ؿ^åBRW Project1Test.dprC

I File | New | Unit Hإߤ@ӷs]S form ^椸Aѩڭ̷|ծרgboɮ׸̭AҥHxsɭԴN  Project1TestCases ɮצW١Aۦb interface uses ly̥[J TestFrameworkC

ŧi@ TTestCaseFirst OAO~Ӧ TTestCaseAM@@ӦpUҥܪ TestFirst k]MaAoӤpdҥuOFAQ_B^A`N̫᪺ initialization ϬqATTestCaseFirst ONObo̧UC

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.

ժGOmҩIs Check k̭Ao̧ګܵLaQnT{ 1 + 1 O_ 2CTestFramework.RegisterTest {Ƿ|ǤJծרҪU즹ج[Utθ̡C

boӱMץHeAID檺 Project | View Source H}ұMתlXA TestFrameWork H GUITestRunner [ uses ly̡AMᲾw] Application {XAåHU{XNG

program Project1Test;

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

{$R *.RES}

begin
 Application.Initialize;
 GUITestRunner.RunRegisteredTests;
end.

{bյ۰{ApG@`AAӷ|ݨ DUnit GUITestRunner A̭@Ӿ𪬤ܥiΪա]ثeu TestFirst^AI@U Run sYiաCeW֨iHAHh覡ܱժءA٦B~sHKնةξӤ䪺AC

Yn[JhաAu²ab TTestCaseFirst ̥[JsդkATTestCase.Suite Ok|zL RTTI]RunTime Type InformationAɴAT^۰ʦaMåBIs̡AoǴդkŦXӱG

`N DUnit |ҧ쪺CӤkU۫إߤ@O]instance^AҥHդki@ɹ骺ơC

{bnA[JӴդkGTestSecond P TestThirdAŧipUG

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;

pGAsoӵ{AAN|ݨ TestSecond եѤF]䦳@Ӥpء^A TestThird |X@Ӳ`]䪺جO⪺^AqLժط|O⪺AӨS檺իhOǦ⪺CѪղM|QCbU誺OWAAhI復̴NiHbOWݨ쥦̪ԲӸơC

pGAb IDE ̭{AA|o{C{oͿ~ɴN|ȰAA DUnit iծɡAo˪欰iणOAQnAAiHӤUBJN IDE o\GI Tools | Debugger OptionsAM Language Exceptions Stop on Delphi Exceptions بC

Setup P TearDown

ڭ̳q`|b@մդei@몺dzƤu@AæbƫiMzCpAbդ@OɭԡAA]\|Qnإ߸OAM復I@ˬdA̫ANApGնثܦhܡAANKFbC@Ӵդk̭gƪ{XCDUnit 惡XѨM׬OAbC@ӴդkQ椧eMOhIs TTestCase k Setup P TearDownAH׷ժܨӻAѳoӤkӴѴիenBzN٬@ fixture]Ķ 2^C

HUdXRF TTestCaseFirst üW[XӴ Delphi XO TStringList kG

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^

Abդ@ӯuΪ]non-trivial^ε{ɡAA|Qnإߤ@ӥHW TTestCase lOANoO[Wh`IAAuݦb initialization ly̭U̴NFAgkWdҤ@ˡCɭԡAAiQnMawqծרҤcYA DUnit ѤFإծM\AiHAbծרҤ]tLծרҩδծM]ϥ Composite ˦^C

pPb TTestCaseFirst ծרҤܪANB⪺դkɡASetUp M TearDown kMQIsSơC䤤ӳBzrCkA̦nN̤WߪծMAkO TTestCaseFirst OAOO TTestArithmetic P TTestStringListG

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աAA]osoǤk@~^

M inistailization {X令oˡG

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

vBإߴծM

TestFrameworkTTestSuite O@FծMAҥHAiHΧ㪺覡إߴնhG

U UnitTests 禡|إߤ@ӴծMAåBb䤤[JӴOG

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@ؼgkAW@Τ]OۦPG

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

WdҬObIs TTestSuite غcɡAn[Jդ@ֳzL}CǻLhC

ϥΤWz@ؤ覡إߪծMAU覡AeUӧOծרҪ覡OۦPG

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

յ{ɡAAN|b GUITestRunner Wݨs𪬶hC

@

L\

bDxҦU

ɭԡAڭ̷|QnbDxҦUծMApAQnΤ@ Makefile 媺աAoɭԥDxҦNܦΡCpnbDxҦUաAeb DPR ɮ׸̭ uses ly GUITestRunner Nn令 TextTestRunnerAåB[JsĶ {$APPTYPE CONSOLE} Ϊ̦b IDE I Project | Options | Linker | Generate console application ﶵC

HUd Project1TestConsole.dpr M׭lXG

{$APPTYPE CONSOLE}

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

{$R *.RES}

begin
  TextTestRunner.RunRegisteredTests;
end.

{檺XG|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..' rA䤤C@ӥyI].^N@L~աA'F' ܴեѡ]failed^A 'E' ܵoͲ`]exception^C

pGAƱեѮɡA TextTestRunner åBǦ^@ӫDsXAAiHǤJ@rxbHaltOnFailures ѼƭȡAoˡG

TextTestRunner.RunRegisteredTests(rxbHaltOnFailures);

Aϥ Makefile ӰծM󪺮ɭԡAoǦ^ǪX|ܦγBC

XR\

The TextExtensions 椸OOΨXR DUnit ج[\AjOϥΤFu|Hv]GoF, Gang of Four^ "Design Patterns" Ѥҩwq decorator ˦C

TRepeatedTest

TRepeatedTest OAƸ˹ճ\hAҦpAư TestFirst ծרҤ TTestArithmetic 10 AA{iHogG

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 غcG

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

o̧ڧnư檺դkWٶǻغcAMoӦW٤@wgA_hHɥuoOH檺GC

pGAQnƴ TTestArithmetic kAAiH⥦̩b@ӮM̡G

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

TTestSetup

TTestSetup OiHA@ӴծרOiߤ@@lƳ]w]Setup P TearDown kOCդkɴN|QIs^CҦpApGAbg@մեHҬYǦsƮw{XAAi|q TTestSetup lͤ@OAåBQΥӶ}ҩMƮwC

@

ѦҸ

SourceForge DUnit ]https://sourceforge.net/projects/dunit/^A̷slXAl׾¡Aݵ...C

Delphi ׷դu ] http://www.suigeneris.org/juanca/writings/1999-11-29.html^AJuancarlo Añez bog峹̤ФFL]p DUnit OA̪줽G Borland }oHsC

JUnit Test Infected: Programmers Love Writing Tests (http://www.junit.org/junit/doc/testinfected/testing.htm)AoO@g JUnit n峹A DUnit NOHج[¦ӵoiXӪC

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

~o~

Ķ

  1. ɮץؿbs̭wgsbFAҦpGframeworkAGHxX̷sؿcǡC
  2. Fixture O XP NyCb@ Test Case ̭AtdlƤβMzʧ@A@WNO SetUp P TearDown oӵkCCծɡA|ƥIsҦ fixture Setup kAåBbյeIs TearDownAڷQ]N]oǬOTwn檺ʧ@AҥHW fixtureAYnĶA]\iHuTw˸mvΡuTwvC fixture 嫬ΪkOb Setup k̭tm귽AåBb TearDown ̭귽ApGAbզsƮw{AåBƱժL{|ܸƮweA]iHb TearDown ̭NҦM^AΪ̼gv{XC