* Rework test tree construction, finding tests (bug ID 30384)

git-svn-id: trunk@34473 -
This commit is contained in:
michael 2016-09-10 10:17:20 +00:00
parent 627e30f47f
commit 1e36144e87
6 changed files with 155 additions and 125 deletions

View File

@ -314,60 +314,11 @@ end;
procedure TTestRunner.DoRun; procedure TTestRunner.DoRun;
procedure CheckTestRegistry (test:TTest; ATestName:string; res : TTestSuite);
var s, c : string;
I, p : integer;
ds : TTestSuite;
D : TTestDecorator;
begin
if (test is TTestSuite) or (test is TTestDecorator) then
begin
p := pos ('.', ATestName);
if p > 0 then
begin
s := copy (ATestName, 1, p-1);
c := copy (ATestName, p+1, maxint);
end
else
begin
s := '';
c := ATestName;
end;
if comparetext(c, test.TestName) = 0 then
res.AddTest(test)
else if (CompareText( s, Test.TestName) = 0) or (s = '') then
begin
if (test is ttestsuite) then
begin
for I := 0 to TTestSuite(test).ChildTestCount - 1 do
CheckTestRegistry ((test as TTestSuite).Test[I], c, res)
end
else if (test is TTestDecorator) then
begin
DS:=TDecoratorTestSuite.Create;
CheckTestRegistry(TTest((test as TTestDecorator).Test), c, ds);
if (ds.CountTestCases>0) then
begin
D:=TTestDecoratorClass(Test.ClassType).Create(DS);
Res.AddTest(D);
end
else
DS.free;
end;
end;
end
else // if test is TTestCase then
begin
if comparetext(test.TestName, ATestName) = 0 then
res.AddTest(test);
end;
end;
var var
I,P : integer; I,P : integer;
S : string; S,TN : string;
TS : TDecoratorTestSuite; TS : TDecoratorTestSuite;
T : TTest;
begin begin
S := CheckOptions(GetShortOpts, LongOpts); S := CheckOptions(GetShortOpts, LongOpts);
@ -383,7 +334,7 @@ begin
fPlain: Write(GetSuiteAsPlain(GetTestRegistry)); fPlain: Write(GetSuiteAsPlain(GetTestRegistry));
fPlainNoTiming: Write(GetSuiteAsPlain(GetTestRegistry)); fPlainNoTiming: Write(GetSuiteAsPlain(GetTestRegistry));
else else
Write(GetSuiteAsXml(GetTestRegistry));; Write(GetSuiteAsXml(GetTestRegistry));
end; end;
//run the tests //run the tests
@ -400,19 +351,17 @@ begin
try try
while Not(S = '') Do while Not(S = '') Do
begin begin
P:=Pos(',',S); P:=Pos(',',S);
if P = 0 Then If P=0 then
begin P:=Length(S)+1;
for I := 0 to GetTestRegistry.ChildTestCount-1 do TN:=Copy(S,1,P-1);
CheckTestRegistry (GetTestregistry[I], S, TS); Delete(S,1,P);
S := ''; if (TN<>'') then
end begin
else T:=GetTestRegistry.FindTest(TN);
begin if Assigned(T) then
for I := 0 to GetTestRegistry.ChildTestCount-1 do TS.AddTest(T);
CheckTestRegistry (GetTestregistry[I],Copy(S, 1,P - 1), TS); end;
Delete(S, 1, P);
end;
end; end;
if (TS.CountTestCases>1) then if (TS.CountTestCases>1) then
DoTestRun(TS) DoTestRun(TS)

View File

