fpcunitreport.pas 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409
  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. implementation
  136. { TCustomResultsWriterTestListener }
  137. constructor TCustomResultsWriterTestListener.Create(
  138. aWriter: TCustomResultsWriter);
  139. begin
  140. Writer:=aWriter;
  141. end;
  142. procedure TCustomResultsWriterTestListener.AddError(ATest: TTest;
  143. AError: TTestFailure);
  144. begin
  145. Writer.AddError(ATest,AError);
  146. end;
  147. procedure TCustomResultsWriterTestListener.AddFailure(ATest: TTest;
  148. AFailure: TTestFailure);
  149. begin
  150. Writer.AddFailure(ATest,AFailure);
  151. end;
  152. procedure TCustomResultsWriterTestListener.EndTest(ATest: TTest);
  153. begin
  154. Writer.EndTest(ATest);
  155. end;
  156. procedure TCustomResultsWriterTestListener.EndTestSuite(ATestSuite: TTestSuite);
  157. begin
  158. Writer.EndTestSuite(ATestSuite);
  159. end;
  160. procedure TCustomResultsWriterTestListener.StartTest(ATest: TTest);
  161. begin
  162. Writer.StartTest(ATest);
  163. end;
  164. procedure TCustomResultsWriterTestListener.StartTestSuite(ATestSuite: TTestSuite
  165. );
  166. begin
  167. Writer.StartTestSuite(ATestSuite);
  168. end;
  169. { TCustomResultsWriter }
  170. procedure TCustomResultsWriter.SetSkipAddressInfo(AValue: Boolean);
  171. begin
  172. if FSkipAddressInfo=AValue then Exit;
  173. FSkipAddressInfo:=AValue;
  174. end;
  175. procedure TCustomResultsWriter.SetSparse(AValue: Boolean);
  176. begin
  177. if FSparse=AValue then Exit;
  178. FSparse:=AValue;
  179. end;
  180. procedure TCustomResultsWriter.WriteTestHeader(ATest: TTest; ALevel: integer;
  181. ACount: integer);
  182. begin
  183. if Assigned(FOnWriteTestHeader) then
  184. FOnWriteTestHeader(Self, ATest, ALevel, ACount);
  185. end;
  186. procedure TCustomResultsWriter.WriteTestFooter(ATest: TTest; ALevel: integer;
  187. ATiming: TDateTime);
  188. begin
  189. if Assigned(FOnWriteTestFooter) then
  190. FOnWriteTestFooter(Self, ATest, ALevel, ATiming);
  191. end;
  192. procedure TCustomResultsWriter.WriteSuiteHeader(ATestSuite: TTestSuite;
  193. ALevel: integer);
  194. begin
  195. if Assigned(FOnWriteSuiteHeader) then
  196. FOnWriteSuiteHeader(Self, ATestSuite, ALevel);
  197. end;
  198. procedure TCustomResultsWriter.WriteSuiteFooter(ATestSuite: TTestSuite;
  199. ALevel: integer; ATiming: TDateTime; ANumRuns, ANumErrors, aNumFailures,
  200. ANumIgnores: integer);
  201. begin
  202. if Assigned(FOnWriteSuiteFooter) then
  203. FOnWriteSuiteFooter(Self, ATestSuite, ALevel, ATiming, ANumRuns, ANumErrors,
  204. aNumFailures, ANumIgnores);
  205. end;
  206. procedure TCustomResultsWriter.WriteHeader;
  207. begin
  208. // do nothing
  209. end;
  210. procedure TCustomResultsWriter.WriteFooter;
  211. begin
  212. // do nothing
  213. end;
  214. procedure TCustomResultsWriter.AddFailure(ATest: TTest; AFailure: TTestFailure);
  215. begin
  216. if AFailure.IsIgnoredTest then
  217. FSuiteResultsStack.IncrementIgnores
  218. else
  219. FSuiteResultsStack.IncrementFailures;
  220. if Assigned(FOnAddFailure) then
  221. FOnAddFailure(Self, ATest, AFailure);
  222. end;
  223. procedure TCustomResultsWriter.AddError(ATest: TTest; AError: TTestFailure);
  224. begin
  225. FSuiteResultsStack.IncrementErrors;
  226. if Assigned(FOnAddError) then
  227. FOnAddError(Self, ATest, AError);
  228. end;
  229. procedure TCustomResultsWriter.StartTest(ATest: TTest);
  230. begin
  231. WriteTestHeader(ATest, FLevel, FCount);
  232. if Assigned(FOnStartTest) then
  233. FOnStartTest(Self, ATest);
  234. FTestTime := Now;
  235. end;
  236. procedure TCustomResultsWriter.EndTest(ATest: TTest);
  237. begin
  238. Inc(FCount);
  239. FTestTime := Now - FTestTime;
  240. FSuiteResultsStack.IncrementRuns;
  241. WriteTestFooter(ATest, FLevel, FTestTime);
  242. if Assigned(FOnEndTest) then
  243. FOnEndTest(Self, ATest);
  244. end;
  245. procedure TCustomResultsWriter.StartTestSuite(ATestSuite: TTestSuite);
  246. begin
  247. inc(FLevel);
  248. WriteSuiteHeader(ATestSuite, FLevel);
  249. if Assigned(FOnStartTestSuite) then
  250. FOnStartTestSuite(Self, ATestSuite);
  251. FSuiteResultsStack.Add;
  252. FSuiteResultsStack.Last.StartTime := now;
  253. end;
  254. procedure TCustomResultsWriter.EndTestSuite(ATestSuite: TTestSuite);
  255. begin
  256. with FSuiteResultsStack.Last do
  257. begin
  258. WriteSuiteFooter(ATestSuite, FLevel, Now - StartTime,
  259. Runs, Errors, Failures, Ignores);
  260. end;
  261. FSuiteResultsStack.RemoveLast;
  262. dec(FLevel);
  263. if Assigned(FOnEndTestSuite) then
  264. FOnEndTestSuite(Self, ATestSuite);
  265. end;
  266. constructor TCustomResultsWriter.Create(AOwner: TComponent);
  267. begin
  268. inherited Create(AOwner);
  269. FLevel := -1;
  270. FCount := 1;
  271. FFilename := '';
  272. FSuiteResultsStack := TSuiteResultsStack.Create;
  273. FTestListener:=TCustomResultsWriterTestListener.Create(Self);
  274. end;
  275. destructor TCustomResultsWriter.Destroy;
  276. begin
  277. FreeAndNil(FSuiteResultsStack);
  278. FreeAndNil(FTestListener);
  279. inherited Destroy;
  280. end;
  281. procedure TCustomResultsWriter.AfterConstruction;
  282. begin
  283. WriteHeader;
  284. end;
  285. procedure TCustomResultsWriter.BeforeDestruction;
  286. begin
  287. WriteFooter;
  288. end;
  289. procedure TCustomResultsWriter.WriteResult(aResult: TTestResult);
  290. begin
  291. // do nothing
  292. if aResult=nil then;
  293. end;
  294. { TSuiteResultsStack }
  295. constructor TSuiteResultsStack.Create;
  296. begin
  297. FResultsList := TFPList.Create;
  298. end;
  299. destructor TSuiteResultsStack.Destroy;
  300. var
  301. i: integer;
  302. begin
  303. for i := 0 to FResultsList.Count-1 do
  304. TObject(FResultsList[i]).Destroy;
  305. FreeAndNil(FResultsList);
  306. inherited Destroy;
  307. end;
  308. function TSuiteResultsStack.Last: TSuiteResults;
  309. begin
  310. Result := TSuiteResults(FResultsList[FResultsList.Count -1]);
  311. end;
  312. procedure TSuiteResultsStack.RemoveLast;
  313. begin
  314. TObject(FResultsList[FResultsList.Count - 1]).Destroy;
  315. FResultsList.Delete(FResultsList.Count - 1);
  316. end;
  317. procedure TSuiteResultsStack.Add;
  318. begin
  319. FResultsList.Add(TSuiteResults.Create);
  320. end;
  321. procedure TSuiteResultsStack.IncrementRuns;
  322. var
  323. i: integer;
  324. begin
  325. for i := 0 to FResultsList.Count -1 do
  326. Inc(TSuiteResults(FResultsList[i]).Runs);
  327. end;
  328. procedure TSuiteResultsStack.IncrementFailures;
  329. var
  330. i: integer;
  331. begin
  332. for i := 0 to FResultsList.Count -1 do
  333. Inc(TSuiteResults(FResultsList[i]).Failures);
  334. end;
  335. procedure TSuiteResultsStack.IncrementErrors;
  336. var
  337. i: integer;
  338. begin
  339. for i := 0 to FResultsList.Count -1 do
  340. Inc(TSuiteResults(FResultsList[i]).Errors);
  341. end;
  342. procedure TSuiteResultsStack.IncrementIgnores;
  343. var
  344. i: integer;
  345. begin
  346. for i := 0 to FResultsList.Count -1 do
  347. Inc(TSuiteResults(FResultsList[i]).Ignores);
  348. end;
  349. end.