2
0

fpcunit.pp 32 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288
  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. SNoException = 'no exception';
  269. implementation
  270. uses
  271. testutils;
  272. Const
  273. sExpectedButWasFmt = 'Expected:' + LineEnding + '"%s"' + LineEnding + 'But was:' + LineEnding + '"%s"';
  274. sExpectedButWasAndMessageFmt = '%s' + LineEnding + sExpectedButWasFmt;
  275. sMsgActualEqualsExpFmt = '%s' + LineEnding + 'Expected ' + LineEnding + '< %s > ' + LineEnding + 'equals actual ' + LineEnding + '< %s >';
  276. sActualEqualsExpFmt = 'Expected ' + LineEnding + '< %s > ' + LineEnding + 'equals actual ' + LineEnding + '< %s >';
  277. { This lets us use a single include file for both the Interface and
  278. Implementation sections. }
  279. {$undef read_interface}
  280. {$define read_implementation}
  281. type
  282. TTestWarning = class(TTestCase)
  283. private
  284. FMessage: String;
  285. protected
  286. procedure RunTest; override;
  287. end;
  288. procedure TTestWarning.RunTest;
  289. begin
  290. Fail(FMessage);
  291. end;
  292. function ComparisonMsg(const aExpected: string; const aActual: string): string;
  293. begin
  294. Result := format(SCompare, [aExpected, aActual]);
  295. end;
  296. constructor EAssertionFailedError.Create;
  297. begin
  298. inherited Create('');
  299. end;
  300. constructor EAssertionFailedError.Create(const msg: string);
  301. begin
  302. inherited Create(msg);
  303. end;
  304. constructor TTestFailure.CreateFailure(ATest: TTest; E: Exception; LastStep: TTestStep);
  305. begin
  306. inherited Create;
  307. FTestName := ATest.GetTestName;
  308. FTestSuiteName := ATest.GetTestSuiteName;
  309. FRaisedExceptionClass := E.ClassType;
  310. FRaisedExceptionMessage := E.Message;
  311. FTestLastStep := LastStep;
  312. end;
  313. function TTestFailure.GetAsString: string;
  314. var
  315. s: string;
  316. begin
  317. if FTestSuiteName <> '' then
  318. s := FTestSuiteName + '.'
  319. else
  320. s := '';
  321. Result := s + FTestName + ': ' + FRaisedExceptionMessage;
  322. end;
  323. function TTestFailure.GetExceptionClassName: string;
  324. begin
  325. Result := FRaisedExceptionClass.ClassName;
  326. end;
  327. function TTestFailure.GetExceptionMessage: string;
  328. begin
  329. Result := FRaisedExceptionMessage;
  330. if TestLastStep = stSetUp then
  331. Result := '[SETUP] ' + Result
  332. else if TestLastStep = stTearDown then
  333. Result := '[TEARDOWN] ' + Result;
  334. end;
  335. function TTestFailure.GetIsFailure: boolean;
  336. begin
  337. Result := FRaisedExceptionClass.InheritsFrom(EAssertionFailedError);
  338. end;
  339. function TTestFailure.GetIsIgnoredTest: boolean;
  340. begin
  341. Result := FRaisedExceptionClass.InheritsFrom(EIgnoredTest);
  342. end;
  343. procedure TTestFailure.SetTestLastStep(const Value: TTestStep);
  344. begin
  345. FTestLastStep := Value;
  346. end;
  347. { TTest}
  348. function TTest.GetTestName: string;
  349. begin
  350. Result := 'TTest';
  351. end;
  352. function TTest.GetTestSuiteName: string;
  353. begin
  354. Result := 'TTest';
  355. end;
  356. function TTest.CountTestCases: integer;
  357. begin
  358. Result := 0;
  359. end;
  360. function TTest.GetEnableIgnores: boolean;
  361. begin
  362. Result := True;
  363. end;
  364. procedure TTest.Run(AResult: TTestResult);
  365. begin
  366. { do nothing }
  367. end;
  368. procedure TTest.Ignore(const AMessage: String);
  369. begin
  370. if EnableIgnores then raise EIgnoredTest.Create(AMessage);
  371. end;
  372. { TAssert }
  373. class procedure TAssert.Fail(const AMessage: String);
  374. begin
  375. raise EAssertionFailedError.Create(AMessage);
  376. end;
  377. class procedure TAssert.AssertTrue(const AMessage: String; ACondition: Boolean);
  378. begin
  379. if (not ACondition) then
  380. Fail(AMessage);
  381. end;
  382. class procedure TAssert.AssertTrue(ACondition: Boolean);
  383. begin
  384. AssertTrue('', ACondition);
  385. end;
  386. class procedure TAssert.AssertFalse(const AMessage: String; ACondition: Boolean);
  387. begin
  388. AssertTrue(AMessage, not ACondition);
  389. end;
  390. class procedure TAssert.AssertFalse(ACondition: Boolean);
  391. begin
  392. AssertFalse('', ACondition);
  393. end;
  394. class procedure TAssert.AssertEquals(const AMessage: string; Expected, Actual: string);
  395. begin
  396. AssertTrue(AMessage + ComparisonMsg(Expected, Actual), AnsiCompareStr(Expected, Actual) = 0);
  397. end;
  398. class procedure TAssert.AssertEquals(Expected, Actual: string);
  399. begin
  400. AssertEquals('', Expected, Actual);
  401. end;
  402. class procedure TAssert.AssertNotNull(const AString: string);
  403. begin
  404. AssertNotNull('', AString);
  405. end;
  406. class procedure TAssert.AssertEquals(const AMessage: string; Expected, Actual: integer);
  407. begin
  408. AssertTrue(AMessage + ComparisonMsg(IntToStr(Expected), IntToStr(Actual)), Expected = Actual);
  409. end;
  410. class procedure TAssert.AssertEquals(Expected, Actual: integer);
  411. begin
  412. AssertEquals('', Expected, Actual);
  413. end;
  414. class procedure TAssert.AssertEquals(const AMessage: string; Expected, Actual: int64);
  415. begin
  416. AssertTrue(AMessage + ComparisonMsg(IntToStr(Expected), IntToStr(Actual)), Expected = Actual);
  417. end;
  418. class procedure TAssert.AssertEquals(Expected, Actual: int64);
  419. begin
  420. AssertEquals('', Expected, Actual);
  421. end;
  422. class procedure TAssert.AssertEquals(const AMessage: string; Expected, Actual: currency);
  423. begin
  424. AssertTrue(AMessage + ComparisonMsg(FloatToStr(Expected), FloatToStr(Actual)), Expected = Actual);
  425. end;
  426. class procedure TAssert.AssertEquals(Expected, Actual: currency);
  427. begin
  428. AssertEquals('', Expected, Actual);
  429. end;
  430. class procedure TAssert.AssertEquals(const AMessage: string; Expected, Actual, Delta: double);
  431. begin
  432. AssertTrue(AMessage + ComparisonMsg(FloatToStr(Expected),FloatToStr(Actual)),
  433. (Abs(Expected - Actual) <= Delta));
  434. end;
  435. class procedure TAssert.AssertEquals(Expected, Actual, Delta: double);
  436. begin
  437. AssertEquals('', Expected, Actual, Delta);
  438. end;
  439. class procedure TAssert.AssertNotNull(const AMessage, AString: string);
  440. begin
  441. AssertTrue(AMessage, AString <> '');
  442. end;
  443. class procedure TAssert.AssertEquals(const AMessage: string; Expected, Actual: boolean);
  444. begin
  445. AssertTrue(AMessage + ComparisonMsg(BoolToStr(Expected, true), BoolToStr(Actual, true)), Expected = Actual);
  446. end;
  447. class procedure TAssert.AssertEquals(Expected, Actual: boolean);
  448. begin
  449. AssertEquals('', Expected, Actual);
  450. end;
  451. class procedure TAssert.AssertEquals(const AMessage: string; Expected, Actual: char);
  452. begin
  453. AssertTrue(AMessage + ComparisonMsg(Expected, Actual), Expected = Actual);
  454. end;
  455. class procedure TAssert.AssertEquals(Expected, Actual: char);
  456. begin
  457. AssertEquals('', Expected, Actual);
  458. end;
  459. class procedure TAssert.AssertEquals(const AMessage: string; Expected, Actual: TClass);
  460. begin
  461. AssertTrue(AMessage + ComparisonMsg(Expected.ClassName, Actual.ClassName), Expected = Actual);
  462. end;
  463. class procedure TAssert.AssertEquals(Expected, Actual: TClass);
  464. begin
  465. AssertEquals('', Expected, Actual);
  466. end;
  467. class procedure TAssert.AssertSame(const AMessage: string; Expected, Actual: TObject);
  468. begin
  469. AssertTrue(AMessage + ComparisonMsg(IntToStr(PtrInt(Expected)), IntToStr(PtrInt(Actual))),
  470. Expected = Actual);
  471. end;
  472. class procedure TAssert.AssertSame(Expected, Actual: TObject);
  473. begin
  474. AssertSame('', Expected, Actual);
  475. end;
  476. class procedure TAssert.AssertSame(const AMessage: string; Expected, Actual: Pointer);
  477. begin
  478. AssertTrue(AMessage + ComparisonMsg(IntToStr(PtrInt(Expected)), IntToStr(PtrInt(Actual))),
  479. Expected = Actual);
  480. end;
  481. class procedure TAssert.AssertSame(Expected, Actual: Pointer);
  482. begin
  483. AssertSame('', Expected, Actual);
  484. end;
  485. class procedure TAssert.AssertNotSame(const AMessage: string; Expected, Actual: TObject);
  486. begin
  487. AssertFalse(SExpectedNotSame, Expected = Actual);
  488. end;
  489. class procedure TAssert.AssertNotSame(Expected, Actual: TObject);
  490. begin
  491. AssertNotSame('', Expected, Actual);
  492. end;
  493. class procedure TAssert.AssertNotSame(const AMessage: string; Expected, Actual: Pointer);
  494. begin
  495. AssertFalse(SExpectedNotSame, Expected = Actual);
  496. end;
  497. class procedure TAssert.AssertNotSame(Expected, Actual: Pointer);
  498. begin
  499. AssertNotSame('', Expected, Actual);
  500. end;
  501. class procedure TAssert.AssertNotNull(const AMessage: string; AObject: TObject);
  502. begin
  503. AssertTrue(AMessage, (AObject <> nil));
  504. end;
  505. class procedure TAssert.AssertNotNull(AObject: TObject);
  506. begin
  507. AssertNotNull('', AObject);
  508. end;
  509. class procedure TAssert.AssertNotNullIntf(const AMessage: string; AInterface: IInterface);
  510. begin
  511. AssertTrue(AMessage, (AInterface <> nil));
  512. end;
  513. class procedure TAssert.AssertNotNullIntf(AInterface: IInterface);
  514. begin
  515. AssertNotNull('', AInterface);
  516. end;
  517. class procedure TAssert.AssertNotNull(const AMessage: string; APointer: Pointer);
  518. begin
  519. AssertTrue(AMessage, (APointer <> nil));
  520. end;
  521. class procedure TAssert.AssertNotNull(APointer: Pointer);
  522. begin
  523. AssertNotNull('', APointer);
  524. end;
  525. class procedure TAssert.AssertNull(const AMessage: string; AObject: TObject);
  526. begin
  527. AssertTrue(AMessage, (AObject = nil));
  528. end;
  529. class procedure TAssert.AssertNull(AObject: TObject);
  530. begin
  531. AssertNull('', AObject);
  532. end;
  533. class procedure TAssert.AssertNullIntf(const AMessage: string; AInterface: IInterface);
  534. begin
  535. AssertTrue(AMessage, (AInterface = nil));
  536. end;
  537. class procedure TAssert.AssertNullINtf(AInterface: IInterface);
  538. begin
  539. AssertNull('', AInterface);
  540. end;
  541. class procedure TAssert.AssertNull(const AMessage: string; APointer: Pointer);
  542. begin
  543. AssertTrue(AMessage, (APointer = nil));
  544. end;
  545. class procedure TAssert.AssertNull(APointer: Pointer);
  546. begin
  547. AssertNull('', APointer);
  548. end;
  549. class procedure TAssert.AssertException(const AMessage: string; AExceptionClass: ExceptClass;
  550. AMethod: TRunMethod);
  551. var
  552. Passed : Boolean;
  553. ExceptionName: string;
  554. begin
  555. Passed := False;
  556. try
  557. AMethod;
  558. ExceptionName:=SNoException;
  559. except
  560. on E: Exception do
  561. begin
  562. ExceptionName := E.ClassName;
  563. if E.ClassType.InheritsFrom(AExceptionClass) then
  564. begin
  565. Passed := AExceptionClass.ClassName = E.ClassName;
  566. end;
  567. end;
  568. end;
  569. AssertTrue(Format(SExceptionCompare, [AExceptionClass.ClassName, ExceptionName])+ ': ' + AMessage, Passed);
  570. end;
  571. class procedure TAssert.AssertException(AExceptionClass: ExceptClass;
  572. AMethod: TRunMethod);
  573. begin
  574. AssertException('', AExceptionClass, AMethod);
  575. end;
  576. { DUnit compatibility interface }
  577. {$IFDEF DUnit}
  578. {$I DUnitCompatibleInterface.inc}
  579. {$ENDIF DUnit}
  580. constructor TTestCase.Create;
  581. begin
  582. inherited Create;
  583. FEnableIgnores := True;
  584. end;
  585. constructor TTestCase.CreateWithName(const AName: string);
  586. begin
  587. Create;
  588. FName := AName;
  589. end;
  590. constructor TTestCase.CreateWith(const ATestName: string; const ATestSuiteName: string);
  591. begin
  592. Create;
  593. FName := ATestName;
  594. FTestSuiteName := ATestSuiteName;
  595. end;
  596. function TTestCase.AsString: string;
  597. begin
  598. Result := TestName + '(' + ClassName + ')';
  599. end;
  600. function TTestCase.CountTestCases: integer;
  601. begin
  602. Result := 1;
  603. end;
  604. function TTestCase.CreateResult: TTestResult;
  605. begin
  606. Result := TTestResult.Create;
  607. end;
  608. function TTestCase.GetTestName: string;
  609. begin
  610. Result := FName;
  611. end;
  612. function TTestCase.GetEnableIgnores: boolean;
  613. begin
  614. Result := FEnableIgnores;
  615. end;
  616. function TTestCase.GetTestSuiteName: string;
  617. begin
  618. Result := FTestSuiteName;
  619. end;
  620. procedure TTestCase.SetTestSuiteName(const aName: string);
  621. begin
  622. if FTestSuiteName <> aName then
  623. FTestSuiteName := aName;
  624. end;
  625. procedure TTestCase.SetTestName(const Value: string);
  626. begin
  627. FName := Value;
  628. end;
  629. procedure TTestCase.SetEnableIgnores(Value: boolean);
  630. begin
  631. FEnableIgnores := Value;
  632. end;
  633. function TTestCase.CreateResultAndRun: TTestResult;
  634. begin
  635. Result := CreateResult;
  636. Run(Result);
  637. end;
  638. procedure TTestCase.Run(AResult: TTestResult);
  639. begin
  640. (AResult).Run(Self);
  641. end;
  642. procedure TTestCase.RunBare;
  643. begin
  644. FLastStep := stSetUp;
  645. SetUp;
  646. try
  647. FLastStep := stRunTest;
  648. RunTest;
  649. FLastStep := stTearDown;
  650. finally
  651. TearDown;
  652. end;
  653. FLastStep := stNothing;
  654. end;
  655. procedure TTestCase.RunTest;
  656. var
  657. m: TMethod;
  658. RunMethod: TRunMethod;
  659. pMethod : Pointer;
  660. begin
  661. AssertNotNull('name of the test not assigned', FName);
  662. pMethod := Self.MethodAddress(FName);
  663. if (Assigned(pMethod)) then
  664. begin
  665. m.Code := pMethod;
  666. m.Data := self;
  667. RunMethod := TRunMethod(m);
  668. RunMethod;
  669. end
  670. else
  671. begin
  672. Fail(format(SMethodNotFound, [FName]));
  673. end;
  674. end;
  675. procedure TTestCase.SetUp;
  676. begin
  677. { do nothing }
  678. end;
  679. procedure TTestCase.TearDown;
  680. begin
  681. { do nothing }
  682. end;
  683. constructor TTestSuite.Create(AClass: TClass; AName: string);
  684. begin
  685. Create(AClass);
  686. FName := AName;
  687. end;
  688. constructor TTestSuite.Create(AClass: TClass);
  689. var
  690. ml: TStringList;
  691. i: integer;
  692. tc: TTestCaseClass;
  693. begin
  694. Create(AClass.ClassName);
  695. if AClass.InheritsFrom(TTestCase) then
  696. begin
  697. tc := TTestCaseClass(AClass);
  698. ml := TStringList.Create;
  699. try
  700. GetMethodList(AClass, ml);
  701. for i := 0 to ml.Count -1 do
  702. begin
  703. AddTest(tc.CreateWith(ml.Strings[i], tc.ClassName));
  704. end;
  705. finally
  706. ml.Free;
  707. end;
  708. end
  709. else
  710. AddTest(Warning(AClass.ClassName + SNoValidInheritance));
  711. if FTests.Count = 0 then
  712. AddTest(Warning(SNoValidTests + AClass.ClassName));
  713. end;
  714. constructor TTestSuite.Create(AClassArray: Array of TClass);
  715. var
  716. i: integer;
  717. begin
  718. Create;
  719. for i := Low(AClassArray) to High(AClassArray) do
  720. if Assigned(AClassArray[i]) then
  721. AddTest(TTestSuite.Create(AClassArray[i]));
  722. end;
  723. constructor TTestSuite.Create(AName: string);
  724. begin
  725. Create();
  726. FName := AName;
  727. end;
  728. constructor TTestSuite.Create;
  729. begin
  730. inherited Create;
  731. FTests := TFPList.Create;
  732. FEnableIgnores := True;
  733. end;
  734. destructor TTestSuite.Destroy;
  735. begin
  736. FreeObjects(FTests);
  737. FTests.Free;
  738. inherited Destroy;
  739. end;
  740. function TTestSuite.GetTest(Index: integer): TTest;
  741. begin
  742. Result := TTest(FTests[Index]);
  743. end;
  744. function TTestSuite.GetTestName: string;
  745. begin
  746. Result := FName;
  747. end;
  748. function TTestSuite.GetTestSuiteName: string;
  749. begin
  750. Result := FTestSuiteName;
  751. end;
  752. function TTestSuite.GetEnableIgnores: boolean;
  753. begin
  754. Result := FEnableIgnores;
  755. end;
  756. procedure TTestSuite.SetTestName(const Value: string);
  757. begin
  758. FName := Value;
  759. end;
  760. procedure TTestSuite.SetTestSuiteName(const aName: string);
  761. begin
  762. if FTestSuiteName <> aName then
  763. FTestSuiteName := aName;
  764. end;
  765. procedure TTestSuite.SetEnableIgnores(Value: boolean);
  766. var
  767. i: integer;
  768. begin
  769. if FEnableIgnores <> Value then
  770. begin
  771. FEnableIgnores := Value;
  772. for i := 0 to FTests.Count - 1 do
  773. TTest(FTests[i]).EnableIgnores := Value;
  774. end
  775. end;
  776. function TTestSuite.CountTestCases: integer;
  777. var
  778. i: integer;
  779. begin
  780. Result := 0;
  781. for i := 0 to FTests.Count - 1 do
  782. begin
  783. Result := Result + TTest(FTests[i]).CountTestCases;
  784. end;
  785. end;
  786. procedure TTestSuite.Run(AResult: TTestResult);
  787. var
  788. i: integer;
  789. begin
  790. if FTests.Count > 0 then
  791. AResult.StartTestSuite(self);
  792. for i := 0 to FTests.Count - 1 do
  793. RunTest(TTest(FTests[i]), AResult);
  794. if FTests.Count > 0 then
  795. AResult.EndTestSuite(self);
  796. end;
  797. procedure TTestSuite.RunTest(ATest: TTest; AResult: TTestResult);
  798. begin
  799. ATest.Run(AResult);
  800. end;
  801. procedure TTestSuite.AddTest(ATest: TTest);
  802. begin
  803. FTests.Add(ATest);
  804. if ATest.TestSuiteName = '' then
  805. ATest.TestSuiteName := Self.TestName;
  806. ATest.EnableIgnores := Self.EnableIgnores;
  807. end;
  808. procedure TTestSuite.AddTestSuiteFromClass(ATestClass: TClass);
  809. begin
  810. AddTest(TTestSuite.Create(ATestClass));
  811. end;
  812. class function TTestSuite.Warning(const aMessage: string): TTestCase;
  813. var
  814. w: TTestWarning;
  815. begin
  816. w := TTestWarning.Create;
  817. w.FMessage := aMessage;
  818. Result := w;
  819. end;
  820. constructor TTestResult.Create;
  821. begin
  822. inherited Create;
  823. FFailures := TFPList.Create;
  824. FIgnoredTests := TFPList.Create;
  825. FErrors := TFPList.Create;
  826. FListeners := TFPList.Create;
  827. FSkippedTests := TFPList.Create;
  828. FStartingTime := Now;
  829. end;
  830. destructor TTestResult.Destroy;
  831. begin
  832. FreeObjects(FFailures);
  833. FFailures.Free;
  834. FreeObjects(FIgnoredTests);
  835. FIgnoredTests.Free;
  836. FreeObjects(FErrors);
  837. FErrors.Free;
  838. FListeners.Free;
  839. FSkippedTests.Free;
  840. end;
  841. procedure TTestResult.ClearErrorLists;
  842. begin
  843. FreeObjects(FFailures);
  844. FFailures.Clear;
  845. FreeObjects(FIgnoredTests);
  846. FIgnoredTests.Clear;
  847. FreeObjects(FErrors);
  848. FErrors.Clear;
  849. end;
  850. function TTestResult.GetNumErrors: integer;
  851. begin
  852. Result := FErrors.Count;
  853. end;
  854. function TTestResult.GetNumFailures: integer;
  855. begin
  856. Result := FFailures.Count;
  857. end;
  858. function TTestResult.GetNumIgnoredTests: integer;
  859. begin
  860. Result := FIgnoredTests.Count;
  861. end;
  862. function TTestResult.GetNumSkipped: integer;
  863. begin
  864. Result := FSkippedTests.Count;
  865. end;
  866. procedure TTestResult.AddListener(AListener: ITestListener);
  867. begin
  868. FListeners.Add(pointer(AListener));
  869. end;
  870. procedure TTestResult.RemoveListener(AListener: ITestListener);
  871. begin
  872. FListeners.Remove(pointer(AListener));
  873. end;
  874. procedure TTestResult.AddFailure(ATest: TTest; E: EAssertionFailedError; aFailureList: TFPList);
  875. var
  876. i: integer;
  877. f: TTestFailure;
  878. begin
  879. //lock mutex
  880. f := TTestFailure.CreateFailure(ATest, E, ATest.LastStep);
  881. aFailureList.Add(f);
  882. for i := 0 to FListeners.Count - 1 do
  883. ITestListener(FListeners[i]).AddFailure(ATest, f);
  884. //unlock mutex
  885. end;
  886. procedure TTestResult.AddError(ATest: TTest; E: Exception;
  887. AUnitName: string; AFailedMethodName: string; ALineNumber: longint);
  888. var
  889. i: integer;
  890. f: TTestFailure;
  891. begin
  892. //lock mutex
  893. f := TTestFailure.CreateFailure(ATest, E, ATest.LastStep);
  894. f.SourceUnitName := AUnitName;
  895. f.FailedMethodName := AFailedMethodName;
  896. f.LineNumber := ALineNumber;
  897. FErrors.Add(f);
  898. for i := 0 to FListeners.Count - 1 do
  899. ITestListener(FListeners[i]).AddError(ATest, f);
  900. //unlock mutex
  901. end;
  902. procedure TTestResult.EndTest(ATest: TTest);
  903. var
  904. i: integer;
  905. begin
  906. for i := 0 to FListeners.Count - 1 do
  907. ITestListener(FListeners[i]).EndTest(ATest);
  908. end;
  909. procedure ProtectTest(aTest: TTest; aResult: TTestResult);
  910. begin
  911. TTestCase(aTest).RunBare;
  912. end;
  913. procedure TTestResult.Run(ATestCase: TTestCase);
  914. begin
  915. if not SkipTest(ATestCase) then
  916. begin
  917. StartTest(ATestCase);
  918. RunProtected(ATestCase, @ProtectTest);
  919. EndTest(ATestCase);
  920. end;
  921. end;
  922. procedure TTestResult.RunProtected(ATestCase: TTest; protect: TProtect);
  923. var
  924. func, source: shortstring;
  925. line: longint;
  926. begin
  927. func := '';
  928. source := '';
  929. line := 0;
  930. try
  931. protect(ATestCase, Self);
  932. except
  933. on E: EIgnoredTest do
  934. AddFailure(ATestCase, E, FIgnoredTests);
  935. on E: EAssertionFailedError do
  936. AddFailure(ATestCase, E, FFailures);
  937. on E: Exception do
  938. begin
  939. {$ifdef SHOWLINEINFO}
  940. GetLineInfo(LongWord(ExceptAddr), func, source, line);
  941. {$endif}
  942. AddError(ATestCase, E, source, func, line);
  943. end;
  944. end;
  945. end;
  946. procedure TTestResult.StartTest(ATest: TTest);
  947. var
  948. count: integer;
  949. i: integer;
  950. begin
  951. count := ATest.CountTestCases;
  952. //lock mutex
  953. FRunTests := FRunTests + count;
  954. for i := 0 to FListeners.Count - 1 do
  955. ITestListener(FListeners[i]).StartTest(ATest);
  956. //unlock mutex
  957. end;
  958. function TTestResult.WasSuccessful: boolean;
  959. begin
  960. //lock mutex
  961. Result := (FErrors.Count = 0) and (FFailures.Count = 0);
  962. //unlock mutex
  963. end;
  964. function TTestResult.SkipTest(ATestCase: TTestCase): Boolean;
  965. var
  966. i: integer;
  967. begin
  968. Result := false;
  969. if FSkippedTests.Count = 0 then
  970. begin
  971. result := false;
  972. Exit;
  973. end
  974. else
  975. for i := 0 to FSkippedTests.Count - 1 do
  976. begin
  977. if PtrInt(FSkippedTests[i]) = PtrInt(ATestCase) then
  978. begin
  979. Result := true;
  980. Exit;
  981. end;
  982. end;
  983. end;
  984. procedure TTestResult.AddToSkipList(ATestCase: TTestCase);
  985. begin
  986. FSkippedTests.Add(ATestCase);
  987. end;
  988. procedure TTestResult.RemoveFromSkipList(ATestCase: TTestCase);
  989. begin
  990. FSkippedTests.Remove(ATestCase);
  991. end;
  992. procedure TTestResult.StartTestSuite(ATestSuite: TTestSuite);
  993. var
  994. i: integer;
  995. begin
  996. for i := 0 to FListeners.Count - 1 do
  997. ITestListener(FListeners[i]).StartTestSuite(ATestSuite);
  998. end;
  999. procedure TTestResult.EndTestSuite(ATestSuite: TTestSuite);
  1000. var
  1001. i: integer;
  1002. begin
  1003. for i := 0 to FListeners.Count - 1 do
  1004. ITestListener(FListeners[i]).EndTestSuite(ATestSuite);
  1005. end;
  1006. end.