123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408 |
- unit htmltestreport;
- {$mode objfpc}
- interface
- uses
- Classes, SysUtils, FPCUnit, FPCUnitReport, web;
- Type
- { TTestTreeBuilder }
- TTestTreeBuilder = Class
- private
- FBaseElement: TJSElement;
- FBaseElementID: String;
- Public
- Constructor Create(aBaseElementID : String); Virtual; reintroduce;
- Procedure ShowSuite(aSuite : TTestSuite); virtual; abstract;
- Property BaseElement : TJSElement Read FBaseElement;
- Property BaseElementID : String Read FBaseElementID;
- end;
- { THTMLTreeBuilder }
- THTMLTreeBuilder = Class(TTestTreeBuilder)
- private
- FIDPrefix : String;
- procedure AppendSuite(Parent: TJSElement; aSuite: TTestSuite; aLevel: integer);
- procedure PopIDPrefix(aPrefix: String);
- procedure PushIDPrefix(aPrefix: String);
- procedure ShowStatsHeader(aParent: TJSElement);
- Public
- Procedure ShowSuite(aSuite : TTestSuite); override;
- end;
- { THTMLResultsWriter }
- THTMLResultsWriter = class(TCustomResultsWriter)
- private
- FBaseElementID: String;
- FIDPrefix : String;
- procedure AppendStats(AParent: TJSElement; ATiming: TDateTime; ANumRuns, ANumErrors, ANumFailures, ANumIgnores: Integer);
- procedure SetBaseElementID(AValue: String);
- protected
- procedure PopIDPrefix(aPrefix: String);
- procedure PushIDPrefix(aPrefix: String);
- procedure SetSkipAddressInfo(AValue: Boolean); override;
- procedure SetSparse(AValue: Boolean); override;
- procedure WriteTestHeader(ATest: TTest; ALevel: integer; ACount: integer); override;
- procedure WriteTestFooter(ATest: TTest; ALevel: integer; ATiming: TDateTime); override;
- procedure WriteSuiteHeader(ATestSuite: TTestSuite; ALevel: integer); override;
- procedure WriteSuiteFooter(ATestSuite: TTestSuite; ALevel: integer;
- ATiming: TDateTime; ANumRuns: integer; ANumErrors: integer;
- ANumFailures: integer; ANumIgnores: integer); override;
- public
- constructor Create(aOwner: TComponent); override;
- destructor Destroy; override;
- procedure WriteHeader; override;
- procedure WriteResult(aResult: TTestResult); override;
- procedure AddFailure(ATest: TTest; AFailure: TTestFailure); override;
- procedure AddError(ATest: TTest; AError: TTestFailure); override;
- // Base element ID where to display the testsuite. Default is 'fpcunit'
- Property BaseElementID : String Read FBaseElementID Write SetBaseElementID;
- end;
- implementation
- { TTestTreeBuilder }
- constructor TTestTreeBuilder.create(aBaseElementID: String);
- begin
- FBaseElementID:=aBaseElementID;
- if FBaseElementID='' then
- FBaseElementID:='fpcunit';
- FBaseElement:=document.getElementById(FBaseElementID);
- end;
- { THTMLTreeBuilder }
- procedure THTMLTreeBuilder.ShowStatsHeader(aParent : TJSElement);
- Var
- SEL : TJSHTMLELement;
- Procedure addc(s,i : string);
- var
- LEL : TJSHTMLELement;
- begin
- LEL:=TJSHTMLELement(document.CreateElement('li'));
- LEL.className:=S;
- SEL.AppendChild(LEL);
- LEL.InnerHTML:=i;
- end;
- begin
- SEL:=TJSHTMLELement(document.CreateElement('ul'));
- SEL.id:=FIDPrefix+'-stats';
- Addc('progress','Progress: <em>0</em>');
- Addc('passes','Pass: <em>0</em>');
- Addc('failures','Fail: <em>0</em>');
- Addc('duration','duration: <em>0</em> ms');
- aParent.Append(SEL);
- end;
- procedure THTMLTreeBuilder.ShowSuite(aSuite: TTestSuite);
- Var
- RU : TJSHTMLElement;
- N : TJSElement;
- begin
- FIDPrefix:=BaseElementID;
- if (BaseElement=Nil) then
- Console.error('No base element available to append test tree to!!');
- N:=BaseElement.firstElementChild;
- While (N<>Nil) do
- begin
- BaseElement.removeChild(N);
- N:=BaseElement.firstElementChild;
- end;
- ShowStatsHeader(BaseElement);
- RU:=TJSHTMLElement(document.createElement('ul'));
- BaseElement.appendChild(RU);
- AppendSuite(RU,aSuite,0);
- end;
- procedure THTMLTreeBuilder.PushIDPrefix(aPrefix : String) ;
- begin
- if aPrefix='' then
- exit;
- if (FIDPrefix<>'') then
- FIDPrefix:=FIDPrefix+'-';
- FIDPrefix:=FIDPrefix+aPrefix;
- end;
- procedure THTMLTreeBuilder.PopIDPrefix(aPrefix : String) ;
- Var
- L : integer;
- begin
- L:=Pos(aPrefix,FIDPrefix);
- if (L+Length(APrefix)-1)=Length(FIDPrefix) then
- FIDPrefix:=Copy(FIDPrefix,1,L-2);
- end;
- procedure THTMLTreeBuilder.AppendSuite(Parent : TJSElement; aSuite : TTestSuite; aLevel : integer);
- Var
- SE,SU,SH,Ti,TH : TJSHTMLElement;
- T : TTest;
- I : Integer;
- begin
- SE:=TJSHTMLElement(Document.createElement('li'));
- SE.ClassName:='suite level'+intToStr(aLevel);
- SH:=TJSHTMLElement(Document.createElement('h1'));
- if aLevel=0 then
- begin
- SH.innerText:='FPCUnit Test Suite'
- end
- else
- begin
- SH.innerText:=aSuite.TestName;
- end;
- SE.appendChild(SH);
- PushIDPrefix(aSuite.TestName);
- try
- if (aSuite.TestName='') then
- SE.id:=FIDPrefix+'-root-'+IntToStr(aLevel)
- else
- SE.id:=FIDPrefix;
- SU:=TJSHTMLElement(Document.createElement('ul'));
- SU.className:='suite level'+intToStr(aLevel);
- SE.AppendChild(SU);
- for I:=0 to aSuite.GetChildTestCount-1 do
- begin
- T:=asuite.GetChildTest(i);
- // Writeln('Examining ',T.TestSuiteName,'.',T.TestName,' (',t.className,')');
- if T is TTestSuite then
- AppendSuite(SU,t as TTestSuite, alevel+1)
- else
- begin
- ti:=TJSHTMLElement(document.CreateElement('li'));
- ti.className:='test pending';
- ti.id:=FIDPrefix+'-'+T.TestName;
- TH:=TJSHTMLElement(document.CreateElement('h2'));
- TH.innerText:=T.TestName;
- TI.AppendChild(th);
- SU.appendChild(ti);
- end;
- end;
- Parent.appendChild(SE);
- finally
- PopIDPrefix(aSuite.TestName);
- end;
- end;
- { THTMLResultsWriter }
- procedure THTMLResultsWriter.SetBaseElementID(AValue: String);
- begin
- if FBaseElementID=AValue then Exit;
- FBaseElementID:=AValue;
- FIDPrefix:=FBaseElementID;
- end;
- procedure THTMLResultsWriter.PopIDPrefix(aPrefix: String);
- Var
- L : integer;
- begin
- L:=Pos(aPrefix,FIDPrefix);
- if (L+Length(APrefix)-1)=Length(FIDPrefix) then
- FIDPrefix:=Copy(FIDPrefix,1,L-2);
- end;
- procedure THTMLResultsWriter.PushIDPrefix(aPrefix: String);
- begin
- if aPrefix='' then
- exit;
- if (FIDPrefix<>'') then
- FIDPrefix:=FIDPrefix+'-';
- FIDPrefix:=FIDPrefix+aPrefix;
- end;
- procedure THTMLResultsWriter.SetSkipAddressInfo(AValue: Boolean);
- begin
- inherited SetSkipAddressInfo(AValue);
- end;
- procedure THTMLResultsWriter.SetSparse(AValue: Boolean);
- begin
- inherited SetSparse(AValue);
- end;
- procedure THTMLResultsWriter.WriteTestHeader(ATest: TTest; ALevel: integer; ACount: integer);
- begin
- inherited WriteTestHeader(ATest, ALevel, ACount);
- end;
- procedure THTMLResultsWriter.WriteTestFooter(ATest: TTest; ALevel: integer; ATiming: TDateTime);
- Var
- E : TJSHTMLElement;
- S : String;
- p : integer;
- begin
- inherited WriteTestFooter(ATest, ALevel, ATiming);
- // console.info('Attempting to find test '+FIDPrefix+'-'+ATest.Testname);
- E:=TJSHTMLElement(Document.getElementById(FIDPrefix+'-'+ATest.Testname));
- if not Assigned(E) then
- console.Error('Failed to find test '+FIDPrefix+'-'+ATest.Testname)
- else
- begin
- S:=E.Classname;
- P:=Pos(' pending',s);
- if (P>0) then
- system.delete(S,P,8);
- if (Pos(' fail',S)=0) and (Pos(' error',S)=0) then
- S:=S+' pass';
- E.ClassName:=S;
- end;
- end;
- procedure THTMLResultsWriter.WriteSuiteHeader(ATestSuite: TTestSuite; ALevel: integer);
- begin
- inherited WriteSuiteHeader(ATestSuite, ALevel);
- PushIDPrefix(ATestSuite.TestName);
- end;
- procedure THTMLResultsWriter.AppendStats(AParent : TJSElement;ATiming : TDateTime; ANumRuns, ANumErrors, ANumFailures, ANumIgnores : Integer);
- Procedure addc(s,i : string);
- var
- LEL : TJSHTMLELement;
- begin
- LEL:=TJSHTMLELement(document.CreateElement('li'));
- LEL.className:=S;
- aParent.AppendChild(LEL);
- LEL.InnerHTML:=i;
- end;
- begin
- AParent.innerHTML:='';
- Addc('progress','Count: <em>'+IntToStr(ANumRuns)+'</em>');
- Addc('passes','Pass: <em>'+IntToStr(ANumRuns-ANumFailures-ANumErrors-ANumIgnores)+'</em>');
- Addc('failures','Fail: <em>'+IntToStr(ANumFailures)+'</em>');
- Addc('errors','Error: <em>'+IntToStr(ANumErrors)+'</em>');
- Addc('ignores','Ignore: <em>'+IntToStr(ANumIgnores)+'</em>');
- Addc('duration','duration: <em>'+TimeToStr(ATiming)+'</em> ms');
- end;
- procedure THTMLResultsWriter.WriteSuiteFooter(ATestSuite: TTestSuite; ALevel: integer; ATiming: TDateTime; ANumRuns: integer;
- ANumErrors: integer; ANumFailures: integer; ANumIgnores: integer);
- Var
- E : TJSHTMLElement;
- begin
- inherited WriteSuiteFooter(ATestSuite, ALevel, ATiming, ANumRuns, ANumErrors, ANumFailures, ANumIgnores);
- // console.info('Level',aLevel,'Attempting to find suite '+FIDPrefix);
- if (ALevel=0) or (FIDPrefix='') then
- begin
- E:=TJSHTMLElement(Document.getElementById(BaseElementID+'-stats'));
- if Not Assigned(E) then
- begin
- console.error('Failed to find '+FIDPrefix);
- exit;
- end;
- AppendStats(E,ATiming, ANumRuns, ANumErrors, ANumFailures, ANumIgnores);
- end
- else
- begin
- E:=TJSHTMLElement(Document.getElementById(FIDPrefix));
- if Not Assigned(E) then
- begin
- console.error('Failed to find '+FIDPrefix);
- exit;
- end;
- if ANumFailures+ANumErrors>0 then
- begin
- E.className:=E.className+' fail';
- end
- else
- begin
- E.className:=E.className+' pass';
- end;
- end;
- PopIDPrefix(ATestSuite.TestName);
- end;
- constructor THTMLResultsWriter.Create(aOwner: TComponent);
- begin
- inherited Create(aOwner);
- BaseElementID:='fpcunit';
- end;
- destructor THTMLResultsWriter.Destroy;
- begin
- inherited Destroy;
- end;
- procedure THTMLResultsWriter.WriteHeader;
- begin
- inherited WriteHeader;
- end;
- procedure THTMLResultsWriter.WriteResult(aResult: TTestResult);
- begin
- inherited WriteResult(aResult);
- console.info('Test result: ', aResult);
- end;
- procedure THTMLResultsWriter.AddFailure(ATest: TTest; AFailure: TTestFailure);
- Var
- E,Err : TJSHTMLElement;
- begin
- inherited addFailure(aTest,aFailure);
- if ATest is TTestSuite then exit;
- // console.info('Attempting to find test (for failure) '+FIDPrefix+'-'+aTest.TestName);
- E:=TJSHTMLElement(Document.getElementById(FIDPrefix+'-'+aTest.TestName));
- if Not Assigned(E) then
- console.error('Failed to find fail test'+FIDPrefix+'-'+aTest.TestName)
- else
- begin
- if AFailure.IsIgnoredTest then
- E.className:=E.className+' ignore'
- else
- E.className:=E.className+' fail';
- err:=TJSHTMLElement(document.createElement('pre'));
- Err.InnerText:=AFailure.ExceptionClass.ClassName+' : '+AFailure.ExceptionMessage;
- e.AppendChild(err);
- end;
- end;
- procedure THTMLResultsWriter.AddError(ATest: TTest; AError: TTestFailure);
- Var
- E,Err : TJSHTMLElement;
- begin
- inherited AddError(ATest, AError);
- if ATest is TTestSuite then exit;
- // console.info('Attempting to find test (for error) '+FIDPrefix+'-'+aTest.TestName);
- E:=TJSHTMLElement(Document.getElementById(FIDPrefix+'-'+aTest.TestName));
- if Not Assigned(E) then
- console.error('Failed to find error test '+FIDPrefix+'-'+aTest.TestName)
- else
- begin
- E.className:=E.className+' error';
- err:=TJSHTMLElement(document.createElement('pre'));
- Err.InnerText:=AError.ExceptionClass.ClassName+' : '+AError.ExceptionMessage;
- e.AppendChild(err);
- end;
- end;
- end.
|