diff --git a/src/Tools/AI Test Toolkit/src/AITTestContext.Codeunit.al b/src/Tools/AI Test Toolkit/src/AITTestContext.Codeunit.al
index b168b50b7a..9a7deb7128 100644
--- a/src/Tools/AI Test Toolkit/src/AITTestContext.Codeunit.al
+++ b/src/Tools/AI Test Toolkit/src/AITTestContext.Codeunit.al
@@ -84,6 +84,16 @@ codeunit 149044 "AIT Test Context"
exit(AITTestContextImpl.GetExpectedData());
end;
+ ///
+ /// Gets the continue on failure flag for the current turn.
+ /// If the flag is not set in the test input, it defaults to false.
+ ///
+ /// True if the eval should continue on failure, false otherwise.
+ procedure GetCanContinueOnFailure(): Boolean
+ begin
+ exit(AITTestContextImpl.GetCanContinueOnFailure());
+ end;
+
///
/// Sets the answer for a question and answer evaluation.
/// This will also copy the context, question and ground truth to the output dataset.
@@ -204,6 +214,34 @@ codeunit 149044 "AIT Test Context"
AITTestContextImpl.SetTokenConsumption(TokensUsed);
end;
+ ///
+ /// Gets the per-suite setup data as a Test Input Json.
+ /// The consuming test app must have imported a YAML file with the suite_setup token.
+ ///
+ /// Test Input Json containing the suite setup data.
+ procedure GetEvalSuiteSetupDataInput(): Codeunit "Test Input Json"
+ begin
+ exit(AITTestContextImpl.GetEvalSuiteSetupDataInput());
+ end;
+
+ ///
+ /// Marks the per-suite setup as completed on the test suite record.
+ /// Call this after your suite setup logic has finished successfully.
+ ///
+ procedure SetEvalSuiteSetupCompleted()
+ begin
+ AITTestContextImpl.SetEvalSuiteSetupCompleted();
+ end;
+
+ ///
+ /// Checks if the per-suite setup has been marked as done on the test suite record.
+ ///
+ /// True if suite setup has been executed.
+ procedure IsSuiteSetupDone(): Boolean
+ begin
+ exit(AITTestContextImpl.IsSuiteSetupDone());
+ end;
+
///
/// Integration event that is raised after an eval run is completed.
///
diff --git a/src/Tools/AI Test Toolkit/src/AITTestContextImpl.Codeunit.al b/src/Tools/AI Test Toolkit/src/AITTestContextImpl.Codeunit.al
index bf0807c649..15b1f8cf5c 100644
--- a/src/Tools/AI Test Toolkit/src/AITTestContextImpl.Codeunit.al
+++ b/src/Tools/AI Test Toolkit/src/AITTestContextImpl.Codeunit.al
@@ -18,6 +18,7 @@ codeunit 149043 "AIT Test Context Impl."
var
AITTestSuiteMgt: Codeunit "AIT Test Suite Mgt.";
GlobalTestOutputJson: Codeunit "Test Output Json";
+ GlobalSuiteSetupJson: Codeunit "Test Input Json";
GlobalAccuracy: Decimal;
CurrentTurn: Integer;
NumberOfTurns: Integer;
@@ -29,6 +30,7 @@ codeunit 149043 "AIT Test Context Impl."
ContextTok: Label 'context', Locked = true;
GroundTruthTok: Label 'ground_truth', Locked = true;
ExpectedDataTok: Label 'expected_data', Locked = true;
+ ContinueOnFailureTok: Label 'continue_on_failure', Locked = true;
TestMetricsTok: Label 'test_metrics', Locked = true;
TestSetupTok: Label 'test_setup', Locked = true;
QuestionTok: Label 'question', Locked = true;
@@ -39,6 +41,9 @@ codeunit 149043 "AIT Test Context Impl."
RoleTok: Label 'role', Locked = true;
ContentTok: Label 'content', Locked = true;
ConversationTok: Label 'conversation', Locked = true;
+ HasSuiteSetupData: Boolean;
+ SuiteSetupDataNotLoadedErr: Label 'Per-suite setup data has not been loaded.';
+ SuiteSetupInputCodeTok: Label 'SUITE-SETUP', Locked = true;
///
/// Returns the Test Input value as Test Input Json Codeunit from the input dataset for the current iteration.
@@ -97,6 +102,23 @@ codeunit 149043 "AIT Test Context Impl."
exit(GetTestInput(ExpectedDataTok));
end;
+ ///
+ /// Gets the continue on failure flag for the current turn.
+ /// If the flag is not set in the test input, it defaults to false.
+ ///
+ /// True if the eval should continue on failure, false otherwise.
+ procedure GetCanContinueOnFailure(): Boolean
+ var
+ ContinueOnFailureInput: Codeunit "Test Input Json";
+ ElementFound: Boolean;
+ begin
+ ContinueOnFailureInput := GetTestInput(ContinueOnFailureTok, ElementFound);
+ if not ElementFound then
+ exit(false);
+
+ exit(ContinueOnFailureInput.ValueAsBoolean());
+ end;
+
///
/// Sets the answer for a question and answer evaluation.
/// This will also copy the context, question and ground truth to the output dataset.
@@ -332,6 +354,58 @@ codeunit 149043 "AIT Test Context Impl."
NumberOfTurns := TurnsInputJson.GetElementCount()
else
NumberOfTurns := 1;
+
+ if not HasSuiteSetupData then
+ LoadSuiteSetupFromDataset();
+ end;
+
+ ///
+ /// Loads suite setup data from the dataset referenced by the current test's Test Input Group.
+ /// Resolves language variants using the suite's Run Language ID.
+ ///
+ local procedure LoadSuiteSetupFromDataset()
+ var
+ SuiteSetupGroup: Record "Test Input Group";
+ AITTestSuite: Record "AIT Test Suite";
+ TestInputCU: Codeunit "Test Input";
+ AITTestSuiteLanguage: Codeunit "AIT Test Suite Language";
+ SuiteSetupInputJson: Codeunit "Test Input Json";
+ ResolvedDatasetCode: Code[100];
+ begin
+ if not GetSuiteSetupGroup(SuiteSetupGroup) then
+ exit;
+
+ GetAITTestSuite(AITTestSuite);
+ ResolvedDatasetCode := AITTestSuiteLanguage.GetLanguageDataset(SuiteSetupGroup.Code, AITTestSuite."Run Language ID");
+ SuiteSetupInputJson := TestInputCU.GetTestInputByCode(ResolvedDatasetCode, SuiteSetupInputCodeTok);
+
+ if SuiteSetupInputJson.ToText() = '' then
+ exit;
+
+ ImportSuiteSetupData(SuiteSetupInputJson.AsJsonToken());
+ end;
+
+ ///
+ /// Finds the suite setup Test Input Group for the current test's dataset.
+ /// Navigates: AITTestMethodLine."Input Dataset" → TestInputGroup."Suite Setup Group Name" → target group.
+ ///
+ local procedure GetSuiteSetupGroup(var SuiteSetupGroup: Record "Test Input Group"): Boolean
+ var
+ AITTestMethodLine: Record "AIT Test Method Line";
+ DatasetGroup: Record "Test Input Group";
+ begin
+ GetAITTestMethodLine(AITTestMethodLine);
+ if AITTestMethodLine."Input Dataset" = '' then
+ exit(false);
+
+ if not DatasetGroup.Get(AITTestMethodLine."Input Dataset") then
+ exit(false);
+
+ if DatasetGroup."Suite Setup Group Name" = '' then
+ exit(false);
+
+ SuiteSetupGroup.SetRange("Group Name", DatasetGroup."Suite Setup Group Name");
+ exit(SuiteSetupGroup.FindFirst());
end;
///
@@ -349,6 +423,22 @@ codeunit 149043 "AIT Test Context Impl."
TestInputJson := TestInput.GetTestInput(ElementName);
end;
+ ///
+ /// Gets the test input for the provided element, returning whether the element was found.
+ ///
+ /// Element name to get from test input.
+ /// Set to true if the element exists.
+ /// Test Input Json for the element
+ local procedure GetTestInput(ElementName: Text; var ElementFound: Boolean) TestInputJson: Codeunit "Test Input Json"
+ var
+ TestInput: Codeunit "Test Input";
+ begin
+ if IsMultiTurn then
+ TestInputJson := TestInput.GetTestInput(TurnsTok).ElementAt(CurrentTurn - 1).ElementExists(ElementName, ElementFound)
+ else
+ TestInputJson := TestInput.GetTestInput().ElementExists(ElementName, ElementFound);
+ end;
+
///
/// Adds a message to the test output for the current iteration.
///
@@ -411,6 +501,52 @@ codeunit 149043 "AIT Test Context Impl."
CurrentTestOutputJson.Add(ElementName, TestInput.GetTestInput(ElementName).ValueAsText());
end;
+ ///
+ /// Sets the per-suite setup data from a parsed JSON token.
+ ///
+ /// The JSON token containing the parsed suite setup data.
+ internal procedure ImportSuiteSetupData(SuiteSetupJsonToken: JsonToken)
+ begin
+ GlobalSuiteSetupJson.Initialize(SuiteSetupJsonToken);
+ HasSuiteSetupData := true;
+ end;
+
+ ///
+ /// Gets the per-suite setup data as a Test Input Json.
+ ///
+ /// Test Input Json containing the suite setup data.
+ procedure GetEvalSuiteSetupDataInput(): Codeunit "Test Input Json"
+ begin
+ if not HasSuiteSetupData then
+ Error(SuiteSetupDataNotLoadedErr);
+ exit(GlobalSuiteSetupJson);
+ end;
+
+ ///
+ /// Marks the per-suite setup as completed on the suite setup test input group.
+ ///
+ procedure SetEvalSuiteSetupCompleted()
+ var
+ SuiteSetupGroup: Record "Test Input Group";
+ begin
+ if GetSuiteSetupGroup(SuiteSetupGroup) then
+ SuiteSetupGroup.SetSuiteSetupDone();
+ end;
+
+ ///
+ /// Checks if the per-suite setup has been marked as done on the suite setup test input group.
+ ///
+ /// True if suite setup has been executed.
+ procedure IsSuiteSetupDone(): Boolean
+ var
+ SuiteSetupGroup: Record "Test Input Group";
+ begin
+ if not GetSuiteSetupGroup(SuiteSetupGroup) then
+ exit(false);
+
+ exit(SuiteSetupGroup."Suite Setup Done");
+ end;
+
///
/// Sets the token consumption for the method line run. Useful if external calls are made outside of AI toolkit.
///
diff --git a/src/Tools/AI Test Toolkit/src/TestSuite/AITALTestSuiteMgt.Codeunit.al b/src/Tools/AI Test Toolkit/src/TestSuite/AITALTestSuiteMgt.Codeunit.al
index a7c6ebde3d..869cafd457 100644
--- a/src/Tools/AI Test Toolkit/src/TestSuite/AITALTestSuiteMgt.Codeunit.al
+++ b/src/Tools/AI Test Toolkit/src/TestSuite/AITALTestSuiteMgt.Codeunit.al
@@ -17,6 +17,7 @@ codeunit 149037 "AIT AL Test Suite Mgt"
var
RunProcedureOperationTok: Label 'Run Procedure', Locked = true;
AITTestSuitePrefixTok: Label 'AIT-', Locked = true;
+ InvalidSuiteSetupYamlErr: Label 'The per-suite setup content is not valid YAML.';
internal procedure GetDefaultRunProcedureOperationLbl(): Text
begin
@@ -224,6 +225,22 @@ codeunit 149037 "AIT AL Test Suite Mgt"
exit(OutputJsonArray);
end;
+ ///
+ /// Import per-suite setup data from YAML content.
+ /// The YAML is parsed and stored for access via AITTestContext.GetSuiteSetupData().
+ ///
+ /// The YAML content as text.
+ procedure ImportSuiteSetupData(SuiteSetupYamlContent: Text)
+ var
+ AITTestContextImpl: Codeunit "AIT Test Context Impl.";
+ SuiteSetupDataJsonObj: JsonObject;
+ begin
+ if not SuiteSetupDataJsonObj.ReadFromYaml(SuiteSetupYamlContent) then
+ Error(InvalidSuiteSetupYamlErr);
+
+ AITTestContextImpl.ImportSuiteSetupData(SuiteSetupDataJsonObj.AsToken());
+ end;
+
///
/// Import the Test Input Dataset from an InStream of a dataset in a supported format.
/// Overwrite the dataset if the dataset with same filename is already imported by the same app
diff --git a/src/Tools/AI Test Toolkit/src/TestSuite/AITTestMethodLines.Page.al b/src/Tools/AI Test Toolkit/src/TestSuite/AITTestMethodLines.Page.al
index 5034971f03..ae7c31fb63 100644
--- a/src/Tools/AI Test Toolkit/src/TestSuite/AITTestMethodLines.Page.al
+++ b/src/Tools/AI Test Toolkit/src/TestSuite/AITTestMethodLines.Page.al
@@ -5,6 +5,8 @@
namespace System.TestTools.AITestToolkit;
+using System.TestTools.TestRunner;
+
page 149034 "AIT Test Method Lines"
{
Caption = 'Evals';
@@ -239,6 +241,32 @@ page 149034 "AIT Test Method Lines"
CurrPage.Update(false);
end;
}
+ action(ResetSuiteSetup)
+ {
+ Caption = 'Reset Suite Setup';
+ ToolTip = 'Resets the per-suite setup flag so that the setup data can be created again.';
+ Image = ResetStatus;
+
+ trigger OnAction()
+ var
+ TestInputGroup: Record "Test Input Group";
+ SuiteSetupGroup: Record "Test Input Group";
+ InputDatasetCode: Code[100];
+ begin
+ InputDatasetCode := Rec.GetTestInputCode();
+ if not TestInputGroup.Get(InputDatasetCode) then
+ exit;
+
+ if TestInputGroup."Suite Setup Group Name" = '' then
+ exit;
+
+ SuiteSetupGroup.SetRange("Group Name", TestInputGroup."Suite Setup Group Name");
+ if SuiteSetupGroup.FindFirst() then begin
+ SuiteSetupGroup.ResetSuiteSetup();
+ CurrPage.Update(false);
+ end;
+ end;
+ }
action(LogEntries)
{
Caption = 'Log Entries';
diff --git a/src/Tools/AI Test Toolkit/src/TestSuite/AITTestSuite.Page.al b/src/Tools/AI Test Toolkit/src/TestSuite/AITTestSuite.Page.al
index 371ce3d411..a1a65bfc97 100644
--- a/src/Tools/AI Test Toolkit/src/TestSuite/AITTestSuite.Page.al
+++ b/src/Tools/AI Test Toolkit/src/TestSuite/AITTestSuite.Page.al
@@ -347,6 +347,18 @@ page 149031 "AIT Test Suite"
end;
}
+ action(ResetSuiteSetup)
+ {
+ Caption = 'Reset Suite Setup';
+ ToolTip = 'Resets the per-suite setup flag so that the setup can be run again.';
+ Image = ResetStatus;
+
+ trigger OnAction()
+ begin
+ Rec.ResetSuiteSetup();
+ CurrPage.Update(false);
+ end;
+ }
action(Compare)
{
Caption = 'View runs';
diff --git a/src/Tools/AI Test Toolkit/src/TestSuite/AITTestSuite.Table.al b/src/Tools/AI Test Toolkit/src/TestSuite/AITTestSuite.Table.al
index 092e268591..b818f13b7d 100644
--- a/src/Tools/AI Test Toolkit/src/TestSuite/AITTestSuite.Table.al
+++ b/src/Tools/AI Test Toolkit/src/TestSuite/AITTestSuite.Table.al
@@ -298,6 +298,22 @@ table 149030 "AIT Test Suite"
exit(AITTestSuiteLanguage.GetLanguageDataset(Rec."Input Dataset", Rec."Run Language ID"));
end;
+ internal procedure ResetSuiteSetup()
+ var
+ TestInputGroup: Record "Test Input Group";
+ SuiteSetupGroup: Record "Test Input Group";
+ begin
+ if not TestInputGroup.Get(Rec."Input Dataset") then
+ exit;
+
+ if TestInputGroup."Suite Setup Group Name" = '' then
+ exit;
+
+ SuiteSetupGroup.SetRange("Group Name", TestInputGroup."Suite Setup Group Name");
+ if SuiteSetupGroup.FindFirst() then
+ SuiteSetupGroup.ResetSuiteSetup();
+ end;
+
var
BaseVersionMustBeLessThanVersionErr: Label 'Base Version must be less than or equal to Version';
}
diff --git a/src/Tools/Test Framework/Test Runner/src/ALTestSuite.Table.al b/src/Tools/Test Framework/Test Runner/src/ALTestSuite.Table.al
index d375666665..a54af1de9b 100644
--- a/src/Tools/Test Framework/Test Runner/src/ALTestSuite.Table.al
+++ b/src/Tools/Test Framework/Test Runner/src/ALTestSuite.Table.al
@@ -115,5 +115,6 @@ table 130451 "AL Test Suite"
if "Test Runner Id" = 0 then
"Test Runner Id" := TestRunnerMgt.GetDefaultTestRunner();
end;
+
}
diff --git a/src/Tools/Test Framework/Test Runner/src/DataDrivenTest/DataInputs/TestInput.Codeunit.al b/src/Tools/Test Framework/Test Runner/src/DataDrivenTest/DataInputs/TestInput.Codeunit.al
index 10cf5c60c0..d76464e31d 100644
--- a/src/Tools/Test Framework/Test Runner/src/DataDrivenTest/DataInputs/TestInput.Codeunit.al
+++ b/src/Tools/Test Framework/Test Runner/src/DataDrivenTest/DataInputs/TestInput.Codeunit.al
@@ -66,6 +66,22 @@ codeunit 130460 "Test Input"
exit(DataPerTest.GetInput(DataPerTest));
end;
+ procedure GetTestInputByCode(GroupCode: Code[100]; InputCode: Code[100]): Codeunit "Test Input Json"
+ var
+ TestInputRec: Record "Test Input";
+ TestInputJson: Codeunit "Test Input Json";
+ InputContent: Text;
+ begin
+ if not TestInputRec.Get(GroupCode, InputCode) then
+ exit(TestInputJson);
+
+ InputContent := TestInputRec.GetInput(TestInputRec);
+ if InputContent <> '' then
+ TestInputJson.Initialize(InputContent);
+
+ exit(TestInputJson);
+ end;
+
var
DataPerTest: Record "Test Input";
DataPerTestTestInput: Codeunit "Test Input Json";
diff --git a/src/Tools/Test Framework/Test Runner/src/DataDrivenTest/DataInputs/TestInput.Page.al b/src/Tools/Test Framework/Test Runner/src/DataDrivenTest/DataInputs/TestInput.Page.al
index dd9a522edc..02339c890d 100644
--- a/src/Tools/Test Framework/Test Runner/src/DataDrivenTest/DataInputs/TestInput.Page.al
+++ b/src/Tools/Test Framework/Test Runner/src/DataDrivenTest/DataInputs/TestInput.Page.al
@@ -50,6 +50,10 @@ page 130457 "Test Input"
{
Editable = false;
}
+ field("Suite Setup Done"; Rec."Suite Setup Done")
+ {
+ Importance = Additional;
+ }
}
part(TestInputPart; "Test Input Part")
{
diff --git a/src/Tools/Test Framework/Test Runner/src/DataDrivenTest/DataInputs/TestInputGroup.Table.al b/src/Tools/Test Framework/Test Runner/src/DataDrivenTest/DataInputs/TestInputGroup.Table.al
index 988c6454ba..d82df9a631 100644
--- a/src/Tools/Test Framework/Test Runner/src/DataDrivenTest/DataInputs/TestInputGroup.Table.al
+++ b/src/Tools/Test Framework/Test Runner/src/DataDrivenTest/DataInputs/TestInputGroup.Table.al
@@ -113,6 +113,18 @@ table 130454 "Test Input Group"
ToolTip = 'Specifies the AppId from which the test input group was imported.';
DataClassification = SystemMetadata;
}
+ field(80; "Suite Setup Done"; Boolean)
+ {
+ Caption = 'Suite Setup Done';
+ ToolTip = 'Specifies whether the per-suite setup has been executed for this test input group.';
+ DataClassification = SystemMetadata;
+ }
+ field(81; "Suite Setup Group Name"; Text[250])
+ {
+ Caption = 'Suite Setup Group Name';
+ ToolTip = 'Specifies the group name of the test input group that contains suite setup data for this dataset.';
+ DataClassification = CustomerContent;
+ }
}
keys
{
@@ -218,6 +230,18 @@ table 130454 "Test Input Group"
ValidateGroups();
end;
+ procedure SetSuiteSetupDone()
+ begin
+ Rec."Suite Setup Done" := true;
+ Rec.Modify(true);
+ end;
+
+ procedure ResetSuiteSetup()
+ begin
+ Rec."Suite Setup Done" := false;
+ Rec.Modify(true);
+ end;
+
procedure GetTestInputGroupLanguages(TestInputCode: Code[100]; var LanguageVersions: Record "Test Input Group"): Boolean
begin
LanguageVersions.Reset();
diff --git a/src/Tools/Test Framework/Test Runner/src/DataDrivenTest/DataInputs/TestInputGroups.Page.al b/src/Tools/Test Framework/Test Runner/src/DataDrivenTest/DataInputs/TestInputGroups.Page.al
index dae881fa9e..eeadf026e9 100644
--- a/src/Tools/Test Framework/Test Runner/src/DataDrivenTest/DataInputs/TestInputGroups.Page.al
+++ b/src/Tools/Test Framework/Test Runner/src/DataDrivenTest/DataInputs/TestInputGroups.Page.al
@@ -67,6 +67,28 @@ page 130462 "Test Input Groups"
{
area(Processing)
{
+ action(DeleteSelected)
+ {
+ Caption = 'Delete Selected';
+ ToolTip = 'Delete the selected test input groups and their entries.';
+ Image = Delete;
+ Scope = Repeater;
+
+ trigger OnAction()
+ var
+ TestInputGroup: Record "Test Input Group";
+ begin
+ CurrPage.SetSelectionFilter(TestInputGroup);
+ if TestInputGroup.IsEmpty() then
+ exit;
+
+ if not Confirm(DeleteSelectedQst) then
+ exit;
+
+ TestInputGroup.DeleteAll(true);
+ CurrPage.Update(false);
+ end;
+ }
fileuploadaction(ImportDataInputs)
{
Caption = 'Import data-driven test inputs';
@@ -90,9 +112,15 @@ page 130462 "Test Input Groups"
}
area(Promoted)
{
+ actionref(DeleteSelected_Promoted; DeleteSelected)
+ {
+ }
actionref(ImportDefinition_Promoted; ImportDataInputs)
{
}
}
}
+
+ var
+ DeleteSelectedQst: Label 'Are you sure you want to delete the selected test input groups?';
}
\ No newline at end of file
diff --git a/src/Tools/Test Framework/Test Runner/src/DataDrivenTest/DataInputs/TestInputsManagement.Codeunit.al b/src/Tools/Test Framework/Test Runner/src/DataDrivenTest/DataInputs/TestInputsManagement.Codeunit.al
index 30f869a010..123707dd87 100644
--- a/src/Tools/Test Framework/Test Runner/src/DataDrivenTest/DataInputs/TestInputsManagement.Codeunit.al
+++ b/src/Tools/Test Framework/Test Runner/src/DataDrivenTest/DataInputs/TestInputsManagement.Codeunit.al
@@ -137,14 +137,20 @@ codeunit 130458 "Test Inputs Management"
TestInputGroup: Record "Test Input Group";
TestInput: Record "Test Input";
InputText: Text;
+ SuiteSetupGroupName: Text;
FileType: Text;
TelemetryCD: Dictionary of [Text, Text];
begin
- ReadMetadataFromFile(FileName, TestInputInStream, LanguageID, GroupName, InputText);
+ ReadMetadataFromFile(FileName, TestInputInStream, LanguageID, GroupName, SuiteSetupGroupName, InputText);
if not TestInputGroup.Find() then
CreateTestInputGroup(TestInputGroup, FileName, ImportedByAppId, LanguageID, GroupName);
+ if SuiteSetupGroupName <> '' then begin
+ TestInputGroup."Suite Setup Group Name" := CopyStr(SuiteSetupGroupName, 1, MaxStrLen(TestInputGroup."Suite Setup Group Name"));
+ TestInputGroup.Modify(true);
+ end;
+
if FileName.EndsWith(JsonFileExtensionTxt) then begin
FileType := JsonFileExtensionTxt;
TestInputInStream.Read(InputText);
@@ -207,7 +213,7 @@ codeunit 130458 "Test Inputs Management"
TestInputGroupCode := CopyStr(FileName, 1, MaxStrLen(TestInputGroupCode));
end;
- local procedure ReadMetadataFromFile(FileName: Text; var TestInputInStream: InStream; var LanguageID: Integer; var GroupName: Text; var InputText: Text)
+ local procedure ReadMetadataFromFile(FileName: Text; var TestInputInStream: InStream; var LanguageID: Integer; var GroupName: Text; var SuiteSetupGroupName: Text; var InputText: Text)
var
WindowsLanguage: Record "Windows Language";
MetadataJsonObject: JsonObject;
@@ -231,6 +237,10 @@ codeunit 130458 "Test Inputs Management"
if MetadataJsonObject.Get(NameTok, MetadataJsonToken) then
if MetadataJsonToken.IsValue() then
GroupName := MetadataJsonToken.AsValue().AsText();
+
+ if MetadataJsonObject.Get(TestSuiteSetupTok, MetadataJsonToken) then
+ if MetadataJsonToken.IsValue() then
+ SuiteSetupGroupName := MetadataJsonToken.AsValue().AsText();
end;
local procedure CreateTestInputGroup(var TestInputGroup: Record "Test Input Group"; FileName: Text; ImportedByAppId: Guid; LanguageID: Integer; GroupName: Text)
@@ -294,6 +304,13 @@ codeunit 130458 "Test Inputs Management"
if not DataInputJsonObject.ReadFromYaml(TestData) then
Error(CouldNotParseYamlInputErr);
+ // Suite setup: store entire content as a single row (only when value is an object, not a scalar reference)
+ if DataInputJsonObject.Get(TestSuiteSetupTok, DataInputJsonToken) then
+ if not DataInputJsonToken.IsValue() then begin
+ InsertSuiteSetupDataInput(DataInputJsonToken, TestInputGroup);
+ exit;
+ end;
+
if not DataInputJsonObject.Get(TestsTok, DataInputJsonToken) then begin
InsertDataInputLine(DataInputJsonObject, TestInputGroup);
exit;
@@ -305,7 +322,27 @@ codeunit 130458 "Test Inputs Management"
exit;
end;
- InsertDataInputLine(DataInputJsonObject, TestInputGroup);
+ InsertDataInputLine(DataInputJsonToken.AsObject(), TestInputGroup);
+ end;
+
+ local procedure InsertSuiteSetupDataInput(SuiteSetupJsonToken: JsonToken; var TestInputGroup: Record "Test Input Group")
+ var
+ TestInput: Record "Test Input";
+ SuiteSetupText: Text;
+ begin
+ TestInput.SetRange("Test Input Group Code", TestInputGroup.Code);
+ if not TestInput.IsEmpty() then
+ Error(SuiteSetupOnlyOneRowErr);
+
+ TestInput.Reset();
+ TestInput."Test Input Group Code" := TestInputGroup.Code;
+ TestInput."Language ID" := TestInputGroup."Language ID";
+ TestInput.Code := SuiteSetupInputCodeTok;
+ TestInput.Description := SuiteSetupInputCodeTok;
+ TestInput.Insert(true);
+
+ SuiteSetupJsonToken.WriteTo(SuiteSetupText);
+ TestInput.SetInput(TestInput, SuiteSetupText);
end;
local procedure InsertDataInputsFromJsonArray(var TestInputGroup: Record "Test Input Group"; var DataOnlyTestInputsArray: JsonArray)
@@ -405,12 +442,15 @@ codeunit 130458 "Test Inputs Management"
LanguageTok: Label 'language', Locked = true;
NameTok: Label 'name', Locked = true;
TestsTok: Label 'tests', Locked = true;
+ TestSuiteSetupTok: Label 'suite_setup', Locked = true;
TestInputTok: Label 'testInput', Locked = true;
+ SuiteSetupInputCodeTok: Label 'SUITE-SETUP', Locked = true;
ChooseFileLbl: Label 'Choose a file to import';
TestInputNameTok: Label 'INPUT-', Locked = true;
CouldNotParseYamlInputErr: Label 'The data does not represent valid YAML.';
CouldNotParseInputErr: Label 'Could not parse input dataset.';
CouldNotParseJsonlInputErr: Label 'Could not parse JSONL input line: %1', Comment = '%1 = JSON Line Content';
+ SuiteSetupOnlyOneRowErr: Label 'Suite setup datasets can only contain a single entry per language.';
LineTypeMustBeCodeunitErr: Label 'Line type must be Codeunit.';
JsonFileExtensionTxt: Label '.json', Locked = true;
JsonlFileExtensionTxt: Label '.jsonl', Locked = true;