fpcunitreport.pas 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428
  1. {
  2. This file is part of the Free Component Library (FCL)
  3. Copyright (c) 2006 by Dean Zobec
  4. Port to Pas2JS by Mattias Gaertner in 2017.
  5. common base classes for FPCUnit test reports
  6. See the file COPYING.FPC, included in this distribution,
  7. for details about the copyright.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  11. **********************************************************************}
  12. unit FPCUnitReport;
  13. {$mode objfpc}
  14. interface
  15. uses
  16. Classes, SysUtils, FPCUnit;
  17. type
  18. TWriteTestHeaderEvent = procedure(Sender: TObject; ATest: TTest;
  19. ALevel: integer; ACount: integer) of object;
  20. TWriteTestFooterEvent = procedure(Sender: TObject; ATest: TTest;
  21. ALevel: integer; ATiming: TDateTime) of object;
  22. TTestNameEvent = procedure(Sender: TObject; const AName: string) of object;
  23. TFailureEvent = procedure(Sender: TObject; ATest: TTest; AFailure: TTestFailure) of object;
  24. TTestEvent = procedure(Sender: TObject; ATest: TTest) of object;
  25. TWriteTestSuiteHeaderEvent = procedure(Sender: TObject; ATestSuite: TTestSuite;
  26. ALevel: integer) of object;
  27. TWriteTestSuiteFooterEvent = procedure(Sender: TObject; ATestSuite: TTestSuite;
  28. ALevel: integer; ATiming: TDateTime; ANumRuns, ANumErrors, ANumFailures,
  29. ANumIgnores: integer) of object;
  30. { TSuiteResults }
  31. TSuiteResults = class(TObject)
  32. private
  33. FStartTime: TDateTime;
  34. public
  35. Runs: integer;
  36. Failures: integer;
  37. Errors: integer;
  38. Ignores: integer;
  39. property StartTime: TDateTime read FStartTime write FStartTime;
  40. end;
  41. { TSuiteResultsStack }
  42. TSuiteResultsStack = class(TObject)
  43. private
  44. FResultsList: TFPList;
  45. public
  46. constructor Create; reintroduce;
  47. destructor Destroy; override;
  48. function Last: TSuiteResults;
  49. procedure RemoveLast;
  50. procedure Add;
  51. procedure IncrementRuns;
  52. procedure IncrementFailures;
  53. procedure IncrementErrors;
  54. procedure IncrementIgnores;
  55. end;
  56. TCustomResultsWriter = class;
  57. { TCustomResultsWriterTestListener }
  58. TCustomResultsWriterTestListener = class(ITestListener) // ToDo: replace when interfaces are implemented
  59. public
  60. Writer: TCustomResultsWriter;
  61. constructor Create(aWriter: TCustomResultsWriter); reintroduce;
  62. procedure AddError(ATest: TTest; AError: TTestFailure); override;
  63. procedure AddFailure(ATest: TTest; AFailure: TTestFailure); override;
  64. procedure EndTest(ATest: TTest); override;
  65. procedure EndTestSuite(ATestSuite: TTestSuite); override;
  66. procedure StartTest(ATest: TTest); override;
  67. procedure StartTestSuite(ATestSuite: TTestSuite); override;
  68. end;
  69. { TCustomResultsWriter }
  70. TCustomResultsWriter = class(TComponent)
  71. private
  72. FLevel: integer;
  73. FCount: integer;
  74. FSkipAddressInfo: Boolean;
  75. FSparse: Boolean;
  76. FTestTime: TDateTime;
  77. FFileName: string;
  78. FSuiteResultsStack : TSuiteResultsStack;
  79. FOnWriteSuiteHeader: TWriteTestSuiteHeaderEvent;
  80. FOnWriteSuiteFooter: TWriteTestSuiteFooterEvent;
  81. FOnWriteTestHeader: TWriteTestHeaderEvent;
  82. FOnWriteTestFooter: TWriteTestFooterEvent;
  83. FOnAddFailure: TFailureEvent;
  84. FOnAddError: TFailureEvent;
  85. FOnStartTest: TTestEvent;
  86. FOnEndTest: TTestEvent;
  87. FOnStartTestSuite: TTestEvent;
  88. FOnEndTestSuite: TTestEvent;
  89. FSkipTiming: Boolean;
  90. FTestListener: ITestListener; // TCustomResultsWriterTestListener ToDo: replace when interfaces are implemented
  91. protected
  92. procedure SetSkipAddressInfo(AValue: Boolean); virtual;
  93. procedure SetSparse(AValue: Boolean); virtual;
  94. procedure WriteTestHeader(ATest: TTest; ALevel: integer; ACount: integer); virtual;
  95. procedure WriteTestFooter(ATest: TTest; ALevel: integer; ATiming: TDateTime); virtual;
  96. procedure WriteSuiteHeader(ATestSuite: TTestSuite; ALevel: integer); virtual;
  97. procedure WriteSuiteFooter(ATestSuite: TTestSuite; ALevel: integer;
  98. ATiming: TDateTime; ANumRuns, ANumErrors, aNumFailures, ANumIgnores: integer); virtual;
  99. procedure WriteHeader; virtual;
  100. procedure WriteFooter; virtual;
  101. public
  102. {ITestListener}
  103. procedure AddFailure(ATest: TTest; AFailure: TTestFailure); virtual;
  104. procedure AddError(ATest: TTest; AError: TTestFailure); virtual;
  105. procedure StartTest(ATest: TTest); virtual;
  106. procedure EndTest(ATest: TTest); virtual;
  107. procedure StartTestSuite(ATestSuite: TTestSuite); virtual;
  108. procedure EndTestSuite(ATestSuite: TTestSuite); virtual;
  109. constructor Create(AOwner: TComponent); override;
  110. destructor Destroy; override;
  111. procedure AfterConstruction; override;
  112. procedure BeforeDestruction; override;
  113. procedure WriteResult(aResult: TTestResult); virtual;
  114. published
  115. property FileName: string read FFileName write FFileName;
  116. property OnWriteSuiteHeader: TWriteTestSuiteHeaderEvent read FOnWriteSuiteHeader
  117. write FOnWriteSuiteHeader;
  118. property OnWriteSuiteFooter: TWriteTestSuiteFooterEvent read FOnWriteSuiteFooter
  119. write FOnWriteSuiteFooter;
  120. property OnWriteTestHeader: TWriteTestHeaderEvent read FOnWriteTestHeader
  121. write FOnWriteTestHeader;
  122. property OnWriteTestFooter: TWriteTestFooterEvent read FOnWriteTestFooter
  123. write FOnWriteTestFooter;
  124. property OnAddFailure: TFailureEvent read FOnAddFailure write FOnAddFailure;
  125. property OnAddError: TFailureEvent read FOnAddError write FOnAddError;
  126. property OnStartTest: TTestEvent read FOnStartTest write FOnStartTest;
  127. property OnEndTest: TTestEvent read FOnEndTest write FOnEndTest;
  128. property OnStartTestSuite: TTestEvent read FOnStartTestSuite write FOnStartTestSuite;
  129. property OnEndTestSuite: TTestEvent read FOnEndTestSuite write FOnEndTestSuite;
  130. Property SkipTiming : Boolean Read FSkipTiming Write FSkipTiming;
  131. Property Sparse : Boolean Read FSparse Write SetSparse;
  132. Property SkipAddressInfo : Boolean Read FSkipAddressInfo Write SetSkipAddressInfo;
  133. Property TestListener: ITestListener read FTestListener; // ToDo: replace when interfaces are implemented
  134. end;
  135. // This is a callback which can be used to re-run test in apps
  136. TRunForm = class(TComponent)
  137. private
  138. FOnRun: TNotifyEvent;
  139. Public
  140. Procedure Initialize; virtual;
  141. Property OnRun : TNotifyEvent Read FOnRun Write FOnRun;
  142. end;
  143. TRunFormClass = class of TRunForm;
  144. implementation
  145. { TCustomResultsWriterTestListener }
  146. constructor TCustomResultsWriterTestListener.Create(
  147. aWriter: TCustomResultsWriter);
  148. begin
  149. Writer:=aWriter;
  150. end;
  151. procedure TCustomResultsWriterTestListener.AddError(ATest: TTest;
  152. AError: TTestFailure);
  153. begin
  154. Writer.AddError(ATest,AError);
  155. end;
  156. procedure TCustomResultsWriterTestListener.AddFailure(ATest: TTest;
  157. AFailure: TTestFailure);
  158. begin
  159. Writer.AddFailure(ATest,AFailure);
  160. end;
  161. procedure TCustomResultsWriterTestListener.EndTest(ATest: TTest);
  162. begin
  163. Writer.EndTest(ATest);
  164. end;
  165. procedure TCustomResultsWriterTestListener.EndTestSuite(ATestSuite: TTestSuite);
  166. begin
  167. Writer.EndTestSuite(ATestSuite);
  168. end;
  169. procedure TCustomResultsWriterTestListener.StartTest(ATest: TTest);
  170. begin
  171. Writer.StartTest(ATest);
  172. end;
  173. procedure TCustomResultsWriterTestListener.StartTestSuite(ATestSuite: TTestSuite
  174. );
  175. begin
  176. Writer.StartTestSuite(ATestSuite);
  177. end;
  178. { TCustomResultsWriter }
  179. procedure TCustomResultsWriter.SetSkipAddressInfo(AValue: Boolean);
  180. begin
  181. if FSkipAddressInfo=AValue then Exit;
  182. FSkipAddressInfo:=AValue;
  183. end;
  184. procedure TCustomResultsWriter.SetSparse(AValue: Boolean);
  185. begin
  186. if FSparse=AValue then Exit;
  187. FSparse:=AValue;
  188. end;
  189. procedure TCustomResultsWriter.WriteTestHeader(ATest: TTest; ALevel: integer;
  190. ACount: integer);
  191. begin
  192. if Assigned(FOnWriteTestHeader) then
  193. FOnWriteTestHeader(Self, ATest, ALevel, ACount);
  194. end;
  195. procedure TCustomResultsWriter.WriteTestFooter(ATest: TTest; ALevel: integer;
  196. ATiming: TDateTime);
  197. begin
  198. if Assigned(FOnWriteTestFooter) then
  199. FOnWriteTestFooter(Self, ATest, ALevel, ATiming);
  200. end;
  201. procedure TCustomResultsWriter.WriteSuiteHeader(ATestSuite: TTestSuite;
  202. ALevel: integer);
  203. begin
  204. if Assigned(FOnWriteSuiteHeader) then
  205. FOnWriteSuiteHeader(Self, ATestSuite, ALevel);
  206. end;
  207. procedure TCustomResultsWriter.WriteSuiteFooter(ATestSuite: TTestSuite;
  208. ALevel: integer; ATiming: TDateTime; ANumRuns, ANumErrors, aNumFailures,
  209. ANumIgnores: integer);
  210. begin
  211. if Assigned(FOnWriteSuiteFooter) then
  212. FOnWriteSuiteFooter(Self, ATestSuite, ALevel, ATiming, ANumRuns, ANumErrors,
  213. aNumFailures, ANumIgnores);
  214. end;
  215. procedure TCustomResultsWriter.WriteHeader;
  216. begin
  217. // do nothing
  218. end;
  219. procedure TCustomResultsWriter.WriteFooter;
  220. begin
  221. // do nothing
  222. end;
  223. procedure TCustomResultsWriter.AddFailure(ATest: TTest; AFailure: TTestFailure);
  224. begin
  225. if AFailure.IsIgnoredTest then
  226. FSuiteResultsStack.IncrementIgnores
  227. else
  228. FSuiteResultsStack.IncrementFailures;
  229. if Assigned(FOnAddFailure) then
  230. FOnAddFailure(Self, ATest, AFailure);
  231. end;
  232. procedure TCustomResultsWriter.AddError(ATest: TTest; AError: TTestFailure);
  233. begin
  234. FSuiteResultsStack.IncrementErrors;
  235. if Assigned(FOnAddError) then
  236. FOnAddError(Self, ATest, AError);
  237. end;
  238. procedure TCustomResultsWriter.StartTest(ATest: TTest);
  239. begin
  240. WriteTestHeader(ATest, FLevel, FCount);
  241. if Assigned(FOnStartTest) then
  242. FOnStartTest(Self, ATest);
  243. FTestTime := Now;
  244. end;
  245. procedure TCustomResultsWriter.EndTest(ATest: TTest);
  246. begin
  247. Inc(FCount);
  248. FTestTime := Now - FTestTime;
  249. FSuiteResultsStack.IncrementRuns;
  250. WriteTestFooter(ATest, FLevel, FTestTime);
  251. if Assigned(FOnEndTest) then
  252. FOnEndTest(Self, ATest);
  253. end;
  254. procedure TCustomResultsWriter.StartTestSuite(ATestSuite: TTestSuite);
  255. begin
  256. inc(FLevel);
  257. WriteSuiteHeader(ATestSuite, FLevel);
  258. if Assigned(FOnStartTestSuite) then
  259. FOnStartTestSuite(Self, ATestSuite);
  260. FSuiteResultsStack.Add;
  261. FSuiteResultsStack.Last.StartTime := now;
  262. end;
  263. procedure TCustomResultsWriter.EndTestSuite(ATestSuite: TTestSuite);
  264. begin
  265. with FSuiteResultsStack.Last do
  266. begin
  267. WriteSuiteFooter(ATestSuite, FLevel, Now - StartTime,
  268. Runs, Errors, Failures, Ignores);
  269. end;
  270. FSuiteResultsStack.RemoveLast;
  271. dec(FLevel);
  272. if Assigned(FOnEndTestSuite) then
  273. FOnEndTestSuite(Self, ATestSuite);
  274. end;
  275. constructor TCustomResultsWriter.Create(AOwner: TComponent);
  276. begin
  277. inherited Create(AOwner);
  278. FLevel := -1;
  279. FCount := 1;
  280. FFilename := '';
  281. FSuiteResultsStack := TSuiteResultsStack.Create;
  282. FTestListener:=TCustomResultsWriterTestListener.Create(Self);
  283. end;
  284. destructor TCustomResultsWriter.Destroy;
  285. begin
  286. FreeAndNil(FSuiteResultsStack);
  287. FreeAndNil(FTestListener);
  288. inherited Destroy;
  289. end;
  290. procedure TCustomResultsWriter.AfterConstruction;
  291. begin
  292. WriteHeader;
  293. end;
  294. procedure TCustomResultsWriter.BeforeDestruction;
  295. begin
  296. WriteFooter;
  297. end;
  298. procedure TCustomResultsWriter.WriteResult(aResult: TTestResult);
  299. begin
  300. // do nothing
  301. if aResult=nil then;
  302. end;
  303. { TSuiteResultsStack }
  304. constructor TSuiteResultsStack.Create;
  305. begin
  306. FResultsList := TFPList.Create;
  307. end;
  308. destructor TSuiteResultsStack.Destroy;
  309. var
  310. i: integer;
  311. begin
  312. for i := 0 to FResultsList.Count-1 do
  313. TObject(FResultsList[i]).Destroy;
  314. FreeAndNil(FResultsList);
  315. inherited Destroy;
  316. end;
  317. function TSuiteResultsStack.Last: TSuiteResults;
  318. begin
  319. Result := TSuiteResults(FResultsList[FResultsList.Count -1]);
  320. end;
  321. procedure TSuiteResultsStack.RemoveLast;
  322. begin
  323. TObject(FResultsList[FResultsList.Count - 1]).Destroy;
  324. FResultsList.Delete(FResultsList.Count - 1);
  325. end;
  326. procedure TSuiteResultsStack.Add;
  327. begin
  328. FResultsList.Add(TSuiteResults.Create);
  329. end;
  330. procedure TSuiteResultsStack.IncrementRuns;
  331. var
  332. i: integer;
  333. begin
  334. for i := 0 to FResultsList.Count -1 do
  335. Inc(TSuiteResults(FResultsList[i]).Runs);
  336. end;
  337. procedure TSuiteResultsStack.IncrementFailures;
  338. var
  339. i: integer;
  340. begin
  341. for i := 0 to FResultsList.Count -1 do
  342. Inc(TSuiteResults(FResultsList[i]).Failures);
  343. end;
  344. procedure TSuiteResultsStack.IncrementErrors;
  345. var
  346. i: integer;
  347. begin
  348. for i := 0 to FResultsList.Count -1 do
  349. Inc(TSuiteResults(FResultsList[i]).Errors);
  350. end;
  351. procedure TSuiteResultsStack.IncrementIgnores;
  352. var
  353. i: integer;
  354. begin
  355. for i := 0 to FResultsList.Count -1 do
  356. Inc(TSuiteResults(FResultsList[i]).Ignores);
  357. end;
  358. { TRunForm }
  359. procedure TRunForm.Initialize;
  360. begin
  361. // Do nothing
  362. end;
  363. end.