lazarus/components/fpcunit/testinsight/testinsightprotocol.pas
2023-11-25 22:26:14 +01:00

384 lines
8.9 KiB
ObjectPascal

unit TestInsightProtocol;
{$mode ObjFPC}{$H+}
interface
uses
Classes, SysUtils, fpJSON;
Type
ETestInsight = class(Exception);
TTestResultType = (rtUnknown, rtPassed, rtFailed, rtError, rtWarning, rtSkipped, rtRunning);
TTestPhase = (tpSetUp, tpRunTest, spTearDown, tpNothing);
{ TTestInsightResult }
TTestInsightResult = Class
Public
TestResult : TTestResultType;
TestName: string;
TestDuration: Cardinal;
TestUnitName: string;
TestClassName: string;
TestMethodName: string;
// Status
TestStatus: string;
TestExceptionMessage: string;
TestExceptionClass: string;
TestIsIgnored : Boolean;
TestPhase : TTestPhase;
// Failure info
FailureUnitName: string;
FailureMethodName: string;
FailureLineNumber: Integer;
FailureSourceUnitName : String; // Exception
FailureLocationInfo : String;
Constructor Create; virtual;
procedure FromJSON(const aJSON : TJSONStringType); overload;
procedure FromJSON(const aJSON : TJSONObject); overload;
function ToJSON: string;
Procedure ToJSON(aJSON : TJSONObject);
end;
TTestInsightResultClass = Class of TTestInsightResult;
TTestInsightResultArray = Array of TTestInsightResult;
{ TTestInsightOptions }
TTestInsightOptions = Class (TPersistent)
Public
ExecuteTests: Boolean;
ShowProgress: Boolean;
TestSuite : String;
Constructor Create; virtual;
Procedure Assign(Source : TPersistent); override;
procedure FromJSON(const aJSON : TJSONStringType); overload;
procedure FromJSON(const aJSON : TJSONObject); overload;
function ToJSON: string;
Procedure ToJSON(aJSON : TJSONObject);
end;
TTestInsightOptionsClass = Class of TTestInsightOptions;
Const
// Used in URLS
DefaultUrl = 'http://localhost:8081/tests';
pathTests = '/tests';
pathStarted = 'started';
pathFinished = 'finished';
pathResults = 'results';
pathOptions = 'options';
qryTotalCount = 'totalcount';
// Used in TTestInsightResult JSON encoding.
keyTestName = 'testname';
KeyTestUnitName = 'testunitname';
keyTestClassName = 'testclassname';
keyTestMethodName = 'testmethodname';
keyTestDuration = 'testduration';
keyResultType = 'testresulttype';
keyExceptionMessage = 'exceptionmessage';
KeyExceptionClass = 'exceptionclass';
keyfailureMethodName = 'failuremethodname';
keyFailureUnitName = 'failureunitname';
keyFailureLineNumber = 'failurelinenumber';
KeyFailureSourceUnitName = 'failuresourceunitname';
KeyFailureLocationInfo = 'location';
keyStatus = 'status';
keyIsIgnored = 'ignored';
KeyTestPhase = 'phase';
// Config file settings
SConfig = 'Config';
KeyBaseURL = 'BaseUrl';
// Used in TTestInsightOptions JSON encoding and Ini file
keyExecuteTests = 'ExecuteTests';
keyShowProgress = 'ShowProgress';
KeySuite = 'Suite';
ResultTypeNames: array[TTestResultType] of string
= ('?','Passed', 'Failed', 'Error', 'Warning', 'Skipped', 'Running');
TestPhaseNames: array[TTestPhase] of string
= ('Setup', 'Run', 'TearDown','');
Function StringToResultType(aValue : string) : TTestResultType;
Function ResultTypeToString(aValue : TTestResultType) : string;
Function StringToTestPhase(aValue : string) : TTestPhase;
Function TestPhaseToString(aValue : TTestPhase) : string;
// Convert CR/LF separated list name to expected JSON format
Function TestStringsToJSON(aContent : String): TJSONObject;
implementation
Function ResultTypeToString(aValue : TTestResultType) : string;
begin
Result:=ResultTypeNames[aValue];
end;
function StringToTestPhase(aValue: string): TTestPhase;
Var
T : TTestPhase;
begin
Result:=tpNothing;
For T in TTestPhase do
if SameText(TestPhaseNames[T],aValue) then
Exit(T);
end;
function TestPhaseToString(aValue: TTestPhase): string;
begin
Result:=TestPhaseNames[aValue];
end;
Function StringToResultType(aValue : string) : TTestResultType;
Var
T : TTestResultType;
begin
Result:=rtFailed;
For T in TTestResultType do
if SameText(ResultTypeNames[T],aValue) then
Exit(T);
end;
Procedure AddTests(aParent : TJSONObject; aList : TStrings; aPath : String; var aIdx : Integer);
Var
P : integer;
Up : Boolean;
Curr,Sub : String;
Obj : TJSONObject;
begin
Repeat
Curr:=aList[aIdx];
Up:=(aPath<>'') and Not SameText(Copy(Curr,1,Length(aPath)),aPath);
if not Up then
begin
Delete(Curr,1,Length(aPath));
if Curr[1]='.' then delete(Curr,1,1);
P:=Pos('.',Curr);
if P<>0 then
begin
Sub:=Copy(Curr,1,P-1);
Obj:=TJSONObject.Create;
aParent.Add(Sub,Obj);
if aPath<>'' then
AddTests(Obj,aList,APath+'.'+Sub,aIdx)
else
AddTests(Obj,aList,Sub,aIdx)
end
else
begin
aParent.Add(Curr,TJSONNull.Create);
Inc(aIdx);
end;
end
Until (aIdx>=aList.Count) or Up;
end;
Function TestStringsToJSON(aContent : String): TJSONObject;
Var
L : TStringList;
aPath : String;
aIdx : Integer;
begin
Result:=nil;
L:=TStringList.Create;
try
L.Text:=aContent;
L.Sort;
Result:=TJSONObject.Create;
aPath:='';
aIdx:=0;
AddTests(Result,L,aPath,aIdx);
finally
L.Free;
end;
end;
{ TTestInsightOptions }
constructor TTestInsightOptions.Create;
begin
ExecuteTests:=True;
ShowProgress:=True;
end;
procedure TTestInsightOptions.Assign(Source: TPersistent);
var
Src : TTestInsightOptions absolute source;
begin
if Source is TTestInsightOptions then
begin
ExecuteTests:=Src.ExecuteTests;
ShowProgress:=Src.ShowProgress;
TestSuite:=Src.TestSuite;
end
else
inherited Assign(Source);
end;
procedure TTestInsightOptions.FromJSON(const aJSON: TJSONStringType);
Var
D : TJSONData;
begin
D:=GetJSON(aJSON);
try
if D is TJSONObject then
FromJSON(D as TJSONObject);
finally
D.Free;
end;
end;
procedure TTestInsightOptions.FromJSON(const aJSON: TJSONObject);
begin
with aJSON do
begin
ExecuteTests:=Get(KeyExecuteTests,ExecuteTests);
ShowProgress:=Get(KeyShowProgress,ShowProgress);
TestSuite:=Get(KeySuite,TestSuite);
end;
end;
function TTestInsightOptions.ToJSON: string;
Var
Obj : TJSONObject;
begin
Obj:=TJSONObject.Create;
try
ToJSON(Obj);
Result := Obj.AsJSON;
finally
Obj.Free;
end;
end;
procedure TTestInsightOptions.ToJSON(aJSON: TJSONObject);
begin
with aJSON do
begin
Add(KeyExecuteTests,ExecuteTests);
Add(KeyShowProgress,ShowProgress);
Add(KeySuite,TestSuite);
end;
end;
{ TTestInsightResult }
constructor TTestInsightResult.Create;
begin
TestResult:=rtUnknown;
end;
procedure TTestInsightResult.FromJSON(const aJSON: TJSONStringType);
Var
D : TJSONData;
begin
D:=GetJSON(aJSON);
try
if D is TJSONObject then
FromJSON(D as TJSONObject);
finally
D.Free;
end;
end;
procedure TTestInsightResult.FromJSON(const aJSON: TJSONObject);
begin
With aJSON Do
begin
TestName:=Get(KeyTestName, TestName);
TestUnitName:=Get(KeyTestUnitName, TestUnitName);
TestClassName:=Get(KeyTestClassName, TestClassName);
TestMethodName:=Get(KeyTestMethodName, TestMethodName);
TestResult:=StringToResultType(Get(KeyResultType, ResultTypeNames[TestResult]));
TestDuration:=Get(KeyTestDuration, TestDuration);
TestStatus:=Get(Keystatus, TestStatus);
TestIsIgnored:=Get(keyIsIgnored,TestIsIgnored);
TestPhase:=StringToTestPhase(Get(KeyTestPhase,TestPhaseToString(TestPhase)));
TestExceptionMessage:=Get(KeyExceptionMessage, TestExceptionMessage);
TestExceptionClass:=Get(KeyExceptionClass, TestExceptionClass);
FailureUnitName:=Get(KeyFailureUnitName, FailureUnitName);
FailureMethodName:=Get(KeyFailureMethodName, FailureMethodName);
FailureLineNumber:=Get(KeyFailureLineNumber, FailureLineNumber);
FailureSourceUnitName:=Get(KeyFailureSourceUnitName,FailureSourceUnitName);
FailureLocationInfo:=Get(KeyFailureLocationInfo,FailureLocationInfo);
end;
end;
function TTestInsightResult.ToJSON: string;
Var
Obj : TJSONObject;
begin
Obj:=TJSONObject.Create;
try
ToJSON(Obj);
Result := Obj.AsJSON;
finally
Free;
end;
end;
procedure TTestInsightResult.ToJSON(aJSON: TJSONObject);
begin
With aJSON do
begin
Add(KeyTestname, TestName);
Add(KeyTestUnitName, TestUnitName);
Add(KeyTestClassName, TestClassName);
Add(KeyTestMethodName,TestMethodName);
Add(KeyResultType, ResultTypeNames[TestResult]);
Add(KeyTestDuration, TestDuration);
Add(KeyStatus, TestStatus);
Add(keyIsIgnored,TestIsIgnored);
Add(KeyTestPhase,TestPhaseToString(TestPhase));
Add(KeyExceptionMessage, TestExceptionMessage);
Add(KeyExceptionClass, TestExceptionClass);
Add(KeyFailureUnitName, FailureUnitName);
Add(KeyFailureMethodName, FailureMethodName);
Add(KeyFailureLinenumber, FailureLineNumber);
Add(KeyFailureSourceUnitName,FailureSourceUnitName);
Add(KeyFailureLocationInfo,FailureLocationInfo);
end;
end;
end.