@ -54,7 +54,11 @@ type
TTestSuite = class; TTestSuite = class;
{$M+} {$M+}
{ TTest }
TTest = class(TObject) TTest = class(TObject)
private
protected protected
FLastStep: TTestStep; FLastStep: TTestStep;
function GetTestName: string; virtual; function GetTestName: string; virtual;
@ -64,6 +68,10 @@ type
procedure SetEnableIgnores(Value: boolean); virtual; abstract; procedure SetEnableIgnores(Value: boolean); virtual; abstract;
public public
function CountTestCases: integer; virtual; function CountTestCases: integer; virtual;
Function GetChildTestCount : Integer; virtual;
Function GetChildTest(AIndex : Integer) : TTest; virtual;
function FindChildTest(const AName: String): TTest;
Function FindTest(Const AName : String) : TTest;
procedure Run(AResult: TTestResult); virtual; procedure Run(AResult: TTestResult); virtual;
procedure Ignore(const AMessage: string); procedure Ignore(const AMessage: string);
published published
@ -240,8 +248,6 @@ type
FName: string; FName: string;
FTestSuiteName: string; FTestSuiteName: string;
FEnableIgnores: boolean; FEnableIgnores: boolean;
function GetTest(Index: integer): TTest;
function GetTestCount: Integer;
protected protected
Function DoAddTest(ATest : TTest) : Integer; Function DoAddTest(ATest : TTest) : Integer;
function GetTestName: string; override; function GetTestName: string; override;
@ -258,13 +264,15 @@ type
constructor Create; reintroduce; overload; virtual; constructor Create; reintroduce; overload; virtual;
destructor Destroy; override; destructor Destroy; override;
function CountTestCases: integer; override; function CountTestCases: integer; override;
Function GetChildTestCount : Integer; override;
Function GetChildTest(AIndex : Integer) : TTest; override;
procedure Run(AResult: TTestResult); override; procedure Run(AResult: TTestResult); override;
procedure RunTest(ATest: TTest; AResult: TTestResult); virtual; procedure RunTest(ATest: TTest; AResult: TTestResult); virtual;
procedure AddTest(ATest: TTest); overload; virtual; procedure AddTest(ATest: TTest); overload; virtual;
procedure AddTestSuiteFromClass(ATestClass: TClass); virtual; procedure AddTestSuiteFromClass(ATestClass: TClass); virtual;
class function Warning(const aMessage: string): TTestCase; class function Warning(const aMessage: string): TTestCase;
property Test[Index: integer]: TTest read GetTest; default; property Test[Index: integer]: TTest read GetChildTest; default;
Property ChildTestCount : Integer Read GetTestCount; Property ChildTestCount : Integer Read GetChildTestCount;
property TestSuiteName: string read GetTestSuiteName write SetTestSuiteName; property TestSuiteName: string read GetTestSuiteName write SetTestSuiteName;
property TestName: string read GetTestName write SetTestName; property TestName: string read GetTestName write SetTestName;
// Only for backwards compatibility. Use Test and ChildTestCount. // Only for backwards compatibility. Use Test and ChildTestCount.
@ -538,6 +546,65 @@ begin
Result := 0; Result := 0;
end; end;
function TTest.GetChildTestCount: Integer;
begin
Result:=0;
end;
function TTest.GetChildTest(AIndex: Integer): TTest;
begin
Result:=Nil;
end;
function TTest.FindChildTest(const AName: String): TTest;
Var
I : Integer;
begin
Result:=Nil;
I:=GetChildTestCount-1;
While (Result=Nil) and (I>=0) do
begin
Result:=GetChildTest(I);
if CompareText(Result.TestName,AName)<>0 then
Result:=Nil;
Dec(I);
end;
end;
function TTest.FindTest(const AName: String): TTest;
Var
S : String;
I,P : Integer;
begin
Result:=Nil;
S:=AName;
if S='' then exit;
P:=Pos('.',S);
If (P=0) then
P:=Length(S)+1;
Result:=FindChildTest(Copy(S,1,P-1));
if (Result<>Nil) then
begin
Delete(S,1,P);
If (S<>'') then
Result:=Result.FindTest(S);
end
else
begin
P:=GetChildTestCount;
I:=0;
While (Result=Nil) and (I<P) do
begin
Result:=GetChildTest(I).FindTest(Aname);
Inc(I);
end;
end;
end;
function TTest.GetEnableIgnores: boolean; function TTest.GetEnableIgnores: boolean;
begin begin
Result := True; Result := True;
@ -548,7 +615,7 @@ begin
{ do nothing } { do nothing }
end; end;
procedure TTest.Ignore(const AMessage: String); procedure TTest.Ignore(const AMessage: string);
begin begin
if EnableIgnores then raise EIgnoredTest.Create(AMessage); if EnableIgnores then raise EIgnoredTest.Create(AMessage);
end; end;
@ -1197,12 +1264,12 @@ begin
end; end;
function TTestSuite.GetTest(Index: integer): TTest; function TTestSuite.GetChildTest(AIndex: integer): TTest;
begin begin
Result := TTestItem(FTests[Index]).Test; Result := TTestItem(FTests[AIndex]).Test;
end; end;
function TTestSuite.GetTestCount: Integer; function TTestSuite.GetChildTestCount: Integer;
begin begin
Result:=FTests.Count; Result:=FTests.Count;
end; end;

View File

