fpcunit.pp 44 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658
  1. {
  2. This file is part of the Free Component Library (FCL)
  3. Copyright (c) 2004 by Dean Zobec, Michael Van Canneyt
  4. Port to Free Pascal of the JUnit framework.
  5. See the file COPYING.FPC, included in this distribution,
  6. for details about the copyright.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  10. **********************************************************************}
  11. unit fpcunit;
  12. {$mode objfpc}
  13. {$h+}
  14. interface
  15. { Uncomment this define to remove the DUnit compatibility interface. }
  16. {$DEFINE DUnit}
  17. uses
  18. SysUtils
  19. ,Classes
  20. ;
  21. { This lets us use a single include file for both the Interface and
  22. Implementation sections. }
  23. {$define read_interface}
  24. {$undef read_implementation}
  25. type
  26. EAssertionFailedError = class(Exception)
  27. constructor Create; overload;
  28. constructor Create(const msg :string); overload;
  29. end;
  30. EIgnoredTest = class(EAssertionFailedError);
  31. TTestStep = (stSetUp, stRunTest, stTearDown, stNothing);
  32. TRunMethod = procedure of object;
  33. TTestResult = class;
  34. TTestSuite = class;
  35. {$M+}
  36. { TTest }
  37. TTest = class(TObject)
  38. private
  39. protected
  40. FLastStep: TTestStep;
  41. function GetTestName: string; virtual;
  42. function GetTestSuiteName: string; virtual;
  43. function GetEnableIgnores: boolean; virtual;
  44. procedure SetTestSuiteName(const aName: string); virtual; abstract;
  45. procedure SetEnableIgnores(Value: boolean); virtual; abstract;
  46. public
  47. function CountTestCases: integer; virtual;
  48. Function GetChildTestCount : Integer; virtual;
  49. Function GetChildTest(AIndex : Integer) : TTest; virtual;
  50. function FindChildTest(const AName: String): TTest;
  51. Function FindTest(Const AName : String) : TTest;
  52. procedure Run(AResult: TTestResult); virtual;
  53. procedure Ignore(const AMessage: string);
  54. published
  55. property TestName: string read GetTestName;
  56. property TestSuiteName: string read GetTestSuiteName write SetTestSuiteName;
  57. property LastStep: TTestStep read FLastStep;
  58. property EnableIgnores: boolean read GetEnableIgnores write SetEnableIgnores;
  59. end;
  60. {$M-}
  61. { TAssert }
  62. TAssert = class(TTest)
  63. protected
  64. Class var AssertCount : Integer;
  65. public
  66. class procedure Fail(const AMessage: string; AErrorAddrs: Pointer = nil);
  67. class procedure Fail(const AFmt: string; Args : Array of const; AErrorAddrs: Pointer = nil);
  68. class procedure FailEquals(const expected, actual: string; const ErrorMsg: string = ''; AErrorAddrs: Pointer = nil);
  69. class procedure FailNotEquals(const expected, actual: string; const ErrorMsg: string = ''; AErrorAddrs: Pointer = nil);
  70. class procedure AssertTrue(const AMessage: string; ACondition: boolean; AErrorAddrs: Pointer = nil); overload;
  71. class procedure AssertTrue(ACondition: boolean); overload;
  72. class procedure AssertFalse(const AMessage: string; ACondition: boolean; AErrorAddrs: Pointer = nil); overload;
  73. class procedure AssertFalse(ACondition: boolean); overload;
  74. class procedure AssertEquals(const AMessage: string; Expected, Actual: string); overload;
  75. class procedure AssertEquals(Expected, Actual: string); overload;
  76. class procedure AssertEquals(const AMessage: string; Expected, Actual: UnicodeString); overload;
  77. class procedure AssertEquals(Expected, Actual: UnicodeString); overload;
  78. class procedure AssertEquals(const AMessage: string; Expected, Actual: integer); overload;
  79. class procedure AssertEquals(Expected, Actual: integer); overload;
  80. class procedure AssertEquals(const AMessage: string; Expected, Actual: int64); overload;
  81. class procedure AssertEquals(Expected, Actual: int64); overload;
  82. class procedure AssertEquals(const AMessage: string; Expected, Actual: QWord); overload;
  83. class procedure AssertEquals(Expected, Actual: QWord); overload;
  84. class procedure AssertEquals(const AMessage: string; Expected, Actual: currency); overload;
  85. class procedure AssertEquals(Expected, Actual: currency); overload;
  86. class procedure AssertEquals(const AMessage: string; Expected, Actual, Delta: double); overload;
  87. class procedure AssertEquals(Expected, Actual, Delta: double); overload;
  88. class procedure AssertEquals(const AMessage: string; Expected, Actual: boolean); overload;
  89. class procedure AssertEquals(Expected, Actual: boolean); overload;
  90. class procedure AssertEquals(const AMessage: string; Expected, Actual: char); overload;
  91. class procedure AssertEquals(Expected, Actual: char); overload;
  92. class procedure AssertEquals(const AMessage: string; Expected, Actual: TClass); overload;
  93. class procedure AssertEquals(Expected, Actual: TClass); overload;
  94. class procedure AssertSame(const AMessage: string; Expected, Actual: TObject); overload;
  95. class procedure AssertSame(Expected, Actual: TObject); overload;
  96. class procedure AssertSame(const AMessage: string; Expected, Actual: Pointer); overload;
  97. class procedure AssertSame(Expected, Actual: Pointer); overload;
  98. class procedure AssertNotSame(const AMessage: string; Expected, Actual: TObject); overload;
  99. class procedure AssertNotSame(Expected, Actual: TObject); overload;
  100. class procedure AssertNotSame(const AMessage: string; Expected, Actual: Pointer); overload;
  101. class procedure AssertNotSame(Expected, Actual: Pointer); overload;
  102. class procedure AssertNotNull(const AMessage: string; AObject: TObject); overload;
  103. class procedure AssertNotNull(AObject: TObject); overload;
  104. class procedure AssertNotNullIntf(const AMessage: string; AInterface: IInterface); overload;
  105. class procedure AssertNotNullIntf(AInterface: IInterface); overload;
  106. class procedure AssertNotNull(const AMessage: string; APointer: Pointer); overload;
  107. class procedure AssertNotNull(APointer: Pointer); overload;
  108. class procedure AssertNull(const AMessage: string; AObject: TObject); overload;
  109. class procedure AssertNull(AObject: TObject); overload;
  110. class procedure AssertNullIntf(const AMessage: string; AInterface: IInterface); overload;
  111. class procedure AssertNullIntf(AInterface: IInterface); overload;
  112. class procedure AssertNull(const AMessage: string; APointer: Pointer); overload;
  113. class procedure AssertNull(APointer: Pointer); overload;
  114. class procedure AssertNotNull(const AMessage, AString: string); overload;
  115. class procedure AssertNotNull(const AString: string); overload;
  116. class procedure AssertException(const AMessage: string; AExceptionClass: ExceptClass; AMethod: TRunMethod;AExceptionMessage : String = ''; AExceptionContext : Integer = 0; AErrorAddr : Pointer = Nil); overload;
  117. class procedure AssertException(AExceptionClass: ExceptClass; AMethod: TRunMethod;AExceptionMessage : String = ''; AExceptionContext : Integer = 0); overload;
  118. {$IFDEF DUnit}
  119. {$I DUnitCompatibleInterface.inc}
  120. {$ENDIF DUnit}
  121. end;
  122. TTestFailure = class(TObject)
  123. private
  124. FTestName: string;
  125. FTestSuiteName: string;
  126. FLineNumber: longint;
  127. FFailedMethodName: string;
  128. FRaisedExceptionClass: TClass;
  129. FRaisedExceptionMessage: string;
  130. FSourceUnitName: string;
  131. FThrownExceptionAddress: Pointer;
  132. FTestLastStep: TTestStep;
  133. function GetAsString: string;
  134. function GetExceptionMessage: string;
  135. function GetIsFailure: boolean;
  136. function GetIsIgnoredTest: boolean;
  137. function GetExceptionClassName: string;
  138. function GetLocationInfo: string;
  139. procedure SetTestLastStep(const Value: TTestStep);
  140. public
  141. constructor CreateFailure(ATest: TTest; E: Exception; LastStep: TTestStep; ThrownExceptionAddrs: pointer = nil);
  142. property ExceptionClass: TClass read FRaisedExceptionClass;
  143. published
  144. property AsString: string read GetAsString;
  145. property IsFailure: boolean read GetIsFailure;
  146. property IsIgnoredTest: boolean read GetIsIgnoredTest;
  147. property ExceptionMessage: string read GetExceptionMessage;
  148. property ExceptionClassName: string read GetExceptionClassName;
  149. property SourceUnitName: string read FSourceUnitName write FSourceUnitName;
  150. property LineNumber: longint read FLineNumber write FLineNumber;
  151. property LocationInfo: string read GetLocationInfo;
  152. property FailedMethodName: string read FFailedMethodName write FFailedMethodName;
  153. property TestLastStep: TTestStep read FTestLastStep write SetTestLastStep;
  154. end;
  155. ITestListener = interface
  156. ['{0CE9D3AE-882A-D811-9401-ADEB5E4C7FC1}']
  157. procedure AddFailure(ATest: TTest; AFailure: TTestFailure);
  158. procedure AddError(ATest: TTest; AError: TTestFailure);
  159. procedure StartTest(ATest: TTest);
  160. procedure EndTest(ATest: TTest);
  161. procedure StartTestSuite(ATestSuite: TTestSuite);
  162. procedure EndTestSuite(ATestSuite: TTestSuite);
  163. end;
  164. { TTestCase }
  165. TTestCase = class(TAssert)
  166. private
  167. FName: string;
  168. FTestSuiteName: string;
  169. FEnableIgnores: boolean;
  170. FExpectedExceptionFailMessage : String;
  171. FExpectedException : TClass;
  172. FExpectedExceptionMessage: String;
  173. FExpectedExceptionContext: Integer;
  174. FExpectedExceptionCaller : Pointer;
  175. protected
  176. function CreateResult: TTestResult; virtual;
  177. procedure SetUp; virtual;
  178. procedure TearDown; virtual;
  179. procedure RunTest; virtual;
  180. function GetTestName: string; override;
  181. function GetTestSuiteName: string; override;
  182. function GetEnableIgnores: boolean; override;
  183. procedure SetTestSuiteName(const aName: string); override;
  184. procedure SetTestName(const Value: string); virtual;
  185. procedure SetEnableIgnores(Value: boolean); override;
  186. procedure RunBare; virtual;
  187. Class function SingleInstanceForSuite : Boolean; virtual;
  188. Public
  189. Class Var CheckAssertCalled : Boolean;
  190. public
  191. constructor Create; virtual;
  192. constructor CreateWith(const ATestName: string; const ATestSuiteName: string); virtual;
  193. constructor CreateWithName(const AName: string); virtual;
  194. procedure ExpectException(AExceptionClass: TClass; AExceptionMessage: string=''; AExceptionHelpContext: Integer=0);
  195. procedure ExpectException(const Msg: String; AExceptionClass: TClass; AExceptionMessage: string=''; AExceptionHelpContext: Integer=0);
  196. function CountTestCases: integer; override;
  197. function CreateResultAndRun: TTestResult; virtual;
  198. procedure Run(AResult: TTestResult); override;
  199. function AsString: string;
  200. property TestSuiteName: string read GetTestSuiteName write SetTestSuiteName;
  201. Property ExpectedExceptionFailMessage : String Read FExpectedExceptionFailMessage;
  202. Property ExpectedException : TClass Read FExpectedException;
  203. Property ExpectedExceptionMessage : String Read FExpectedExceptionMessage;
  204. Property ExpectedExceptionContext: Integer Read FExpectedExceptionContext;
  205. published
  206. property TestName: string read GetTestName write SetTestName;
  207. end;
  208. TTestCaseClass = class of TTestCase;
  209. { TTestSuite }
  210. TTestSuite = class(TTest)
  211. private
  212. FOwnsTests: Boolean;
  213. FTests: TFPList;
  214. FName: string;
  215. FTestSuiteName: string;
  216. FEnableIgnores: boolean;
  217. procedure SetOwnsTests(AValue: Boolean);
  218. protected
  219. Procedure SetOwnTestOnTests(AValue: Boolean);
  220. Function DoAddTest(ATest : TTest) : Integer;
  221. function GetTestName: string; override;
  222. function GetTestSuiteName: string; override;
  223. function GetEnableIgnores: boolean; override;
  224. procedure SetTestSuiteName(const aName: string); override;
  225. procedure SetTestName(const Value: string); virtual;
  226. procedure SetEnableIgnores(Value: boolean); override;
  227. property OwnsTests : Boolean Read FOwnsTests Write SetOwnsTests;
  228. public
  229. constructor Create(AClass: TClass; AName: string); reintroduce; overload; virtual;
  230. constructor Create(AClass: TClass); reintroduce; overload; virtual;
  231. constructor Create(AClassArray: Array of TClass); reintroduce; overload; virtual;
  232. constructor Create(AName: string); reintroduce; overload; virtual;
  233. constructor Create; reintroduce; overload; virtual;
  234. destructor Destroy; override;
  235. function CountTestCases: integer; override;
  236. Function GetChildTestCount : Integer; override;
  237. Function GetChildTest(AIndex : Integer) : TTest; override;
  238. procedure Run(AResult: TTestResult); override;
  239. procedure RunTest(ATest: TTest; AResult: TTestResult); virtual;
  240. procedure AddTest(ATest: TTest); overload; virtual;
  241. procedure AddTestSuiteFromClass(ATestClass: TClass); virtual;
  242. class function Warning(const aMessage: string): TTestCase;
  243. property Test[Index: integer]: TTest read GetChildTest; default;
  244. Property ChildTestCount : Integer Read GetChildTestCount;
  245. property TestSuiteName: string read GetTestSuiteName write SetTestSuiteName;
  246. property TestName: string read GetTestName write SetTestName;
  247. // Only for backwards compatibility. Use Test and ChildTestCount.
  248. property Tests: TFPList read FTests; deprecated;
  249. end;
  250. TProtect = procedure(aTest: TTest; aResult: TTestResult);
  251. { TTestResult }
  252. TTestResult = class(TObject)
  253. protected
  254. FRunTests: integer;
  255. FFailures: TFPList;
  256. FIgnoredTests: TFPList;
  257. FErrors: TFPList;
  258. FListeners: TFPList;
  259. FSkippedTests: TFPList;
  260. FStartingTime: TDateTime;
  261. function GetNumErrors: integer;
  262. function GetNumFailures: integer;
  263. function GetNumIgnoredTests: integer;
  264. function GetNumSkipped: integer;
  265. public
  266. constructor Create; virtual;
  267. destructor Destroy; override;
  268. procedure ClearErrorLists;
  269. procedure StartTest(ATest: TTest);
  270. procedure AddFailure(ATest: TTest; E: EAssertionFailedError; aFailureList: TFPList; AThrownExceptionAdrs: Pointer);
  271. procedure AddError(ATest: TTest; E: Exception; AThrownExceptionAdrs: Pointer);
  272. procedure EndTest(ATest: TTest);
  273. procedure AddListener(AListener: ITestListener);
  274. procedure RemoveListener(AListener: ITestListener);
  275. procedure Run(ATestCase: TTestCase);
  276. procedure RunProtected(ATestCase: TTest; protect: TProtect);
  277. function WasSuccessful: boolean;
  278. function SkipTest(ATestCase: TTestCase): boolean;
  279. procedure AddToSkipList(ATestCase: TTestCase);
  280. procedure RemoveFromSkipList(ATestCase: TTestCase);
  281. procedure StartTestSuite(ATestSuite: TTestSuite);
  282. procedure EndTestSuite(ATestSuite: TTestSuite);
  283. published
  284. property Listeners: TFPList read FListeners;
  285. property Failures: TFPList read FFailures;
  286. property IgnoredTests: TFPList read FIgnoredTests;
  287. property Errors: TFPList read FErrors;
  288. property RunTests: integer read FRunTests;
  289. property NumberOfErrors: integer read GetNumErrors;
  290. property NumberOfFailures: integer read GetNumFailures;
  291. property NumberOfIgnoredTests: integer read GetNumIgnoredTests;
  292. property NumberOfSkippedTests: integer read GetNumSkipped;
  293. property StartingTime: TDateTime read FStartingTime;
  294. end;
  295. function ComparisonMsg(const aExpected: string; const aActual: string; const aCheckEqual: boolean=true): string; overload;
  296. function ComparisonMsg(const aExpected: UnicodeString; const aActual: UnicodeString; const aCheckEqual: boolean=true): Unicodestring; overload;
  297. function ComparisonMsg(const aMsg: string; const aExpected: string; const aActual: string; const aCheckEqual: boolean=true): string; overload;
  298. // Made public for 3rd party developers extending TTestCase with new AssertXXX methods
  299. function CallerAddr: Pointer;
  300. Resourcestring
  301. SCompare = ' expected: <%s> but was: <%s>';
  302. SCompareNotEqual = ' expected: not equal to <%s> but was: <%s>';
  303. SExpectedNotSame = 'expected not same';
  304. SExceptionCompare = 'Exception %s expected but %s was raised';
  305. SExceptionMessageCompare = 'Exception raised but exception property Message differs: ';
  306. SExceptionHelpContextCompare = 'Exception raised but exception property HelpContext differs: ';
  307. SMethodNotFound = 'Method <%s> not found';
  308. SNoValidInheritance = ' does not inherit from TTestCase';
  309. SNoValidTests = 'No valid tests found in ';
  310. SNoException = 'no exception';
  311. SAssertNotCalled = 'Assert not called during test.';
  312. implementation
  313. uses
  314. testutils;
  315. Const
  316. sExpectedButWasFmt = 'Expected:' + LineEnding + '"%s"' + LineEnding + 'But was:' + LineEnding + '"%s"';
  317. sExpectedButWasAndMessageFmt = '%s' + LineEnding + sExpectedButWasFmt;
  318. { This lets us use a single include file for both the Interface and
  319. Implementation sections. }
  320. {$undef read_interface}
  321. {$define read_implementation}
  322. function CallerAddr: Pointer;
  323. Var
  324. address: CodePointer;
  325. nframes: sizeint;
  326. begin
  327. nframes:=CaptureBacktrace(2,1,@address);
  328. if nframes=1 then
  329. result:=address
  330. else
  331. result:=nil;
  332. end;
  333. function AddrsToStr(Addrs: Pointer): string;
  334. begin
  335. if PtrUInt(Addrs) > 0 then
  336. Result := '$'+Format('%p', [Addrs])
  337. else
  338. Result := 'n/a';
  339. end;
  340. function PointerToLocationInfo(Addrs: Pointer): string;
  341. begin
  342. Result := BackTraceStrFunc(Addrs);
  343. if Trim(Result) = '' then
  344. Result := AddrsToStr(Addrs) + ' <no map file>';
  345. end;
  346. // Get the ClassName of C
  347. function GetN(C : TClass) : string;
  348. begin
  349. if C=Nil then
  350. Result:='<NIL>'
  351. else
  352. Result:=C.ClassName;
  353. end;
  354. type
  355. TTestWarning = class(TTestCase)
  356. private
  357. FMessage: String;
  358. protected
  359. procedure RunTest; override;
  360. end;
  361. procedure TTestWarning.RunTest;
  362. begin
  363. Fail(FMessage);
  364. end;
  365. function ComparisonMsg(const aExpected: string; const aActual: string; const aCheckEqual: boolean=true): string;
  366. // aCheckEqual=false gives the error message if the test does *not* expect the results to be the same.
  367. begin
  368. if aCheckEqual then
  369. Result := format(SCompare, [aExpected, aActual])
  370. else {check unequal requires opposite error message}
  371. Result := format(SCompareNotEqual, [aExpected, aActual]);
  372. end;
  373. function ComparisonMsg(const aExpected: Unicodestring; const aActual: Unicodestring; const aCheckEqual: boolean=true): Unicodestring;
  374. // aCheckEqual=false gives the error message if the test does *not* expect the results to be the same.
  375. begin
  376. if aCheckEqual then
  377. Result := unicodeformat(SCompare, [aExpected, aActual])
  378. else {check unequal requires opposite error message}
  379. Result := unicodeformat(SCompareNotEqual, [aExpected, aActual]);
  380. end;
  381. function ComparisonMsg(const aMsg: string; const aExpected: string; const aActual: string; const aCheckEqual: boolean): string;
  382. begin
  383. Result := '"' + aMsg + '"' + ComparisonMsg(aExpected, aActual, aCheckEqual);
  384. end;
  385. constructor EAssertionFailedError.Create;
  386. begin
  387. inherited Create('');
  388. end;
  389. constructor EAssertionFailedError.Create(const msg: string);
  390. begin
  391. inherited Create(msg);
  392. end;
  393. constructor TTestFailure.CreateFailure(ATest: TTest; E: Exception; LastStep: TTestStep; ThrownExceptionAddrs: pointer);
  394. begin
  395. inherited Create;
  396. FTestName := ATest.GetTestName;
  397. FTestSuiteName := ATest.GetTestSuiteName;
  398. FRaisedExceptionClass := E.ClassType;
  399. FRaisedExceptionMessage := E.Message;
  400. FThrownExceptionAddress := ThrownExceptionAddrs;
  401. FTestLastStep := LastStep;
  402. end;
  403. function TTestFailure.GetAsString: string;
  404. var
  405. s: string;
  406. begin
  407. if FTestSuiteName <> '' then
  408. s := FTestSuiteName + '.'
  409. else
  410. s := '';
  411. Result := s + FTestName + ': ' + FRaisedExceptionMessage;
  412. end;
  413. function TTestFailure.GetExceptionClassName: string;
  414. begin
  415. if Assigned(FRaisedExceptionClass) then
  416. Result := FRaisedExceptionClass.ClassName
  417. else
  418. Result := '<NIL>'
  419. end;
  420. function TTestFailure.GetLocationInfo: string;
  421. begin
  422. Result := PointerToLocationInfo(FThrownExceptionAddress);
  423. end;
  424. function TTestFailure.GetExceptionMessage: string;
  425. begin
  426. Result := FRaisedExceptionMessage;
  427. if TestLastStep = stSetUp then
  428. Result := '[SETUP] ' + Result
  429. else if TestLastStep = stTearDown then
  430. Result := '[TEARDOWN] ' + Result;
  431. end;
  432. function TTestFailure.GetIsFailure: boolean;
  433. begin
  434. Result := FRaisedExceptionClass.InheritsFrom(EAssertionFailedError);
  435. end;
  436. function TTestFailure.GetIsIgnoredTest: boolean;
  437. begin
  438. Result := FRaisedExceptionClass.InheritsFrom(EIgnoredTest);
  439. end;
  440. procedure TTestFailure.SetTestLastStep(const Value: TTestStep);
  441. begin
  442. FTestLastStep := Value;
  443. end;
  444. { TTest}
  445. function TTest.GetTestName: string;
  446. begin
  447. Result := 'TTest';
  448. end;
  449. function TTest.GetTestSuiteName: string;
  450. begin
  451. Result := 'TTest';
  452. end;
  453. function TTest.CountTestCases: integer;
  454. begin
  455. Result := 0;
  456. end;
  457. function TTest.GetChildTestCount: Integer;
  458. begin
  459. Result:=0;
  460. end;
  461. function TTest.GetChildTest(AIndex: Integer): TTest;
  462. begin
  463. Result:=Nil;
  464. end;
  465. function TTest.FindChildTest(const AName: String): TTest;
  466. Var
  467. I : Integer;
  468. begin
  469. Result:=Nil;
  470. I:=GetChildTestCount-1;
  471. While (Result=Nil) and (I>=0) do
  472. begin
  473. Result:=GetChildTest(I);
  474. if CompareText(Result.TestName,AName)<>0 then
  475. Result:=Nil;
  476. Dec(I);
  477. end;
  478. end;
  479. function TTest.FindTest(const AName: String): TTest;
  480. Var
  481. S : String;
  482. I,P : Integer;
  483. begin
  484. Result:=Nil;
  485. S:=AName;
  486. if S='' then exit;
  487. P:=Pos('.',S);
  488. If (P=0) then
  489. P:=Length(S)+1;
  490. Result:=FindChildTest(Copy(S,1,P-1));
  491. if (Result<>Nil) then
  492. begin
  493. Delete(S,1,P);
  494. If (S<>'') then
  495. Result:=Result.FindTest(S);
  496. end
  497. else
  498. begin
  499. P:=GetChildTestCount;
  500. I:=0;
  501. While (Result=Nil) and (I<P) do
  502. begin
  503. Result:=GetChildTest(I).FindTest(Aname);
  504. Inc(I);
  505. end;
  506. end;
  507. end;
  508. function TTest.GetEnableIgnores: boolean;
  509. begin
  510. Result := True;
  511. end;
  512. procedure TTest.Run(AResult: TTestResult);
  513. begin
  514. { do nothing }
  515. end;
  516. procedure TTest.Ignore(const AMessage: string);
  517. begin
  518. if EnableIgnores then raise EIgnoredTest.Create(AMessage);
  519. end;
  520. { TAssert }
  521. class procedure TAssert.Fail(const AMessage: string; AErrorAddrs: Pointer);
  522. begin
  523. Inc(AssertCount);
  524. if AErrorAddrs = nil then
  525. raise EAssertionFailedError.Create(AMessage) at CallerAddr
  526. else
  527. raise EAssertionFailedError.Create(AMessage) at AErrorAddrs;
  528. end;
  529. class procedure TAssert.Fail(const AFmt: string; Args: array of const; AErrorAddrs: Pointer = nil);
  530. begin
  531. Inc(AssertCount);
  532. if AErrorAddrs = nil then
  533. raise EAssertionFailedError.CreateFmt(AFmt,Args) at CallerAddr
  534. else
  535. raise EAssertionFailedError.CreateFmt(AFmt,Args) at AErrorAddrs;
  536. end;
  537. class procedure TAssert.FailEquals(const expected, actual: string; const ErrorMsg: string; AErrorAddrs: Pointer);
  538. begin
  539. Fail(EqualsErrorMessage(expected, actual, ErrorMsg), AErrorAddrs);
  540. end;
  541. class procedure TAssert.FailNotEquals(const expected, actual: string; const ErrorMsg: string; AErrorAddrs: Pointer);
  542. begin
  543. Fail(NotEqualsErrorMessage(expected, actual, ErrorMsg), AErrorAddrs);
  544. end;
  545. class procedure TAssert.AssertTrue(const AMessage: string; ACondition: boolean; AErrorAddrs: Pointer = nil);
  546. begin
  547. if AErrorAddrs=Nil then
  548. AErrorAddrs:=CallerAddr;
  549. if (not ACondition) then
  550. Fail(AMessage,AErrorAddrs)
  551. else
  552. Inc(AssertCount); // Fail will increae AssertCount
  553. end;
  554. class procedure TAssert.AssertTrue(ACondition: boolean);
  555. begin
  556. AssertTrue('', ACondition,CallerAddr);
  557. end;
  558. class procedure TAssert.AssertFalse(const AMessage: string; ACondition: boolean; AErrorAddrs: Pointer = nil
  559. );
  560. begin
  561. if AErrorAddrs=Nil then
  562. AErrorAddrs:=CallerAddr;
  563. AssertTrue(AMessage, not ACondition,AErrorAddrs);
  564. end;
  565. class procedure TAssert.AssertFalse(ACondition: boolean);
  566. begin
  567. AssertFalse('', ACondition,CallerAddr);
  568. end;
  569. class procedure TAssert.AssertEquals(const AMessage: string; Expected, Actual: string);
  570. begin
  571. AssertTrue(ComparisonMsg(AMessage ,Expected, Actual), Expected=Actual,CallerAddr);
  572. end;
  573. class procedure TAssert.AssertEquals(Expected, Actual: string);
  574. begin
  575. AssertTrue(ComparisonMsg(Expected, Actual), Expected=Actual,CallerAddr);
  576. end;
  577. class procedure TAssert.AssertEquals(const AMessage: string; Expected, Actual: Unicodestring);
  578. begin
  579. AssertTrue(ComparisonMsg(AMessage ,Expected, Actual), Expected=Actual,CallerAddr);
  580. end;
  581. class procedure TAssert.AssertEquals(Expected, Actual: Unicodestring);
  582. begin
  583. AssertTrue(ComparisonMsg(Expected, Actual), Expected=Actual,CallerAddr);
  584. end;
  585. class procedure TAssert.AssertNotNull(const AString: string);
  586. begin
  587. AssertNotNull('', AString);
  588. end;
  589. class procedure TAssert.AssertEquals(const AMessage: string; Expected, Actual: integer);
  590. begin
  591. AssertTrue(ComparisonMsg(AMessage,IntToStr(Expected), IntToStr(Actual)), Expected = Actual,CallerAddr);
  592. end;
  593. class procedure TAssert.AssertEquals(Expected, Actual: integer);
  594. begin
  595. AssertTrue(ComparisonMsg(IntToStr(Expected), IntToStr(Actual)), Expected = Actual,CallerAddr);
  596. end;
  597. class procedure TAssert.AssertEquals(const AMessage: string; Expected, Actual: int64);
  598. begin
  599. AssertTrue(ComparisonMsg(AMessage,IntToStr(Expected), IntToStr(Actual)), Expected = Actual,CallerAddr);
  600. end;
  601. class procedure TAssert.AssertEquals(Expected, Actual: int64);
  602. begin
  603. AssertTrue(ComparisonMsg(IntToStr(Expected), IntToStr(Actual)), Expected = Actual,CallerAddr);
  604. end;
  605. class procedure TAssert.AssertEquals(const AMessage: string; Expected, Actual: QWord);
  606. begin
  607. AssertTrue(ComparisonMsg(AMessage,IntToStr(Expected), IntToStr(Actual)), Expected = Actual,CallerAddr);
  608. end;
  609. class procedure TAssert.AssertEquals(Expected, Actual: QWord);
  610. begin
  611. AssertTrue(ComparisonMsg(IntToStr(Expected), IntToStr(Actual)), Expected = Actual,CallerAddr);
  612. end;
  613. class procedure TAssert.AssertEquals(const AMessage: string; Expected, Actual: currency);
  614. begin
  615. AssertTrue(ComparisonMsg(AMessage,FloatToStr(Expected), FloatToStr(Actual)), Expected = Actual,CallerAddr);
  616. end;
  617. class procedure TAssert.AssertEquals(Expected, Actual: currency);
  618. begin
  619. AssertTrue(ComparisonMsg(FloatToStr(Expected), FloatToStr(Actual)), Expected = Actual,CallerAddr);
  620. end;
  621. class procedure TAssert.AssertEquals(const AMessage: string; Expected, Actual, Delta: double);
  622. begin
  623. AssertTrue(ComparisonMsg(AMessage,FloatToStr(Expected),FloatToStr(Actual)),
  624. (Abs(Expected - Actual) <= Delta),CallerAddr);
  625. end;
  626. class procedure TAssert.AssertEquals(Expected, Actual, Delta: double);
  627. begin
  628. AssertTrue(ComparisonMsg(FloatToStr(Expected),FloatToStr(Actual)),
  629. (Abs(Expected - Actual) <= Delta),CallerAddr);
  630. end;
  631. class procedure TAssert.AssertNotNull(const AMessage, AString: string);
  632. begin
  633. AssertTrue(AMessage, AString <> '',CallerAddr);
  634. end;
  635. class procedure TAssert.AssertEquals(const AMessage: string; Expected, Actual: boolean);
  636. begin
  637. AssertTrue(ComparisonMsg(AMessage,BoolToStr(Expected, true), BoolToStr(Actual, true)), Expected = Actual,CallerAddr);
  638. end;
  639. class procedure TAssert.AssertEquals(Expected, Actual: boolean);
  640. begin
  641. AssertTrue(ComparisonMsg(BoolToStr(Expected, true), BoolToStr(Actual, true)), Expected = Actual,CallerAddr);
  642. end;
  643. class procedure TAssert.AssertEquals(const AMessage: string; Expected, Actual: char);
  644. begin
  645. AssertTrue(ComparisonMsg(AMessage,Expected, Actual), Expected = Actual,CallerAddr);
  646. end;
  647. class procedure TAssert.AssertEquals(Expected, Actual: char);
  648. begin
  649. AssertTrue(ComparisonMsg(Expected, Actual), Expected = Actual,CallerAddr);
  650. end;
  651. class procedure TAssert.AssertEquals(const AMessage: string; Expected, Actual: TClass);
  652. begin
  653. AssertTrue(ComparisonMsg(AMessage,GetN(Expected), GetN(Actual)), Expected = Actual,CallerAddr);
  654. end;
  655. class procedure TAssert.AssertEquals(Expected, Actual: TClass);
  656. begin
  657. AssertTrue(ComparisonMsg(GetN(Expected), GetN(Actual)), Expected = Actual,CallerAddr);
  658. end;
  659. class procedure TAssert.AssertSame(const AMessage: string; Expected, Actual: TObject);
  660. begin
  661. AssertTrue(ComparisonMsg(AMessage,IntToStr(PtrInt(Expected)), IntToStr(PtrInt(Actual))), Expected = Actual,CallerAddr);
  662. end;
  663. class procedure TAssert.AssertSame(Expected, Actual: TObject);
  664. begin
  665. AssertTrue(ComparisonMsg(IntToStr(PtrInt(Expected)), IntToStr(PtrInt(Actual))), Expected = Actual,CallerAddr);
  666. end;
  667. class procedure TAssert.AssertSame(const AMessage: string; Expected, Actual: Pointer);
  668. begin
  669. AssertTrue(ComparisonMsg(AMessage,IntToStr(PtrInt(Expected)), IntToStr(PtrInt(Actual))), Expected = Actual,CallerAddr);
  670. end;
  671. class procedure TAssert.AssertSame(Expected, Actual: Pointer);
  672. begin
  673. AssertTrue(ComparisonMsg(IntToStr(PtrInt(Expected)), IntToStr(PtrInt(Actual))), Expected = Actual,CallerAddr);
  674. end;
  675. class procedure TAssert.AssertNotSame(const AMessage: string; Expected, Actual: TObject);
  676. begin
  677. AssertFalse('"' + aMessage + '"' + SExpectedNotSame, Expected = Actual,CallerAddr);
  678. end;
  679. class procedure TAssert.AssertNotSame(Expected, Actual: TObject);
  680. begin
  681. AssertFalse(SExpectedNotSame, Expected = Actual);
  682. end;
  683. class procedure TAssert.AssertNotSame(const AMessage: string; Expected, Actual: Pointer);
  684. begin
  685. AssertFalse('"' + aMessage + '"' + SExpectedNotSame, Expected = Actual,CallerAddr);
  686. end;
  687. class procedure TAssert.AssertNotSame(Expected, Actual: Pointer);
  688. begin
  689. AssertFalse(SExpectedNotSame, Expected = Actual,CallerAddr);
  690. end;
  691. class procedure TAssert.AssertNotNull(const AMessage: string; AObject: TObject);
  692. begin
  693. AssertTrue(AMessage, (AObject <> nil),CallerAddr);
  694. end;
  695. class procedure TAssert.AssertNotNull(AObject: TObject);
  696. begin
  697. AssertTrue('',(AObject <> nil),CallerAddr);
  698. end;
  699. class procedure TAssert.AssertNotNullIntf(const AMessage: string; AInterface: IInterface);
  700. begin
  701. AssertTrue(AMessage, (AInterface <> nil),CallerAddr);
  702. end;
  703. class procedure TAssert.AssertNotNullIntf(AInterface: IInterface);
  704. begin
  705. AssertTrue('', (AInterface <> nil),CallerAddr);
  706. end;
  707. class procedure TAssert.AssertNotNull(const AMessage: string; APointer: Pointer);
  708. begin
  709. AssertTrue(AMessage, (APointer <> nil),callerAddr);
  710. end;
  711. class procedure TAssert.AssertNotNull(APointer: Pointer);
  712. begin
  713. AssertTrue('', (APointer <> nil),callerAddr);
  714. end;
  715. class procedure TAssert.AssertNull(const AMessage: string; AObject: TObject);
  716. begin
  717. AssertTrue(AMessage, (AObject = nil),CallerAddr);
  718. end;
  719. class procedure TAssert.AssertNull(AObject: TObject);
  720. begin
  721. AssertTrue('',(AObject = nil),CallerAddr);
  722. end;
  723. class procedure TAssert.AssertNullIntf(const AMessage: string; AInterface: IInterface);
  724. begin
  725. AssertTrue(AMessage, (AInterface = nil),CallerAddr);
  726. end;
  727. class procedure TAssert.AssertNullIntf(AInterface: IInterface);
  728. begin
  729. AssertTrue('', (AInterface = nil),CallerAddr);
  730. end;
  731. class procedure TAssert.AssertNull(const AMessage: string; APointer: Pointer);
  732. begin
  733. AssertTrue(AMessage, (APointer = nil),CallerAddr);
  734. end;
  735. class procedure TAssert.AssertNull(APointer: Pointer);
  736. begin
  737. AssertTrue('', (APointer = nil),CallerAddr);
  738. end;
  739. class procedure TAssert.AssertException(const AMessage: string; AExceptionClass: ExceptClass;
  740. AMethod: TRunMethod;AExceptionMessage : String = ''; AExceptionContext : Integer = 0; AErrorAddr : Pointer = Nil);
  741. Function MisMatch (AClassName : String) : String;
  742. begin
  743. Result:=Format(SExceptionCompare,[AExceptionClass.ClassName, AClassName])
  744. end;
  745. var
  746. FailMsg : string;
  747. begin
  748. If AErrorAddr=Nil then
  749. AErrorAddr:=CallerAddr;
  750. FailMsg:='';
  751. try
  752. AMethod;
  753. FailMsg:=MisMatch(SNoException);
  754. except
  755. on E: Exception do
  756. begin
  757. if Not E.ClassType.InheritsFrom(AExceptionClass) then
  758. FailMsg:=MisMatch(E.ClassName)
  759. else if not (AExceptionClass.ClassName = E.ClassName) then
  760. FailMsg:=MisMatch(E.ClassName)
  761. else if (AExceptionMessage<>'') and (AExceptionMessage<>E.Message) then
  762. FailMsg:=ComparisonMsg(SExceptionMessageCompare,AExceptionMessage,E.Message)
  763. else if (AExceptionContext<>0) and (AExceptionContext<>E.HelpContext) then
  764. FailMsg:=ComparisonMsg(SExceptionHelpContextCompare,IntToStr(AExceptionContext),IntToStr(E.HelpContext))
  765. end;
  766. end;
  767. AssertTrue(AMessage + ': '+FailMsg, FailMsg='', AErrorAddr);
  768. end;
  769. class procedure TAssert.AssertException(AExceptionClass: ExceptClass;
  770. AMethod: TRunMethod;AExceptionMessage : String = ''; AExceptionContext : Integer = 0);
  771. begin
  772. AssertException('', AExceptionClass, AMethod, AExceptionMessage, AExceptionContext, CallerAddr);
  773. end;
  774. { DUnit compatibility interface }
  775. {$IFDEF DUnit}
  776. {$I DUnitCompatibleInterface.inc}
  777. {$ENDIF DUnit}
  778. constructor TTestCase.Create;
  779. begin
  780. inherited Create;
  781. FEnableIgnores := True;
  782. end;
  783. constructor TTestCase.CreateWithName(const AName: string);
  784. begin
  785. Create;
  786. FName := AName;
  787. end;
  788. constructor TTestCase.CreateWith(const ATestName: string; const ATestSuiteName: string);
  789. begin
  790. Create;
  791. FName := ATestName;
  792. FTestSuiteName := ATestSuiteName;
  793. end;
  794. function TTestCase.AsString: string;
  795. begin
  796. Result := TestName + '(' + ClassName + ')';
  797. end;
  798. function TTestCase.CountTestCases: integer;
  799. begin
  800. Result := 1;
  801. end;
  802. function TTestCase.CreateResult: TTestResult;
  803. begin
  804. Result := TTestResult.Create;
  805. end;
  806. function TTestCase.GetTestName: string;
  807. begin
  808. Result := FName;
  809. end;
  810. function TTestCase.GetEnableIgnores: boolean;
  811. begin
  812. Result := FEnableIgnores;
  813. end;
  814. function TTestCase.GetTestSuiteName: string;
  815. begin
  816. Result := FTestSuiteName;
  817. end;
  818. procedure TTestCase.SetTestSuiteName(const aName: string);
  819. begin
  820. if FTestSuiteName <> aName then
  821. FTestSuiteName := aName;
  822. end;
  823. procedure TTestCase.SetTestName(const Value: string);
  824. begin
  825. FName := Value;
  826. end;
  827. procedure TTestCase.SetEnableIgnores(Value: boolean);
  828. begin
  829. FEnableIgnores := Value;
  830. end;
  831. function TTestCase.CreateResultAndRun: TTestResult;
  832. begin
  833. Result := CreateResult;
  834. Run(Result);
  835. end;
  836. procedure TTestCase.Run(AResult: TTestResult);
  837. begin
  838. (AResult).Run(Self);
  839. end;
  840. procedure TTestCase.RunBare;
  841. begin
  842. FLastStep := stSetUp;
  843. SetUp;
  844. try
  845. FLastStep := stRunTest;
  846. RunTest;
  847. FLastStep := stTearDown;
  848. finally
  849. TearDown;
  850. end;
  851. FLastStep := stNothing;
  852. end;
  853. class function TTestCase.SingleInstanceForSuite: Boolean;
  854. begin
  855. Result:=False;
  856. end;
  857. procedure TTestCase.RunTest;
  858. var
  859. m: TMethod;
  860. RunMethod: TRunMethod;
  861. pMethod : Pointer;
  862. FailMessage : String;
  863. begin
  864. AssertNotNull('name of the test not assigned', FName);
  865. pMethod := Self.MethodAddress(FName);
  866. if (Assigned(pMethod)) then
  867. begin
  868. m.Code := pMethod;
  869. m.Data := self;
  870. RunMethod := TRunMethod(m);
  871. ExpectException('',Nil,'',0);
  872. try
  873. AssertCount:=0;
  874. FailMessage:='';
  875. RunMethod;
  876. if (FExpectedException<>Nil) then
  877. FailMessage:=Format(SExceptionCompare, [FExpectedException.ClassName, SNoException]);
  878. if CheckAssertCalled and (AssertCount=0) then
  879. FailMessage:=SAssertNotCalled;
  880. except
  881. On E : Exception do
  882. begin
  883. if FExpectedException=Nil then
  884. Raise;
  885. If not (E is FExpectedException) then
  886. FailMessage:=Format(SExceptionCompare, [FExpectedException.ClassName, E.ClassName]);
  887. if (FExpectedExceptionMessage<>'') then
  888. if (FExpectedExceptionMessage<>E.Message) then
  889. FailMessage:=Format(SExceptionmessageCompare+SCompare, [FExpectedExceptionMessage,E.Message]);
  890. if (FExpectedExceptionContext<>0) then
  891. if (FExpectedExceptionContext<>E.HelpContext) then
  892. FailMessage:=Format(SExceptionHelpContextCompare+SCompare, [IntToStr(FExpectedExceptionContext),IntToStr(E.HelpContext)])
  893. end;
  894. end;
  895. if (FailMessage<>'') then
  896. begin
  897. if (FExpectedExceptionFailMessage<>'') then
  898. FailMessage:=' : '+FailMessage;
  899. Fail(FExpectedExceptionFailMessage+FailMessage,FExpectedExceptionCaller);
  900. end;
  901. end
  902. else
  903. begin
  904. Fail(format(SMethodNotFound, [FName]));
  905. end;
  906. end;
  907. procedure TTestCase.SetUp;
  908. begin
  909. { do nothing }
  910. end;
  911. procedure TTestCase.TearDown;
  912. begin
  913. { do nothing }
  914. end;
  915. Type
  916. { TTestItem }
  917. TTestItem = Class(TObject)
  918. private
  919. FName: String;
  920. FOwnsTest: Boolean;
  921. FTest: TTest;
  922. public
  923. Constructor Create(T : TTest);
  924. Destructor Destroy; override;
  925. Property Test : TTest Read FTest;
  926. Property TestName : String Read FName;
  927. Property OwnsTest : Boolean Read FOwnsTest Write FOwnstest;
  928. end;
  929. { TTestItem }
  930. constructor TTestItem.Create(T: TTest);
  931. begin
  932. FTest:=T;
  933. FName:=T.TestName;
  934. FOwnsTest:=True;
  935. end;
  936. destructor TTestItem.Destroy;
  937. begin
  938. if FOwnsTest then
  939. FreeAndNil(FTest);
  940. inherited Destroy;
  941. end;
  942. constructor TTestSuite.Create(AClass: TClass; AName: string);
  943. begin
  944. Create(AClass);
  945. FName := AName;
  946. end;
  947. constructor TTestSuite.Create(AClass: TClass);
  948. var
  949. ml: TStringList;
  950. i,j: integer;
  951. tc: TTestCaseClass;
  952. C : TTestCase;
  953. SN : String;
  954. begin
  955. TAssert.AssertNotNull(AClass);
  956. Create(AClass.ClassName);
  957. if AClass.InheritsFrom(TTestCase) then
  958. begin
  959. tc := TTestCaseClass(AClass);
  960. ml := TStringList.Create;
  961. try
  962. GetMethodList(AClass, ml);
  963. SN:=tc.ClassName;
  964. if tc.SingleInstanceForSuite then
  965. begin
  966. c:=tc.CreateWith('',SN);
  967. for i := 0 to ml.Count -1 do
  968. begin
  969. C.TestName:=ml[i];
  970. J:=DoAddTest(C);
  971. TTestItem(FTests[J]).OwnsTest:=(I=0);
  972. end;
  973. end
  974. else
  975. for i := 0 to ml.Count -1 do
  976. AddTest(tc.CreateWith(ml.Strings[i], SN));
  977. finally
  978. ml.Free;
  979. end;
  980. end
  981. else
  982. AddTest(Warning(AClass.ClassName + SNoValidInheritance));
  983. if FTests.Count = 0 then
  984. AddTest(Warning(SNoValidTests + AClass.ClassName));
  985. end;
  986. constructor TTestSuite.Create(AClassArray: array of TClass);
  987. var
  988. i: integer;
  989. begin
  990. Create;
  991. for i := Low(AClassArray) to High(AClassArray) do
  992. if Assigned(AClassArray[i]) then
  993. AddTest(TTestSuite.Create(AClassArray[i]));
  994. end;
  995. constructor TTestSuite.Create(AName: string);
  996. begin
  997. Create();
  998. FName := AName;
  999. end;
  1000. constructor TTestSuite.Create;
  1001. begin
  1002. inherited Create;
  1003. FTests := TFPList.Create;
  1004. FOwnsTests:=True;
  1005. FEnableIgnores := True;
  1006. end;
  1007. destructor TTestSuite.Destroy;
  1008. begin
  1009. FreeObjects(FTests);
  1010. FTests.Free;
  1011. inherited Destroy;
  1012. end;
  1013. function TTestSuite.GetChildTest(AIndex: integer): TTest;
  1014. begin
  1015. Result := TTestItem(FTests[AIndex]).Test;
  1016. end;
  1017. function TTestSuite.GetChildTestCount: Integer;
  1018. begin
  1019. Result:=FTests.Count;
  1020. end;
  1021. procedure TTestSuite.SetOwnsTests(AValue: Boolean);
  1022. begin
  1023. if FOwnsTests=AValue then Exit;
  1024. FOwnsTests:=AValue;
  1025. SetOwnTestOnTests(AValue);
  1026. end;
  1027. procedure TTestSuite.SetOwnTestOnTests(AValue: Boolean);
  1028. Var
  1029. I : Integer;
  1030. begin
  1031. For I:=0 to FTests.Count-1 do
  1032. TTestItem(FTests[i]).OwnsTest:=AValue;
  1033. end;
  1034. function TTestSuite.DoAddTest(ATest: TTest): Integer;
  1035. Var
  1036. I : TTestItem;
  1037. begin
  1038. I:=TTestItem.Create(ATest);
  1039. I.OwnsTest:=OwnsTests;
  1040. Result:=FTests.Add(I);
  1041. if ATest.TestSuiteName = '' then
  1042. ATest.TestSuiteName := Self.TestName;
  1043. ATest.EnableIgnores := Self.EnableIgnores;
  1044. end;
  1045. function TTestSuite.GetTestName: string;
  1046. begin
  1047. Result := FName;
  1048. end;
  1049. function TTestSuite.GetTestSuiteName: string;
  1050. begin
  1051. Result := FTestSuiteName;
  1052. end;
  1053. function TTestSuite.GetEnableIgnores: boolean;
  1054. begin
  1055. Result := FEnableIgnores;
  1056. end;
  1057. procedure TTestSuite.SetTestName(const Value: string);
  1058. begin
  1059. FName := Value;
  1060. end;
  1061. procedure TTestSuite.SetTestSuiteName(const aName: string);
  1062. begin
  1063. if FTestSuiteName <> aName then
  1064. FTestSuiteName := aName;
  1065. end;
  1066. procedure TTestSuite.SetEnableIgnores(Value: boolean);
  1067. var
  1068. i: integer;
  1069. begin
  1070. if FEnableIgnores <> Value then
  1071. begin
  1072. FEnableIgnores := Value;
  1073. for i := 0 to FTests.Count - 1 do
  1074. TTestItem(FTests[i]).Test.EnableIgnores := Value;
  1075. end
  1076. end;
  1077. function TTestSuite.CountTestCases: integer;
  1078. var
  1079. i: integer;
  1080. begin
  1081. Result := 0;
  1082. for i := 0 to FTests.Count - 1 do
  1083. begin
  1084. Result := Result + TTestItem(FTests[i]).Test.CountTestCases;
  1085. end;
  1086. end;
  1087. procedure TTestCase.ExpectException(const Msg: String;
  1088. AExceptionClass: TClass; AExceptionMessage: string = '';
  1089. AExceptionHelpContext: Integer =0 );
  1090. begin
  1091. FExpectedExceptionFailMessage:=Msg;
  1092. FExpectedException:=AExceptionClass;
  1093. FExpectedExceptionMessage:=AExceptionMessage;
  1094. FExpectedExceptionContext:=AExceptionHelpContext;
  1095. FExpectedExceptionCaller:=CallerAddr;
  1096. end;
  1097. procedure TTestCase.ExpectException(AExceptionClass: TClass;
  1098. AExceptionMessage: string = ''; AExceptionHelpContext: Integer = 0);
  1099. begin
  1100. FExpectedExceptionFailMessage:='';
  1101. FExpectedException:=AExceptionClass;
  1102. FExpectedExceptionMessage:=AExceptionMessage;
  1103. FExpectedExceptionContext:=AExceptionHelpContext;
  1104. FExpectedExceptionCaller:=CallerAddr;
  1105. end;
  1106. procedure TTestSuite.Run(AResult: TTestResult);
  1107. var
  1108. i: integer;
  1109. ti : TTestItem;
  1110. begin
  1111. if FTests.Count > 0 then
  1112. AResult.StartTestSuite(self);
  1113. for i := 0 to FTests.Count - 1 do
  1114. begin
  1115. ti:=TTestItem(FTests[i]);
  1116. if Ti.Test.InheritsFrom(TTestCase) and TTestCase(Ti.Test).SingleInstanceForSuite then
  1117. TTestCase(Ti.Test).SetTestName(Ti.TestName);
  1118. RunTest(TI.Test, AResult);
  1119. end;
  1120. if FTests.Count > 0 then
  1121. AResult.EndTestSuite(self);
  1122. end;
  1123. procedure TTestSuite.RunTest(ATest: TTest; AResult: TTestResult);
  1124. begin
  1125. ATest.Run(AResult);
  1126. end;
  1127. procedure TTestSuite.AddTest(ATest: TTest);
  1128. begin
  1129. DoAddTest(ATest);
  1130. end;
  1131. procedure TTestSuite.AddTestSuiteFromClass(ATestClass: TClass);
  1132. begin
  1133. AddTest(TTestSuite.Create(ATestClass));
  1134. end;
  1135. class function TTestSuite.Warning(const aMessage: string): TTestCase;
  1136. var
  1137. w: TTestWarning;
  1138. begin
  1139. w := TTestWarning.Create;
  1140. w.FMessage := aMessage;
  1141. Result := w;
  1142. end;
  1143. constructor TTestResult.Create;
  1144. begin
  1145. inherited Create;
  1146. FFailures := TFPList.Create;
  1147. FIgnoredTests := TFPList.Create;
  1148. FErrors := TFPList.Create;
  1149. FListeners := TFPList.Create;
  1150. FSkippedTests := TFPList.Create;
  1151. FStartingTime := Now;
  1152. end;
  1153. destructor TTestResult.Destroy;
  1154. begin
  1155. FreeObjects(FFailures);
  1156. FFailures.Free;
  1157. FreeObjects(FIgnoredTests);
  1158. FIgnoredTests.Free;
  1159. FreeObjects(FErrors);
  1160. FErrors.Free;
  1161. FListeners.Free;
  1162. FSkippedTests.Free;
  1163. end;
  1164. procedure TTestResult.ClearErrorLists;
  1165. begin
  1166. FreeObjects(FFailures);
  1167. FFailures.Clear;
  1168. FreeObjects(FIgnoredTests);
  1169. FIgnoredTests.Clear;
  1170. FreeObjects(FErrors);
  1171. FErrors.Clear;
  1172. end;
  1173. function TTestResult.GetNumErrors: integer;
  1174. begin
  1175. Result := FErrors.Count;
  1176. end;
  1177. function TTestResult.GetNumFailures: integer;
  1178. begin
  1179. Result := FFailures.Count;
  1180. end;
  1181. function TTestResult.GetNumIgnoredTests: integer;
  1182. begin
  1183. Result := FIgnoredTests.Count;
  1184. end;
  1185. function TTestResult.GetNumSkipped: integer;
  1186. begin
  1187. Result := FSkippedTests.Count;
  1188. end;
  1189. procedure TTestResult.AddListener(AListener: ITestListener);
  1190. begin
  1191. FListeners.Add(pointer(AListener));
  1192. end;
  1193. procedure TTestResult.RemoveListener(AListener: ITestListener);
  1194. begin
  1195. FListeners.Remove(pointer(AListener));
  1196. end;
  1197. procedure TTestResult.AddFailure(ATest: TTest; E: EAssertionFailedError; aFailureList: TFPList; AThrownExceptionAdrs: Pointer);
  1198. var
  1199. i: integer;
  1200. f: TTestFailure;
  1201. begin
  1202. //lock mutex
  1203. f := TTestFailure.CreateFailure(ATest, E, ATest.LastStep, AThrownExceptionAdrs);
  1204. aFailureList.Add(f);
  1205. for i := 0 to FListeners.Count - 1 do
  1206. ITestListener(FListeners[i]).AddFailure(ATest, f);
  1207. //unlock mutex
  1208. end;
  1209. procedure TTestResult.AddError(ATest: TTest; E: Exception; AThrownExceptionAdrs: Pointer);
  1210. var
  1211. i: integer;
  1212. f: TTestFailure;
  1213. begin
  1214. //lock mutex
  1215. f := TTestFailure.CreateFailure(ATest, E, ATest.LastStep, AThrownExceptionAdrs);
  1216. FErrors.Add(f);
  1217. for i := 0 to FListeners.Count - 1 do
  1218. ITestListener(FListeners[i]).AddError(ATest, f);
  1219. //unlock mutex
  1220. end;
  1221. procedure TTestResult.EndTest(ATest: TTest);
  1222. var
  1223. i: integer;
  1224. begin
  1225. for i := 0 to FListeners.Count - 1 do
  1226. ITestListener(FListeners[i]).EndTest(ATest);
  1227. end;
  1228. procedure ProtectTest(aTest: TTest; aResult: TTestResult);
  1229. begin
  1230. TTestCase(aTest).RunBare;
  1231. end;
  1232. procedure TTestResult.Run(ATestCase: TTestCase);
  1233. begin
  1234. if not SkipTest(ATestCase) then
  1235. begin
  1236. StartTest(ATestCase);
  1237. RunProtected(ATestCase, @ProtectTest);
  1238. EndTest(ATestCase);
  1239. end;
  1240. end;
  1241. procedure TTestResult.RunProtected(ATestCase: TTest; protect: TProtect);
  1242. begin
  1243. try
  1244. protect(ATestCase, Self);
  1245. except
  1246. on E: EIgnoredTest do
  1247. AddFailure(ATestCase, E, FIgnoredTests, ExceptAddr);
  1248. on E: EAssertionFailedError do
  1249. AddFailure(ATestCase, E, FFailures, ExceptAddr);
  1250. on E: Exception do
  1251. begin
  1252. AddError(ATestCase, E, ExceptAddr);
  1253. end;
  1254. end;
  1255. end;
  1256. procedure TTestResult.StartTest(ATest: TTest);
  1257. var
  1258. count: integer;
  1259. i: integer;
  1260. begin
  1261. count := ATest.CountTestCases;
  1262. //lock mutex
  1263. FRunTests := FRunTests + count;
  1264. for i := 0 to FListeners.Count - 1 do
  1265. ITestListener(FListeners[i]).StartTest(ATest);
  1266. //unlock mutex
  1267. end;
  1268. function TTestResult.WasSuccessful: boolean;
  1269. begin
  1270. //lock mutex
  1271. Result := (FErrors.Count = 0) and (FFailures.Count = 0);
  1272. //unlock mutex
  1273. end;
  1274. function TTestResult.SkipTest(ATestCase: TTestCase): boolean;
  1275. var
  1276. i: integer;
  1277. begin
  1278. Result := false;
  1279. if FSkippedTests.Count = 0 then
  1280. begin
  1281. result := false;
  1282. Exit;
  1283. end
  1284. else
  1285. for i := 0 to FSkippedTests.Count - 1 do
  1286. begin
  1287. if PtrUInt(FSkippedTests[i]) = PtrUInt(ATestCase) then
  1288. begin
  1289. Result := true;
  1290. Exit;
  1291. end;
  1292. end;
  1293. end;
  1294. procedure TTestResult.AddToSkipList(ATestCase: TTestCase);
  1295. begin
  1296. FSkippedTests.Add(ATestCase);
  1297. end;
  1298. procedure TTestResult.RemoveFromSkipList(ATestCase: TTestCase);
  1299. begin
  1300. FSkippedTests.Remove(ATestCase);
  1301. end;
  1302. procedure TTestResult.StartTestSuite(ATestSuite: TTestSuite);
  1303. var
  1304. i: integer;
  1305. begin
  1306. for i := 0 to FListeners.Count - 1 do
  1307. ITestListener(FListeners[i]).StartTestSuite(ATestSuite);
  1308. end;
  1309. procedure TTestResult.EndTestSuite(ATestSuite: TTestSuite);
  1310. var
  1311. i: integer;
  1312. begin
  1313. for i := 0 to FListeners.Count - 1 do
  1314. ITestListener(FListeners[i]).EndTestSuite(ATestSuite);
  1315. end;
  1316. initialization
  1317. TTestCase.CheckAssertCalled:=False;
  1318. end.