fpcunitreport.pp 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337
  1. {$mode objfpc}
  2. {$h+}
  3. {
  4. This file is part of the Free Component Library (FCL)
  5. Copyright (c) 2006 by Dean Zobec
  6. common base classes for FPCUnit test reports
  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 fpcunitreport;
  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: integer; ANumErrors: integer;
  29. ANumFailures: integer; ANumIgnores: integer) of object;
  30. TSuiteResults = class(TObject)
  31. private
  32. FStartTime: TDateTime;
  33. public
  34. Runs: integer;
  35. Failures: integer;
  36. Errors: integer;
  37. Ignores: integer;
  38. property StartTime: TDateTime read FStartTime write FStartTime;
  39. end;
  40. TSuiteResultsStack = class(TObject)
  41. private
  42. FResultsList: TFPList;
  43. public
  44. constructor Create;
  45. destructor Destroy; override;
  46. function Last: TSuiteResults;
  47. procedure RemoveLast;
  48. procedure Add;
  49. procedure IncrementRuns;
  50. procedure IncrementFailures;
  51. procedure IncrementErrors;
  52. procedure IncrementIgnores;
  53. end;
  54. { TCustomResultsWriter }
  55. TCustomResultsWriter = class(TComponent, ITestListener)
  56. private
  57. FLevel: integer;
  58. FCount: integer;
  59. FSkipAddressInfo: Boolean;
  60. FSparse: Boolean;
  61. FTestTime: TDateTime;
  62. FFileName: string;
  63. FSuiteResultsStack : TSuiteResultsStack;
  64. FOnWriteSuiteHeader: TWriteTestSuiteHeaderEvent;
  65. FOnWriteSuiteFooter: TWriteTestSuiteFooterEvent;
  66. FOnWriteTestHeader: TWriteTestHeaderEvent;
  67. FOnWriteTestFooter: TWriteTestFooterEvent;
  68. FOnAddFailure: TFailureEvent;
  69. FOnAddError: TFailureEvent;
  70. FOnStartTest: TTestEvent;
  71. FOnEndTest: TTestEvent;
  72. FOnStartTestSuite: TTestEvent;
  73. FOnEndTestSuite: TTestEvent;
  74. FSkipTiming: Boolean;
  75. protected
  76. procedure SetSkipAddressInfo(AValue: Boolean); virtual;
  77. procedure SetSparse(AValue: Boolean); virtual;
  78. procedure WriteTestHeader(ATest: TTest; ALevel: integer; ACount: integer); virtual;
  79. procedure WriteTestFooter(ATest: TTest; ALevel: integer; ATiming: TDateTime); virtual;
  80. procedure WriteSuiteHeader(ATestSuite: TTestSuite; ALevel: integer); virtual;
  81. procedure WriteSuiteFooter(ATestSuite: TTestSuite; ALevel: integer;
  82. ATiming: TDateTime; ANumRuns: integer; ANumErrors: integer; aNumFailures: integer;
  83. ANumIgnores: integer); virtual;
  84. procedure WriteHeader; virtual;
  85. procedure WriteFooter; virtual;
  86. public
  87. {ITestListener}
  88. procedure AddFailure(ATest: TTest; AFailure: TTestFailure); virtual;
  89. procedure AddError(ATest: TTest; AError: TTestFailure); virtual;
  90. procedure StartTest(ATest: TTest); virtual;
  91. procedure EndTest(ATest: TTest); virtual;
  92. procedure StartTestSuite(ATestSuite: TTestSuite); virtual;
  93. procedure EndTestSuite(ATestSuite: TTestSuite); virtual;
  94. constructor Create(AOwner: TComponent); override;
  95. destructor Destroy; override;
  96. procedure AfterConstruction; override;
  97. procedure BeforeDestruction; override;
  98. procedure WriteResult(aResult: TTestResult); virtual;
  99. published
  100. property FileName: string read FFileName write FFileName;
  101. property OnWriteSuiteHeader: TWriteTestSuiteHeaderEvent read FOnWriteSuiteHeader
  102. write FOnWriteSuiteHeader;
  103. property OnWriteSuiteFooter: TWriteTestSuiteFooterEvent read FOnWriteSuiteFooter
  104. write FOnWriteSuiteFooter;
  105. property OnWriteTestHeader: TWriteTestHeaderEvent read FOnWriteTestHeader
  106. write FOnWriteTestHeader;
  107. property OnWriteTestFooter: TWriteTestFooterEvent read FOnWriteTestFooter
  108. write FOnWriteTestFooter;
  109. property OnAddFailure: TFailureEvent read FOnAddFailure write FOnAddFailure;
  110. property OnAddError: TFailureEvent read FOnAddError write FOnAddError;
  111. property OnStartTest: TTestEvent read FOnStartTest write FOnStartTest;
  112. property OnEndTest: TTestEvent read FOnEndTest write FOnEndTest;
  113. property OnStartTestSuite: TTestEvent read FOnStartTestSuite write FOnStartTestSuite;
  114. property OnEndTestSuite: TTestEvent read FOnEndTestSuite write FOnEndTestSuite;
  115. Property SkipTiming : Boolean Read FSkipTiming Write FSkipTiming;
  116. Property Sparse : Boolean Read FSparse Write SetSparse;
  117. Property SkipAddressInfo : Boolean Read FSkipAddressInfo Write SetSkipAddressInfo;
  118. end;
  119. implementation
  120. constructor TSuiteResultsStack.Create;
  121. begin
  122. FResultsList := TFPList.Create;
  123. end;
  124. destructor TSuiteResultsStack.Destroy;
  125. var
  126. i: integer;
  127. begin
  128. for i := 0 to FResultsList.Count -1 do
  129. TObject(FResultsList[i]).Free;
  130. FResultsList.Free;
  131. inherited Destroy;
  132. end;
  133. function TSuiteResultsStack.Last: TSuiteResults;
  134. begin
  135. Result := TSuiteResults(FResultsList[FResultsList.Count -1]);
  136. end;
  137. procedure TSuiteResultsStack.RemoveLast;
  138. begin
  139. TObject(FResultsList[FResultsList.Count - 1]).Free;
  140. FResultsList.Delete(FResultsList.Count - 1);
  141. end;
  142. procedure TSuiteResultsStack.Add;
  143. begin
  144. FResultsList.Add(TSuiteResults.Create);
  145. end;
  146. procedure TSuiteResultsStack.IncrementRuns;
  147. var
  148. i: integer;
  149. begin
  150. for i := 0 to FResultsList.Count -1 do
  151. Inc(TSuiteResults(FResultsList[i]).Runs);
  152. end;
  153. procedure TSuiteResultsStack.IncrementFailures;
  154. var
  155. i: integer;
  156. begin
  157. for i := 0 to FResultsList.Count -1 do
  158. Inc(TSuiteResults(FResultsList[i]).Failures);
  159. end;
  160. procedure TSuiteResultsStack.IncrementErrors;
  161. var
  162. i: integer;
  163. begin
  164. for i := 0 to FResultsList.Count -1 do
  165. Inc(TSuiteResults(FResultsList[i]).Errors);
  166. end;
  167. procedure TSuiteResultsStack.IncrementIgnores;
  168. var
  169. i: integer;
  170. begin
  171. for i := 0 to FResultsList.Count -1 do
  172. Inc(TSuiteResults(FResultsList[i]).Ignores);
  173. end;
  174. constructor TCustomResultsWriter.Create(AOwner: TComponent);
  175. begin
  176. inherited Create(AOwner);
  177. FLevel := -1;
  178. FCount := 1;
  179. FFilename := '';
  180. FSuiteResultsStack := TSuiteResultsStack.Create;
  181. end;
  182. destructor TCustomResultsWriter.Destroy;
  183. begin
  184. FSuiteResultsStack.Free;
  185. inherited Destroy
  186. end;
  187. procedure TCustomResultsWriter.AfterConstruction;
  188. begin
  189. WriteHeader;
  190. end;
  191. procedure TCustomResultsWriter.BeforeDestruction;
  192. begin
  193. WriteFooter;
  194. end;
  195. procedure TCustomResultsWriter.StartTest(ATest: TTest);
  196. begin
  197. WriteTestHeader(ATest, FLevel, FCount);
  198. if Assigned(FOnStartTest) then
  199. FOnStartTest(Self, ATest);
  200. FTestTime := Now;
  201. end;
  202. procedure TCustomResultsWriter.EndTest(ATest: TTest);
  203. begin
  204. Inc(FCount);
  205. FTestTime := Now - FTestTime;
  206. FSuiteResultsStack.IncrementRuns;
  207. WriteTestFooter(ATest, FLevel, FTestTime);
  208. if Assigned(FOnEndTest) then
  209. FOnEndTest(Self, ATest);
  210. end;
  211. procedure TCustomResultsWriter.StartTestSuite(ATestSuite: TTestSuite);
  212. begin
  213. inc(FLevel);
  214. WriteSuiteHeader(ATestSuite, FLevel);
  215. if Assigned(FOnStartTestSuite) then
  216. FOnStartTestSuite(Self, ATestSuite);
  217. FSuiteResultsStack.Add;
  218. FSuiteResultsStack.Last.StartTime := now;
  219. end;
  220. procedure TCustomResultsWriter.EndTestSuite(ATestSuite: TTestSuite);
  221. begin
  222. with FSuiteResultsStack.Last do
  223. begin
  224. WriteSuiteFooter(ATestSuite, FLevel, Now - StartTime,
  225. Runs, Errors, Failures, Ignores);
  226. end;
  227. FSuiteResultsStack.RemoveLast;
  228. dec(FLevel);
  229. if Assigned(FOnEndTestSuite) then
  230. FOnEndTestSuite(Self, ATestSuite);
  231. end;
  232. procedure TCustomResultsWriter.AddFailure(ATest: TTest; AFailure: TTestFailure);
  233. begin
  234. if AFailure.IsIgnoredTest then
  235. FSuiteResultsStack.IncrementIgnores
  236. else
  237. FSuiteResultsStack.IncrementFailures;
  238. if Assigned(FOnAddFailure) then
  239. FOnAddFailure(Self, ATest, AFailure);
  240. end;
  241. procedure TCustomResultsWriter.AddError(ATest: TTest; AError: TTestFailure);
  242. begin
  243. FSuiteResultsStack.IncrementErrors;
  244. if Assigned(FOnAddError) then
  245. FOnAddError(Self, ATest, AError);
  246. end;
  247. procedure TCustomResultsWriter.SetSkipAddressInfo(AValue: Boolean);
  248. begin
  249. if FSkipAddressInfo=AValue then Exit;
  250. FSkipAddressInfo:=AValue;
  251. end;
  252. procedure TCustomResultsWriter.SetSparse(AValue: Boolean);
  253. begin
  254. if FSparse=AValue then Exit;
  255. FSparse:=AValue;
  256. end;
  257. procedure TCustomResultsWriter.WriteTestHeader(ATest: TTest; ALevel: integer; ACount: integer);
  258. begin
  259. if Assigned(FOnWriteTestHeader) then
  260. FOnWriteTestHeader(Self, ATest, ALevel, ACount);
  261. end;
  262. procedure TCustomResultsWriter.WriteTestFooter(ATest: TTest; ALevel: integer;
  263. ATiming: TDateTime);
  264. begin
  265. if Assigned(FOnWriteTestFooter) then
  266. FOnWriteTestFooter(Self, ATest, ALevel, ATiming);
  267. end;
  268. procedure TCustomResultsWriter.WriteSuiteHeader(ATestSuite: TTestSuite; ALevel: integer);
  269. begin
  270. if Assigned(FOnWriteSuiteHeader) then
  271. FOnWriteSuiteHeader(Self, ATestSuite, ALevel);
  272. end;
  273. procedure TCustomResultsWriter.WriteSuiteFooter(ATestSuite: TTestSuite;
  274. ALevel: integer; ATiming: TDateTime; ANumRuns: integer; ANumErrors: integer;
  275. aNumFailures: integer; ANumIgnores: integer);
  276. begin
  277. if Assigned(FOnWriteSuiteFooter) then
  278. FOnWriteSuiteFooter(Self, ATestSuite, ALevel, ATiming, ANumRuns, ANumErrors,
  279. aNumFailures, ANumIgnores);
  280. end;
  281. procedure TCustomResultsWriter.WriteHeader;
  282. begin
  283. // do nothing
  284. end;
  285. procedure TCustomResultsWriter.WriteFooter;
  286. begin
  287. // do nothing
  288. end;
  289. procedure TCustomResultsWriter.WriteResult(aResult: TTestResult);
  290. begin
  291. // do nothing
  292. end;
  293. end.