fpcunit.pp 24 KB

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