fpcunit.pp 26 KB

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