@ -51,7 +51,7 @@ type
procedure EndTest(ATest: TTest); override; procedure EndTest(ATest: TTest); override;
end; end;
function TestSuiteAsLatex(aSuite:TTestSuite): string; function TestSuiteAsLatex(aSuite:TTest): string;
function GetSuiteAsLatex(aSuite: TTestSuite): string; function GetSuiteAsLatex(aSuite: TTestSuite): string;
implementation implementation
@ -250,27 +250,26 @@ begin
end; end;
function TestSuiteAsLatex(aSuite:TTestSuite): string; function TestSuiteAsLatex(aSuite:TTest): string;
var var
i,j: integer; i,j: integer;
s: TTestSuite; s: TTestSuite;
begin begin
Result := TLatexResultsWriter.EscapeText(aSuite.TestSuiteName) + System.sLineBreak; Result:='';
Result := Result + '\begin{itemize}'+ System.sLineBreak; if (aSuite.TestName<>'') then
for i := 0 to aSuite.ChildTestCount - 1 do begin
if ASuite.Test[i] is TTestSuite then Result:=Result + '\item[-] ';
begin Result:=Result+TLatexResultsWriter.EscapeText(ASuite.TestName)+slineBreak
Result:=Result + '\item[-] '; end;
Result := Result + '\flushleft' + System.sLineBreak; if aSuite.GetChildTestCount>0 then
Result:=Result+TestSuiteAsLatex(TTestSuite(ASuite.Test[i]))+System.sLineBreak; begin
end Result := Result + '\begin{itemize}'+ System.sLineBreak;
else for i:=0 to Pred(aSuite.GetChildTestCount) do
begin Result:=Result+TestSuiteAsLatex(aSuite.GetChildTest(i));
Result := Result + '\item[-] ' + if (aSuite.TestName<>'') then
TLatexResultsWriter.EscapeText(TTestcase(aSuite.Test[i]).TestName) Result := Result +'\end{itemize}' + System.sLineBreak;
+ System.sLineBreak; end
end;
Result := Result +'\end{itemize}' + System.sLineBreak;
end; end;
@ -284,7 +283,9 @@ begin
Result := Result + '\begin{document}' + System.sLineBreak + System.sLineBreak; Result := Result + '\begin{document}' + System.sLineBreak + System.sLineBreak;
if aSuite.TestName = '' then if aSuite.TestName = '' then
aSuite.TestName := 'Test Suite'; aSuite.TestName := 'Test Suite';
Result := Result + '\begin{itemize}'+ System.sLineBreak;
Result := Result + TestSuiteAsLatex(aSuite); Result := Result + TestSuiteAsLatex(aSuite);
Result := Result +'\end{itemize}' + System.sLineBreak;
Result := Result + '\end{document}'; Result := Result + '\end{document}';
end end
else else

View File

@ -19,7 +19,7 @@ unit plaintestreport;
interface interface
uses uses
classes, SysUtils, fpcunit, fpcunitreport; classes, SysUtils, fpcunit, fpcunitreport, testdecorator;
type type
TTestResultOption = (ttoSkipAddress,ttoSkipExceptionMessage,ttoErrorsOnly); TTestResultOption = (ttoSkipAddress,ttoSkipExceptionMessage,ttoErrorsOnly);
@ -208,22 +208,21 @@ begin
FSuiteHeaderIdx.Add(Pointer(FDoc.Count - 1)); FSuiteHeaderIdx.Add(Pointer(FDoc.Count - 1));
end; end;
function DoTestSuiteAsPlain(aSuite:TTestSuite; Prefix : String; Options : TTestResultOptions = []): string; function DoTestSuiteAsPlain(aSuite:TTest; Prefix : String; Options : TTestResultOptions = []): string;
var var
i: integer; i: integer;
p : string;
begin begin
Result := Prefix+ASuite.TestName+System.sLineBreak; if (ASuite.TestSuiteName<>'') then
for i := 0 to aSuite.ChildTestCount - 1 do begin
if aSuite.Test[i] is TTestSuite then Prefix:=' '+Prefix;
begin Prefix:=Prefix+ASuite.TestSuiteName+'.';
P:=Prefix; end;
if (ASuite.TestName<>'') then if (ASuite.TestName<>'') then
P:=P+' '; Result := Prefix+ASuite.TestName+System.sLineBreak;
Result := Result + DoTestSuiteAsPlain(TTestSuite(aSuite.Test[i]),P,Options); for i := 0 to aSuite.GetChildTestCount - 1 do
end Result := Result + DoTestSuiteAsPlain(aSuite.GetChildTest(i),Prefix,Options);
else if aSuite.Test[i] is TTestCase then
Result := Result + Prefix+' ' + ASuite.TestName+'.' + TTestcase(aSuite.Test[i]).TestName + System.sLineBreak;
end; end;
function TestSuiteAsPlain(aSuite:TTestSuite; Options : TTestResultOptions = []): string; function TestSuiteAsPlain(aSuite:TTestSuite; Options : TTestResultOptions = []): string;

