fpcunit.pp 31 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280
  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. {$IFNDEF MORPHOS}
  16. {$DEFINE SHOWLINEINFO}
  17. {$ENDIF}
  18. { Uncomment this define to remove the DUnit compatibility interface. }
  19. {$DEFINE DUnit}
  20. uses
  21. {$ifdef SHOWLINEINFO}
  22. LineInfo,
  23. {$endif}
  24. SysUtils
  25. ,Classes
  26. ;
  27. { This lets us use a single include file for both the Interface and
  28. Implementation sections. }
  29. {$define read_interface}
  30. {$undef read_implementation}
  31. type
  32. EAssertionFailedError = class(Exception)
  33. constructor Create; overload;
  34. constructor Create(const msg :string); overload;
  35. end;
  36. EIgnoredTest = class(EAssertionFailedError);
  37. TTestStep = (stSetUp, stRunTest, stTearDown, stNothing);
  38. TRunMethod = procedure of object;
  39. TTestResult = class;
  40. TTestSuite = class;
  41. {$M+}
  42. TTest = class(TObject)
  43. protected
  44. FLastStep: TTestStep;
  45. function GetTestName: string; virtual;
  46. function GetTestSuiteName: string; virtual;
  47. function GetEnableIgnores: boolean; virtual;
  48. procedure SetTestSuiteName(const aName: string); virtual; abstract;
  49. procedure SetEnableIgnores(Value: boolean); virtual; abstract;
  50. public
  51. function CountTestCases: integer; virtual;
  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. public
  64. class procedure Fail(const AMessage: string);
  65. class procedure AssertTrue(const AMessage: string; ACondition: boolean); overload;
  66. class procedure AssertTrue(ACondition: boolean); overload;
  67. class procedure AssertFalse(const AMessage: string; ACondition: boolean); overload;
  68. class procedure AssertFalse(ACondition: boolean); overload;
  69. class procedure AssertEquals(const AMessage: string; Expected, Actual: string); overload;
  70. class procedure AssertEquals(Expected, Actual: string); overload;
  71. class procedure AssertEquals(const AMessage: string; Expected, Actual: integer); overload;
  72. class procedure AssertEquals(Expected, Actual: integer); overload;
  73. class procedure AssertEquals(const AMessage: string; Expected, Actual: int64); overload;
  74. class procedure AssertEquals(Expected, Actual: int64); overload;
  75. class procedure AssertEquals(const AMessage: string; Expected, Actual: currency); overload;
  76. class procedure AssertEquals(Expected, Actual: currency); overload;
  77. class procedure AssertEquals(const AMessage: string; Expected, Actual, Delta: double); overload;
  78. class procedure AssertEquals(Expected, Actual, Delta: double); overload;
  79. class procedure AssertEquals(const AMessage: string; Expected, Actual: boolean); overload;
  80. class procedure AssertEquals(Expected, Actual: boolean); overload;
  81. class procedure AssertEquals(const AMessage: string; Expected, Actual: char); overload;
  82. class procedure AssertEquals(Expected, Actual: char); overload;
  83. class procedure AssertEquals(const AMessage: string; Expected, Actual: TClass); overload;
  84. class procedure AssertEquals(Expected, Actual: TClass); overload;
  85. class procedure AssertSame(const AMessage: string; Expected, Actual: TObject); overload;
  86. class procedure AssertSame(Expected, Actual: TObject); overload;
  87. class procedure AssertSame(const AMessage: string; Expected, Actual: Pointer); overload;
  88. class procedure AssertSame(Expected, Actual: Pointer); overload;
  89. class procedure AssertNotSame(const AMessage: string; Expected, Actual: TObject); overload;
  90. class procedure AssertNotSame(Expected, Actual: TObject); overload;
  91. class procedure AssertNotSame(const AMessage: string; Expected, Actual: Pointer); overload;
  92. class procedure AssertNotSame(Expected, Actual: Pointer); overload;
  93. class procedure AssertNotNull(const AMessage: string; AObject: TObject); overload;
  94. class procedure AssertNotNull(AObject: TObject); overload;
  95. class procedure AssertNotNullIntf(const AMessage: string; AInterface: IInterface); overload;
  96. class procedure AssertNotNullIntf(AInterface: IInterface); overload;
  97. class procedure AssertNotNull(const AMessage: string; APointer: Pointer); overload;
  98. class procedure AssertNotNull(APointer: Pointer); overload;
  99. class procedure AssertNull(const AMessage: string; AObject: TObject); overload;
  100. class procedure AssertNull(AObject: TObject); overload;
  101. class procedure AssertNullIntf(const AMessage: string; AInterface: IInterface); overload;
  102. class procedure AssertNullIntf(AInterface: IInterface); overload;
  103. class procedure AssertNull(const AMessage: string; APointer: Pointer); overload;
  104. class procedure AssertNull(APointer: Pointer); overload;
  105. class procedure AssertNotNull(const AMessage, AString: string); overload;
  106. class procedure AssertNotNull(const AString: string); overload;
  107. class procedure AssertException(const AMessage: string; AExceptionClass: ExceptClass; AMethod: TRunMethod); overload;
  108. class procedure AssertException(AExceptionClass: ExceptClass; AMethod: TRunMethod); overload;
  109. {$IFDEF DUnit}
  110. {$I DUnitCompatibleInterface.inc}
  111. {$ENDIF DUnit}
  112. end;
  113. TTestFailure = class(TObject)
  114. private
  115. FTestName: string;
  116. FTestSuiteName: string;
  117. FLineNumber: longint;
  118. FFailedMethodName: string;
  119. FRaisedExceptionClass: TClass;
  120. FRaisedExceptionMessage: string;
  121. FSourceUnitName: string;
  122. FTestLastStep: TTestStep;
  123. function GetAsString: string;
  124. function GetExceptionMessage: string;
  125. function GetIsFailure: boolean;
  126. function GetIsIgnoredTest: boolean;
  127. function GetExceptionClassName: string;
  128. procedure SetTestLastStep(const Value: TTestStep);
  129. public
  130. constructor CreateFailure(ATest: TTest; E: Exception; LastStep: TTestStep);
  131. property ExceptionClass: TClass read FRaisedExceptionClass;
  132. published
  133. property AsString: string read GetAsString;
  134. property IsFailure: boolean read GetIsFailure;
  135. property IsIgnoredTest: boolean read GetIsIgnoredTest;
  136. property ExceptionMessage: string read GetExceptionMessage;
  137. property ExceptionClassName: string read GetExceptionClassName;
  138. property SourceUnitName: string read FSourceUnitName write FSourceUnitName;
  139. property LineNumber: longint read FLineNumber write FLineNumber;
  140. property FailedMethodName: string read FFailedMethodName write FFailedMethodName;
  141. property TestLastStep: TTestStep read FTestLastStep write SetTestLastStep;
  142. end;
  143. ITestListener = interface
  144. ['{0CE9D3AE-882A-D811-9401-ADEB5E4C7FC1}']
  145. procedure AddFailure(ATest: TTest; AFailure: TTestFailure);
  146. procedure AddError(ATest: TTest; AError: TTestFailure);
  147. procedure StartTest(ATest: TTest);
  148. procedure EndTest(ATest: TTest);
  149. procedure StartTestSuite(ATestSuite: TTestSuite);
  150. procedure EndTestSuite(ATestSuite: TTestSuite);
  151. end;
  152. TTestCase = class(TAssert)
  153. private
  154. FName: string;
  155. FTestSuiteName: string;
  156. FEnableIgnores: boolean;
  157. protected
  158. function CreateResult: TTestResult; virtual;
  159. procedure SetUp; virtual;
  160. procedure TearDown; virtual;
  161. procedure RunTest; virtual;
  162. function GetTestName: string; override;
  163. function GetTestSuiteName: string; override;
  164. function GetEnableIgnores: boolean; override;
  165. procedure SetTestSuiteName(const aName: string); override;
  166. procedure SetTestName(const Value: string); virtual;
  167. procedure SetEnableIgnores(Value: boolean); override;
  168. procedure RunBare; virtual;
  169. public
  170. constructor Create; virtual;
  171. constructor CreateWith(const ATestName: string; const ATestSuiteName: string); virtual;
  172. constructor CreateWithName(const AName: string); virtual;
  173. function CountTestCases: integer; override;
  174. function CreateResultAndRun: TTestResult; virtual;
  175. procedure Run(AResult: TTestResult); override;
  176. function AsString: string;
  177. property TestSuiteName: string read GetTestSuiteName write SetTestSuiteName;
  178. published
  179. property TestName: string read GetTestName write SetTestName;
  180. end;
  181. TTestCaseClass = class of TTestCase;
  182. TTestSuite = class(TTest)
  183. private
  184. FTests: TFPList;
  185. FName: string;
  186. FTestSuiteName: string;
  187. FEnableIgnores: boolean;
  188. function GetTest(Index: integer): TTest;
  189. protected
  190. function GetTestName: string; override;
  191. function GetTestSuiteName: string; override;
  192. function GetEnableIgnores: boolean; override;
  193. procedure SetTestSuiteName(const aName: string); override;
  194. procedure SetTestName(const Value: string); virtual;
  195. procedure SetEnableIgnores(Value: boolean); override;
  196. public
  197. constructor Create(AClass: TClass; AName: string); reintroduce; overload; virtual;
  198. constructor Create(AClass: TClass); reintroduce; overload; virtual;
  199. constructor Create(AClassArray: Array of TClass); reintroduce; overload; virtual;
  200. constructor Create(AName: string); reintroduce; overload; virtual;
  201. constructor Create; reintroduce; overload; virtual;
  202. destructor Destroy; override;
  203. function CountTestCases: integer; override;
  204. procedure Run(AResult: TTestResult); override;
  205. procedure RunTest(ATest: TTest; AResult: TTestResult); virtual;
  206. procedure AddTest(ATest: TTest); overload; virtual;
  207. procedure AddTestSuiteFromClass(ATestClass: TClass); virtual;
  208. class function Warning(const aMessage: string): TTestCase;
  209. property Test[Index: integer]: TTest read GetTest; default;
  210. property TestSuiteName: string read GetTestSuiteName write SetTestSuiteName;
  211. property TestName: string read GetTestName write SetTestName;
  212. property Tests: TFPList read FTests;
  213. end;
  214. TProtect = procedure(aTest: TTest; aResult: TTestResult);
  215. { TTestResult }
  216. TTestResult = class(TObject)
  217. protected
  218. FRunTests: integer;
  219. FFailures: TFPList;
  220. FIgnoredTests: TFPList;
  221. FErrors: TFPList;
  222. FListeners: TFPList;
  223. FSkippedTests: TFPList;
  224. FStartingTime: TDateTime;
  225. function GetNumErrors: integer;
  226. function GetNumFailures: integer;
  227. function GetNumIgnoredTests: integer;
  228. function GetNumSkipped: integer;
  229. public
  230. constructor Create; virtual;
  231. destructor Destroy; override;
  232. procedure ClearErrorLists;
  233. procedure StartTest(ATest: TTest);
  234. procedure AddFailure(ATest: TTest; E: EAssertionFailedError; aFailureList: TFPList);
  235. procedure AddError(ATest: TTest; E: Exception; AUnitName: string;
  236. AFailedMethodName: string; ALineNumber: longint);
  237. procedure EndTest(ATest: TTest);
  238. procedure AddListener(AListener: ITestListener);
  239. procedure RemoveListener(AListener: ITestListener);
  240. procedure Run(ATestCase: TTestCase);
  241. procedure RunProtected(ATestCase: TTest; protect: TProtect);
  242. function WasSuccessful: boolean;
  243. function SkipTest(ATestCase: TTestCase): boolean;
  244. procedure AddToSkipList(ATestCase: TTestCase);
  245. procedure RemoveFromSkipList(ATestCase: TTestCase);
  246. procedure StartTestSuite(ATestSuite: TTestSuite);
  247. procedure EndTestSuite(ATestSuite: TTestSuite);
  248. published
  249. property Listeners: TFPList read FListeners;
  250. property Failures: TFPList read FFailures;
  251. property IgnoredTests: TFPList read FIgnoredTests;
  252. property Errors: TFPList read FErrors;
  253. property RunTests: integer read FRunTests;
  254. property NumberOfErrors: integer read GetNumErrors;
  255. property NumberOfFailures: integer read GetNumFailures;
  256. property NumberOfIgnoredTests: integer read GetNumIgnoredTests;
  257. property NumberOfSkippedTests: integer read GetNumSkipped;
  258. property StartingTime: TDateTime read FStartingTime;
  259. end;
  260. function ComparisonMsg(const aExpected: string; const aActual: string): string;
  261. Resourcestring
  262. SCompare = ' expected: <%s> but was: <%s>';
  263. SExpectedNotSame = 'expected not same';
  264. SExceptionCompare = 'Exception %s expected but %s was raised';
  265. SMethodNotFound = 'Method <%s> not found';
  266. SNoValidInheritance = ' does not inherit from TTestCase';
  267. SNoValidTests = 'No valid tests found in ';
  268. implementation
  269. uses
  270. testutils;
  271. { This lets us use a single include file for both the Interface and
  272. Implementation sections. }
  273. {$undef read_interface}
  274. {$define read_implementation}
  275. type
  276. TTestWarning = class(TTestCase)
  277. private
  278. FMessage: String;
  279. protected
  280. procedure RunTest; override;
  281. end;
  282. procedure TTestWarning.RunTest;
  283. begin
  284. Fail(FMessage);
  285. end;
  286. function ComparisonMsg(const aExpected: string; const aActual: string): string;
  287. begin
  288. Result := format(SCompare, [aExpected, aActual]);
  289. end;
  290. constructor EAssertionFailedError.Create;
  291. begin
  292. inherited Create('');
  293. end;
  294. constructor EAssertionFailedError.Create(const msg: string);
  295. begin
  296. inherited Create(msg);
  297. end;
  298. constructor TTestFailure.CreateFailure(ATest: TTest; E: Exception; LastStep: TTestStep);
  299. begin
  300. inherited Create;
  301. FTestName := ATest.GetTestName;
  302. FTestSuiteName := ATest.GetTestSuiteName;
  303. FRaisedExceptionClass := E.ClassType;
  304. FRaisedExceptionMessage := E.Message;
  305. FTestLastStep := LastStep;
  306. end;
  307. function TTestFailure.GetAsString: string;
  308. var
  309. s: string;
  310. begin
  311. if FTestSuiteName <> '' then
  312. s := FTestSuiteName + '.'
  313. else
  314. s := '';
  315. Result := s + FTestName + ': ' + FRaisedExceptionMessage;
  316. end;
  317. function TTestFailure.GetExceptionClassName: string;
  318. begin
  319. Result := FRaisedExceptionClass.ClassName;
  320. end;
  321. function TTestFailure.GetExceptionMessage: string;
  322. begin
  323. Result := FRaisedExceptionMessage;
  324. if TestLastStep = stSetUp then
  325. Result := '[SETUP] ' + Result
  326. else if TestLastStep = stTearDown then
  327. Result := '[TEARDOWN] ' + Result;
  328. end;
  329. function TTestFailure.GetIsFailure: boolean;
  330. begin
  331. Result := FRaisedExceptionClass.InheritsFrom(EAssertionFailedError);
  332. end;
  333. function TTestFailure.GetIsIgnoredTest: boolean;
  334. begin
  335. Result := FRaisedExceptionClass.InheritsFrom(EIgnoredTest);
  336. end;
  337. procedure TTestFailure.SetTestLastStep(const Value: TTestStep);
  338. begin
  339. FTestLastStep := Value;
  340. end;
  341. { TTest}
  342. function TTest.GetTestName: string;
  343. begin
  344. Result := 'TTest';
  345. end;
  346. function TTest.GetTestSuiteName: string;
  347. begin
  348. Result := 'TTest';
  349. end;
  350. function TTest.CountTestCases: integer;
  351. begin
  352. Result := 0;
  353. end;
  354. function TTest.GetEnableIgnores: boolean;
  355. begin
  356. Result := True;
  357. end;
  358. procedure TTest.Run(AResult: TTestResult);
  359. begin
  360. { do nothing }
  361. end;
  362. procedure TTest.Ignore(const AMessage: String);
  363. begin
  364. if EnableIgnores then raise EIgnoredTest.Create(AMessage);
  365. end;
  366. { TAssert }
  367. class procedure TAssert.Fail(const AMessage: String);
  368. begin
  369. raise EAssertionFailedError.Create(AMessage);
  370. end;
  371. class procedure TAssert.AssertTrue(const AMessage: String; ACondition: Boolean);
  372. begin
  373. if (not ACondition) then
  374. Fail(AMessage);
  375. end;
  376. class procedure TAssert.AssertTrue(ACondition: Boolean);
  377. begin
  378. AssertTrue('', ACondition);
  379. end;
  380. class procedure TAssert.AssertFalse(const AMessage: String; ACondition: Boolean);
  381. begin
  382. AssertTrue(AMessage, not ACondition);
  383. end;
  384. class procedure TAssert.AssertFalse(ACondition: Boolean);
  385. begin
  386. AssertFalse('', ACondition);
  387. end;
  388. class procedure TAssert.AssertEquals(const AMessage: string; Expected, Actual: string);
  389. begin
  390. AssertTrue(AMessage + ComparisonMsg(Expected, Actual), AnsiCompareStr(Expected, Actual) = 0);
  391. end;
  392. class procedure TAssert.AssertEquals(Expected, Actual: string);
  393. begin
  394. AssertEquals('', Expected, Actual);
  395. end;
  396. class procedure TAssert.AssertNotNull(const AString: string);
  397. begin
  398. AssertNotNull('', AString);
  399. end;
  400. class procedure TAssert.AssertEquals(const AMessage: string; Expected, Actual: integer);
  401. begin
  402. AssertTrue(AMessage + ComparisonMsg(IntToStr(Expected), IntToStr(Actual)), Expected = Actual);
  403. end;
  404. class procedure TAssert.AssertEquals(Expected, Actual: integer);
  405. begin
  406. AssertEquals('', Expected, Actual);
  407. end;
  408. class procedure TAssert.AssertEquals(const AMessage: string; Expected, Actual: int64);
  409. begin
  410. AssertTrue(AMessage + ComparisonMsg(IntToStr(Expected), IntToStr(Actual)), Expected = Actual);
  411. end;
  412. class procedure TAssert.AssertEquals(Expected, Actual: int64);
  413. begin
  414. AssertEquals('', Expected, Actual);
  415. end;
  416. class procedure TAssert.AssertEquals(const AMessage: string; Expected, Actual: currency);
  417. begin
  418. AssertTrue(AMessage + ComparisonMsg(FloatToStr(Expected), FloatToStr(Actual)), Expected = Actual);
  419. end;
  420. class procedure TAssert.AssertEquals(Expected, Actual: currency);
  421. begin
  422. AssertEquals('', Expected, Actual);
  423. end;
  424. class procedure TAssert.AssertEquals(const AMessage: string; Expected, Actual, Delta: double);
  425. begin
  426. AssertTrue(AMessage + ComparisonMsg(FloatToStr(Expected),FloatToStr(Actual)),
  427. (Abs(Expected - Actual) <= Delta));
  428. end;
  429. class procedure TAssert.AssertEquals(Expected, Actual, Delta: double);
  430. begin
  431. AssertEquals('', Expected, Actual, Delta);
  432. end;
  433. class procedure TAssert.AssertNotNull(const AMessage, AString: string);
  434. begin
  435. AssertTrue(AMessage, AString <> '');
  436. end;
  437. class procedure TAssert.AssertEquals(const AMessage: string; Expected, Actual: boolean);
  438. begin
  439. AssertTrue(AMessage + ComparisonMsg(BoolToStr(Expected), BoolToStr(Actual)), Expected = Actual);
  440. end;
  441. class procedure TAssert.AssertEquals(Expected, Actual: boolean);
  442. begin
  443. AssertEquals('', Expected, Actual);
  444. end;
  445. class procedure TAssert.AssertEquals(const AMessage: string; Expected, Actual: char);
  446. begin
  447. AssertTrue(AMessage + ComparisonMsg(Expected, Actual), Expected = Actual);
  448. end;
  449. class procedure TAssert.AssertEquals(Expected, Actual: char);
  450. begin
  451. AssertEquals('', Expected, Actual);
  452. end;
  453. class procedure TAssert.AssertEquals(const AMessage: string; Expected, Actual: TClass);
  454. begin
  455. AssertTrue(AMessage + ComparisonMsg(Expected.ClassName, Actual.ClassName), Expected = Actual);
  456. end;
  457. class procedure TAssert.AssertEquals(Expected, Actual: TClass);
  458. begin
  459. AssertEquals('', Expected, Actual);
  460. end;
  461. class procedure TAssert.AssertSame(const AMessage: string; Expected, Actual: TObject);
  462. begin
  463. AssertTrue(AMessage + ComparisonMsg(IntToStr(PtrInt(Expected)), IntToStr(PtrInt(Actual))),
  464. Expected = Actual);
  465. end;
  466. class procedure TAssert.AssertSame(Expected, Actual: TObject);
  467. begin
  468. AssertSame('', Expected, Actual);
  469. end;
  470. class procedure TAssert.AssertSame(const AMessage: string; Expected, Actual: Pointer);
  471. begin
  472. AssertTrue(AMessage + ComparisonMsg(IntToStr(PtrInt(Expected)), IntToStr(PtrInt(Actual))),
  473. Expected = Actual);
  474. end;
  475. class procedure TAssert.AssertSame(Expected, Actual: Pointer);
  476. begin
  477. AssertSame('', Expected, Actual);
  478. end;
  479. class procedure TAssert.AssertNotSame(const AMessage: string; Expected, Actual: TObject);
  480. begin
  481. AssertFalse(SExpectedNotSame, Expected = Actual);
  482. end;
  483. class procedure TAssert.AssertNotSame(Expected, Actual: TObject);
  484. begin
  485. AssertNotSame('', Expected, Actual);
  486. end;
  487. class procedure TAssert.AssertNotSame(const AMessage: string; Expected, Actual: Pointer);
  488. begin
  489. AssertFalse(SExpectedNotSame, Expected = Actual);
  490. end;
  491. class procedure TAssert.AssertNotSame(Expected, Actual: Pointer);
  492. begin
  493. AssertNotSame('', Expected, Actual);
  494. end;
  495. class procedure TAssert.AssertNotNull(const AMessage: string; AObject: TObject);
  496. begin
  497. AssertTrue(AMessage, (AObject <> nil));
  498. end;
  499. class procedure TAssert.AssertNotNull(AObject: TObject);
  500. begin
  501. AssertNotNull('', AObject);
  502. end;
  503. class procedure TAssert.AssertNotNullIntf(const AMessage: string; AInterface: IInterface);
  504. begin
  505. AssertTrue(AMessage, (AInterface <> nil));
  506. end;
  507. class procedure TAssert.AssertNotNullIntf(AInterface: IInterface);
  508. begin
  509. AssertNotNull('', AInterface);
  510. end;
  511. class procedure TAssert.AssertNotNull(const AMessage: string; APointer: Pointer);
  512. begin
  513. AssertTrue(AMessage, (APointer <> nil));
  514. end;
  515. class procedure TAssert.AssertNotNull(APointer: Pointer);
  516. begin
  517. AssertNotNull('', APointer);
  518. end;
  519. class procedure TAssert.AssertNull(const AMessage: string; AObject: TObject);
  520. begin
  521. AssertTrue(AMessage, (AObject = nil));
  522. end;
  523. class procedure TAssert.AssertNull(AObject: TObject);
  524. begin
  525. AssertNull('', AObject);
  526. end;
  527. class procedure TAssert.AssertNullIntf(const AMessage: string; AInterface: IInterface);
  528. begin
  529. AssertTrue(AMessage, (AInterface = nil));
  530. end;
  531. class procedure TAssert.AssertNullINtf(AInterface: IInterface);
  532. begin
  533. AssertNull('', AInterface);
  534. end;
  535. class procedure TAssert.AssertNull(const AMessage: string; APointer: Pointer);
  536. begin
  537. AssertTrue(AMessage, (APointer = nil));
  538. end;
  539. class procedure TAssert.AssertNull(APointer: Pointer);
  540. begin
  541. AssertNull('', APointer);
  542. end;
  543. class procedure TAssert.AssertException(const AMessage: string; AExceptionClass: ExceptClass;
  544. AMethod: TRunMethod);
  545. var
  546. Passed : Boolean;
  547. ExceptionName: string;
  548. begin
  549. Passed := False;
  550. try
  551. AMethod;
  552. except
  553. on E: Exception do
  554. begin
  555. ExceptionName := E.ClassName;
  556. if E.ClassType.InheritsFrom(AExceptionClass) then
  557. begin
  558. Passed := AExceptionClass.ClassName = E.ClassName;
  559. end;
  560. end;
  561. end;
  562. AssertTrue(Format(SExceptionCompare, [AExceptionClass.ClassName, ExceptionName])+ ': ' + AMessage, Passed);
  563. end;
  564. class procedure TAssert.AssertException(AExceptionClass: ExceptClass;
  565. AMethod: TRunMethod);
  566. begin
  567. AssertException('', AExceptionClass, AMethod);
  568. end;
  569. { DUnit compatibility interface }
  570. {$IFDEF DUnit}
  571. {$I DUnitCompatibleInterface.inc}
  572. {$ENDIF DUnit}
  573. constructor TTestCase.Create;
  574. begin
  575. inherited Create;
  576. FEnableIgnores := True;
  577. end;
  578. constructor TTestCase.CreateWithName(const AName: string);
  579. begin
  580. Create;
  581. FName := AName;
  582. end;
  583. constructor TTestCase.CreateWith(const ATestName: string; const ATestSuiteName: string);
  584. begin
  585. Create;
  586. FName := ATestName;
  587. FTestSuiteName := ATestSuiteName;
  588. end;
  589. function TTestCase.AsString: string;
  590. begin
  591. Result := TestName + '(' + ClassName + ')';
  592. end;
  593. function TTestCase.CountTestCases: integer;
  594. begin
  595. Result := 1;
  596. end;
  597. function TTestCase.CreateResult: TTestResult;
  598. begin
  599. Result := TTestResult.Create;
  600. end;
  601. function TTestCase.GetTestName: string;
  602. begin
  603. Result := FName;
  604. end;
  605. function TTestCase.GetEnableIgnores: boolean;
  606. begin
  607. Result := FEnableIgnores;
  608. end;
  609. function TTestCase.GetTestSuiteName: string;
  610. begin
  611. Result := FTestSuiteName;
  612. end;
  613. procedure TTestCase.SetTestSuiteName(const aName: string);
  614. begin
  615. if FTestSuiteName <> aName then
  616. FTestSuiteName := aName;
  617. end;
  618. procedure TTestCase.SetTestName(const Value: string);
  619. begin
  620. FName := Value;
  621. end;
  622. procedure TTestCase.SetEnableIgnores(Value: boolean);
  623. begin
  624. FEnableIgnores := Value;
  625. end;
  626. function TTestCase.CreateResultAndRun: TTestResult;
  627. begin
  628. Result := CreateResult;
  629. Run(Result);
  630. end;
  631. procedure TTestCase.Run(AResult: TTestResult);
  632. begin
  633. (AResult).Run(Self);
  634. end;
  635. procedure TTestCase.RunBare;
  636. begin
  637. FLastStep := stSetUp;
  638. SetUp;
  639. try
  640. FLastStep := stRunTest;
  641. RunTest;
  642. FLastStep := stTearDown;
  643. finally
  644. TearDown;
  645. end;
  646. FLastStep := stNothing;
  647. end;
  648. procedure TTestCase.RunTest;
  649. var
  650. m: TMethod;
  651. RunMethod: TRunMethod;
  652. pMethod : Pointer;
  653. begin
  654. AssertNotNull('name of the test not assigned', FName);
  655. pMethod := Self.MethodAddress(FName);
  656. if (Assigned(pMethod)) then
  657. begin
  658. m.Code := pMethod;
  659. m.Data := self;
  660. RunMethod := TRunMethod(m);
  661. RunMethod;
  662. end
  663. else
  664. begin
  665. Fail(format(SMethodNotFound, [FName]));
  666. end;
  667. end;
  668. procedure TTestCase.SetUp;
  669. begin
  670. { do nothing }
  671. end;
  672. procedure TTestCase.TearDown;
  673. begin
  674. { do nothing }
  675. end;
  676. constructor TTestSuite.Create(AClass: TClass; AName: string);
  677. begin
  678. Create(AClass);
  679. FName := AName;
  680. end;
  681. constructor TTestSuite.Create(AClass: TClass);
  682. var
  683. ml: TStringList;
  684. i: integer;
  685. tc: TTestCaseClass;
  686. begin
  687. Create(AClass.ClassName);
  688. if AClass.InheritsFrom(TTestCase) then
  689. begin
  690. tc := TTestCaseClass(AClass);
  691. ml := TStringList.Create;
  692. try
  693. GetMethodList(AClass, ml);
  694. for i := 0 to ml.Count -1 do
  695. begin
  696. AddTest(tc.CreateWith(ml.Strings[i], tc.ClassName));
  697. end;
  698. finally
  699. ml.Free;
  700. end;
  701. end
  702. else
  703. AddTest(Warning(AClass.ClassName + SNoValidInheritance));
  704. if FTests.Count = 0 then
  705. AddTest(Warning(SNoValidTests + AClass.ClassName));
  706. end;
  707. constructor TTestSuite.Create(AClassArray: Array of TClass);
  708. var
  709. i: integer;
  710. begin
  711. Create;
  712. for i := Low(AClassArray) to High(AClassArray) do
  713. if Assigned(AClassArray[i]) then
  714. AddTest(TTestSuite.Create(AClassArray[i]));
  715. end;
  716. constructor TTestSuite.Create(AName: string);
  717. begin
  718. Create();
  719. FName := AName;
  720. end;
  721. constructor TTestSuite.Create;
  722. begin
  723. inherited Create;
  724. FTests := TFPList.Create;
  725. FEnableIgnores := True;
  726. end;
  727. destructor TTestSuite.Destroy;
  728. begin
  729. FreeObjects(FTests);
  730. FTests.Free;
  731. inherited Destroy;
  732. end;
  733. function TTestSuite.GetTest(Index: integer): TTest;
  734. begin
  735. Result := TTest(FTests[Index]);
  736. end;
  737. function TTestSuite.GetTestName: string;
  738. begin
  739. Result := FName;
  740. end;
  741. function TTestSuite.GetTestSuiteName: string;
  742. begin
  743. Result := FTestSuiteName;
  744. end;
  745. function TTestSuite.GetEnableIgnores: boolean;
  746. begin
  747. Result := FEnableIgnores;
  748. end;
  749. procedure TTestSuite.SetTestName(const Value: string);
  750. begin
  751. FName := Value;
  752. end;
  753. procedure TTestSuite.SetTestSuiteName(const aName: string);
  754. begin
  755. if FTestSuiteName <> aName then
  756. FTestSuiteName := aName;
  757. end;
  758. procedure TTestSuite.SetEnableIgnores(Value: boolean);
  759. var
  760. i: integer;
  761. begin
  762. if FEnableIgnores <> Value then
  763. begin
  764. FEnableIgnores := Value;
  765. for i := 0 to FTests.Count - 1 do
  766. TTest(FTests[i]).EnableIgnores := Value;
  767. end
  768. end;
  769. function TTestSuite.CountTestCases: integer;
  770. var
  771. i: integer;
  772. begin
  773. Result := 0;
  774. for i := 0 to FTests.Count - 1 do
  775. begin
  776. Result := Result + TTest(FTests[i]).CountTestCases;
  777. end;
  778. end;
  779. procedure TTestSuite.Run(AResult: TTestResult);
  780. var
  781. i: integer;
  782. begin
  783. if FTests.Count > 0 then
  784. AResult.StartTestSuite(self);
  785. for i := 0 to FTests.Count - 1 do
  786. RunTest(TTest(FTests[i]), AResult);
  787. if FTests.Count > 0 then
  788. AResult.EndTestSuite(self);
  789. end;
  790. procedure TTestSuite.RunTest(ATest: TTest; AResult: TTestResult);
  791. begin
  792. ATest.Run(AResult);
  793. end;
  794. procedure TTestSuite.AddTest(ATest: TTest);
  795. begin
  796. FTests.Add(ATest);
  797. if ATest.TestSuiteName = '' then
  798. ATest.TestSuiteName := Self.TestName;
  799. end;
  800. procedure TTestSuite.AddTestSuiteFromClass(ATestClass: TClass);
  801. begin
  802. AddTest(TTestSuite.Create(ATestClass));
  803. end;
  804. class function TTestSuite.Warning(const aMessage: string): TTestCase;
  805. var
  806. w: TTestWarning;
  807. begin
  808. w := TTestWarning.Create;
  809. w.FMessage := aMessage;
  810. Result := w;
  811. end;
  812. constructor TTestResult.Create;
  813. begin
  814. inherited Create;
  815. FFailures := TFPList.Create;
  816. FIgnoredTests := TFPList.Create;
  817. FErrors := TFPList.Create;
  818. FListeners := TFPList.Create;
  819. FSkippedTests := TFPList.Create;
  820. FStartingTime := Now;
  821. end;
  822. destructor TTestResult.Destroy;
  823. begin
  824. FreeObjects(FFailures);
  825. FFailures.Free;
  826. FreeObjects(FIgnoredTests);
  827. FIgnoredTests.Free;
  828. FreeObjects(FErrors);
  829. FErrors.Free;
  830. FListeners.Free;
  831. FSkippedTests.Free;
  832. end;
  833. procedure TTestResult.ClearErrorLists;
  834. begin
  835. FreeObjects(FFailures);
  836. FFailures.Clear;
  837. FreeObjects(FIgnoredTests);
  838. FIgnoredTests.Clear;
  839. FreeObjects(FErrors);
  840. FErrors.Clear;
  841. end;
  842. function TTestResult.GetNumErrors: integer;
  843. begin
  844. Result := FErrors.Count;
  845. end;
  846. function TTestResult.GetNumFailures: integer;
  847. begin
  848. Result := FFailures.Count;
  849. end;
  850. function TTestResult.GetNumIgnoredTests: integer;
  851. begin
  852. Result := FIgnoredTests.Count;
  853. end;
  854. function TTestResult.GetNumSkipped: integer;
  855. begin
  856. Result := FSkippedTests.Count;
  857. end;
  858. procedure TTestResult.AddListener(AListener: ITestListener);
  859. begin
  860. FListeners.Add(pointer(AListener));
  861. end;
  862. procedure TTestResult.RemoveListener(AListener: ITestListener);
  863. begin
  864. FListeners.Remove(pointer(AListener));
  865. end;
  866. procedure TTestResult.AddFailure(ATest: TTest; E: EAssertionFailedError; aFailureList: TFPList);
  867. var
  868. i: integer;
  869. f: TTestFailure;
  870. begin
  871. //lock mutex
  872. f := TTestFailure.CreateFailure(ATest, E, ATest.LastStep);
  873. aFailureList.Add(f);
  874. for i := 0 to FListeners.Count - 1 do
  875. ITestListener(FListeners[i]).AddFailure(ATest, f);
  876. //unlock mutex
  877. end;
  878. procedure TTestResult.AddError(ATest: TTest; E: Exception;
  879. AUnitName: string; AFailedMethodName: string; ALineNumber: longint);
  880. var
  881. i: integer;
  882. f: TTestFailure;
  883. begin
  884. //lock mutex
  885. f := TTestFailure.CreateFailure(ATest, E, ATest.LastStep);
  886. f.SourceUnitName := AUnitName;
  887. f.FailedMethodName := AFailedMethodName;
  888. f.LineNumber := ALineNumber;
  889. FErrors.Add(f);
  890. for i := 0 to FListeners.Count - 1 do
  891. ITestListener(FListeners[i]).AddError(ATest, f);
  892. //unlock mutex
  893. end;
  894. procedure TTestResult.EndTest(ATest: TTest);
  895. var
  896. i: integer;
  897. begin
  898. for i := 0 to FListeners.Count - 1 do
  899. ITestListener(FListeners[i]).EndTest(ATest);
  900. end;
  901. procedure ProtectTest(aTest: TTest; aResult: TTestResult);
  902. begin
  903. TTestCase(aTest).RunBare;
  904. end;
  905. procedure TTestResult.Run(ATestCase: TTestCase);
  906. begin
  907. if not SkipTest(ATestCase) then
  908. begin
  909. StartTest(ATestCase);
  910. RunProtected(ATestCase, @ProtectTest);
  911. EndTest(ATestCase);
  912. end;
  913. end;
  914. procedure TTestResult.RunProtected(ATestCase: TTest; protect: TProtect);
  915. var
  916. func, source: shortstring;
  917. line: longint;
  918. begin
  919. func := '';
  920. source := '';
  921. line := 0;
  922. try
  923. protect(ATestCase, Self);
  924. except
  925. on E: EIgnoredTest do
  926. AddFailure(ATestCase, E, FIgnoredTests);
  927. on E: EAssertionFailedError do
  928. AddFailure(ATestCase, E, FFailures);
  929. on E: Exception do
  930. begin
  931. {$ifdef SHOWLINEINFO}
  932. GetLineInfo(LongWord(ExceptAddr), func, source, line);
  933. {$endif}
  934. AddError(ATestCase, E, source, func, line);
  935. end;
  936. end;
  937. end;
  938. procedure TTestResult.StartTest(ATest: TTest);
  939. var
  940. count: integer;
  941. i: integer;
  942. begin
  943. count := ATest.CountTestCases;
  944. //lock mutex
  945. FRunTests := FRunTests + count;
  946. for i := 0 to FListeners.Count - 1 do
  947. ITestListener(FListeners[i]).StartTest(ATest);
  948. //unlock mutex
  949. end;
  950. function TTestResult.WasSuccessful: boolean;
  951. begin
  952. //lock mutex
  953. Result := (FErrors.Count = 0) and (FFailures.Count = 0);
  954. //unlock mutex
  955. end;
  956. function TTestResult.SkipTest(ATestCase: TTestCase): Boolean;
  957. var
  958. i: integer;
  959. begin
  960. Result := false;
  961. if FSkippedTests.Count = 0 then
  962. begin
  963. result := false;
  964. Exit;
  965. end
  966. else
  967. for i := 0 to FSkippedTests.Count - 1 do
  968. begin
  969. if PtrInt(FSkippedTests[i]) = PtrInt(ATestCase) then
  970. begin
  971. Result := true;
  972. Exit;
  973. end;
  974. end;
  975. end;
  976. procedure TTestResult.AddToSkipList(ATestCase: TTestCase);
  977. begin
  978. FSkippedTests.Add(ATestCase);
  979. end;
  980. procedure TTestResult.RemoveFromSkipList(ATestCase: TTestCase);
  981. begin
  982. FSkippedTests.Remove(ATestCase);
  983. end;
  984. procedure TTestResult.StartTestSuite(ATestSuite: TTestSuite);
  985. var
  986. i: integer;
  987. begin
  988. for i := 0 to FListeners.Count - 1 do
  989. ITestListener(FListeners[i]).StartTestSuite(ATestSuite);
  990. end;
  991. procedure TTestResult.EndTestSuite(ATestSuite: TTestSuite);
  992. var
  993. i: integer;
  994. begin
  995. for i := 0 to FListeners.Count - 1 do
  996. ITestListener(FListeners[i]).EndTestSuite(ATestSuite);
  997. end;
  998. end.