fpcunit.pp 23 KB

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