View File

@ -27,16 +27,18 @@ type
{ TTestDecorator } { TTestDecorator }
TTestDecorator = class(TAssert) TTestDecorator = class(TTest{Assert})
private private
FTest: TTest; FTest: TTest;
protected
function GetTestName: string; override; function GetTestName: string; override;
function GetTestSuiteName: string; override; function GetTestSuiteName: string; override;
procedure SetTestSuiteName(const aName: string); override; procedure SetTestSuiteName(const aName: string); override;
protected
function GetEnableIgnores: boolean; override; function GetEnableIgnores: boolean; override;
procedure SetEnableIgnores(Value: boolean); override; procedure SetEnableIgnores(Value: boolean); override;
public public
Function GetChildTest(AIndex: Integer): TTest; override;
Function GetChildTestCount : Integer; override;
function CountTestCases: integer; override; function CountTestCases: integer; override;
constructor Create(aTest: TTest); reintroduce; overload; constructor Create(aTest: TTest); reintroduce; overload;
destructor Destroy; override; destructor Destroy; override;
@ -84,6 +86,16 @@ begin
FTest.EnableIgnores := Value; FTest.EnableIgnores := Value;
end; end;
function TTestDecorator.GetChildTest(AIndex: Integer): TTest;
begin
Result:=FTest.GetChildTest(AIndex);
end;
function TTestDecorator.GetChildTestCount: Integer;
begin
Result:=FTest.GetChildTestCount;
end;
function TTestDecorator.CountTestCases: integer; function TTestDecorator.CountTestCases: integer;
begin begin
Result := FTest.CountTestCases; Result := FTest.CountTestCases;

View File

@ -70,7 +70,7 @@ type
end; end;
function GetSuiteAsXML(aSuite: TTestSuite): string; function GetSuiteAsXML(aSuite: TTestSuite): string;
function TestSuiteAsXML(n: TDOMElement; FDoc: TXMLDocument; aSuite:TTestSuite): string; function TestSuiteAsXML(n: TDOMElement; FDoc: TXMLDocument; aSuite:TTest): string;
implementation implementation
@ -93,35 +93,37 @@ begin
stream := TStringStream.Create(''); stream := TStringStream.Create('');
WriteXMLFile(FDoc, stream); WriteXMLFile(FDoc, stream);
writeln(stream.DataString); Result:=stream.DataString;
stream.Free; stream.Free;
end; end;
end; end;
function TestSuiteAsXML(n: TDOMElement; FDoc: TXMLDocument; aSuite:TTestSuite): string; function TestSuiteAsXML(n: TDOMElement; FDoc: TXMLDocument; aSuite:TTest): string;
var var
i: integer; i: integer;
E,T : TDomElement; E,T : TDomElement;
begin begin
if aSuite.TestName<>'' then Result:='';
if aSuite.GetChildTestCount>0 then
begin begin
E:=FDoc.CreateElement('Suite'); if (aSuite.TestName='') then
E['Name']:=aSuite.TestName; E:=N
N.AppendChild(E); else
begin
E:=FDoc.CreateElement('Suite');
E['Name']:=aSuite.TestName;
N.AppendChild(E);
end;
for i:=0 to Pred(aSuite.GetChildTestCount) do
TestSuiteAsXML(E,FDoc,aSuite.GetChildTest(i));
end end
else else
E:=N; begin
for i:=0 to Pred(aSuite.ChildTestCount) do T:=FDoc.CreateElement('Test');
if TTest(aSuite.Test[i]) is TTestSuite then T['name']:=aSuite.TestName;
TestSuiteAsXML(E, FDoc, TTestSuite(aSuite.Test[i])) N.AppendChild(T);
else end;
if TTest(aSuite.Test[i]) is TTestCase then
begin
T:=FDoc.CreateElement('Test');
T['name']:=TTestCase(aSuite.Test[i]).TestName;
E.AppendChild(T);
end;
end; end;