fpcunit.pp 26 KB

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