fpcunit.pp 28 KB

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