Skip to content

Commit a5a7bbd

Browse files
authored
[AI Test Tool] Add Multi-Turn Accuracy & Export (#2419)
<!-- Thank you for submitting a Pull Request. If you're new to contributing to BCApps please read our pull request guideline below * https://github.com/microsoft/BCApps/Contributing.md --> #### Summary <!-- Provide a general summary of your changes --> This PR adds multi-turn accuracy for tests and export option for results. Accuracy is automatically calculated as the number of turns succeeded / the total number of turns. Accuracy is available on Suite level, codeunit level and test level. Accuracy can also be set by the test manually, using the new SetAccuracy function in the AIT Test Context. Export of results is available on the Log Entries page (exports current view) or Suite (exports results for latest version) #### Work Item(s) <!-- Add the issue number here after the #. The issue needs to be open and approved. Submitting PRs with no linked issues or unapproved issues is highly discouraged. --> Fixes [AB#557118](https://dynamicssmb2.visualstudio.com/Dynamics%20SMB/_workitems/edit/548277/)
1 parent c5831b1 commit a5a7bbd

14 files changed

+405
-5
lines changed
16.7 KB
Binary file not shown.

src/Tools/AI Test Toolkit/src/AITTestContext.Codeunit.al

+9
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,15 @@ codeunit 149044 "AIT Test Context"
123123
AITTestContextImpl.SetTestMetric(TestMetric);
124124
end;
125125

126+
/// <summary>
127+
/// Sets the accuracy of the test.
128+
/// </summary>
129+
/// <param name="Accuracy">The accuracy as a decimal between 0 and 1.</param>
130+
procedure SetAccuracy(Accuracy: Decimal)
131+
begin
132+
AITTestContextImpl.SetAccuracy(Accuracy);
133+
end;
134+
126135
var
127136
AITTestContextImpl: Codeunit "AIT Test Context Impl.";
128137
}

src/Tools/AI Test Toolkit/src/AITTestContextImpl.Codeunit.al

+49-5
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,12 @@ codeunit 149043 "AIT Test Context Impl."
1818
var
1919
AITTestSuiteMgt: Codeunit "AIT Test Suite Mgt.";
2020
GlobalTestOutputJson: Codeunit "Test Output Json";
21+
GlobalAccuracy: Decimal;
2122
CurrentTurn: Integer;
2223
NumberOfTurns: Integer;
2324
IsMultiTurn: Boolean;
25+
AccuracySetManually: Boolean;
26+
AccuracyErr: Label 'Accuracy must be between 0 and 1.';
2427
AnswerTok: Label 'answer', Locked = true;
2528
ContextTok: Label 'context', Locked = true;
2629
GroundTruthTok: Label 'ground_truth', Locked = true;
@@ -146,6 +149,34 @@ codeunit 149043 "AIT Test Context Impl."
146149
SetSuiteTestOutput(CurrentTestOutputJson.ToText());
147150
end;
148151

152+
/// <summary>
153+
/// Sets the accuracy of the test.
154+
/// </summary>
155+
/// <param name="Accuracy">The accuracy as a decimal between 0 and 1.</param>
156+
procedure SetAccuracy(Accuracy: Decimal)
157+
begin
158+
if (Accuracy < 0) or (Accuracy > 1) then
159+
Error(AccuracyErr);
160+
161+
AccuracySetManually := true;
162+
GlobalAccuracy := Accuracy;
163+
end;
164+
165+
/// <summary>
166+
/// Gets the accuracy of the test. Can only be retrieved if the accuracy of the test was already set manually.
167+
/// </summary>
168+
/// <param name="Accuracy">The accuracy as a decimal between 0 and 1.</param>
169+
/// <returns>True if it was possible to get the accuracy, false otherwise.</returns>
170+
procedure GetAccuracy(var Accuracy: Decimal): Boolean
171+
begin
172+
if AccuracySetManually then begin
173+
Accuracy := GlobalAccuracy;
174+
exit(true);
175+
end;
176+
177+
exit(false);
178+
end;
179+
149180
/// <summary>
150181
/// Sets to next turn for multiturn testing.
151182
/// </summary>
@@ -155,7 +186,7 @@ codeunit 149043 "AIT Test Context Impl."
155186
if not IsMultiTurn then
156187
exit(false);
157188

158-
if CurrentTurn + 1 > NumberOfTurns then
189+
if CurrentTurn > NumberOfTurns then
159190
exit(false);
160191

161192
CurrentTurn := CurrentTurn + 1;
@@ -164,14 +195,23 @@ codeunit 149043 "AIT Test Context Impl."
164195
end;
165196

166197
/// <summary>
167-
/// Gets the current turn for multiturn testing. Turns start from turn 0.
198+
/// Gets the current turn for multiturn testing. Turns start from turn 1.
168199
/// </summary>
169200
/// <returns>The current turn number.</returns>
170201
procedure GetCurrentTurn(): Integer
171202
begin
172203
exit(CurrentTurn);
173204
end;
174205

206+
/// <summary>
207+
/// Gets the total number of turns for multiturn testing.
208+
/// </summary>
209+
/// <returns>The total number of turns for the line.</returns>
210+
procedure GetNumberOfTurns(): Integer
211+
begin
212+
exit(NumberOfTurns);
213+
end;
214+
175215
/// <summary>
176216
/// This method starts the scope of the Run Procedure scenario.
177217
/// </summary>
@@ -205,12 +245,16 @@ codeunit 149043 "AIT Test Context Impl."
205245
TestInput: Codeunit "Test Input";
206246
TurnsInputJson: Codeunit "Test Input Json";
207247
begin
208-
CurrentTurn := 0;
248+
AccuracySetManually := false;
249+
GlobalAccuracy := 0;
250+
CurrentTurn := 1;
209251
GlobalTestOutputJson.Initialize();
210252
TurnsInputJson := TestInput.GetTestInput().ElementExists(TurnsTok, IsMultiTurn);
211253

212254
if IsMultiTurn then
213-
NumberOfTurns := TurnsInputJson.GetElementCount() - 1;
255+
NumberOfTurns := TurnsInputJson.GetElementCount()
256+
else
257+
NumberOfTurns := 1;
214258
end;
215259

216260
/// <summary>
@@ -223,7 +267,7 @@ codeunit 149043 "AIT Test Context Impl."
223267
TestInput: Codeunit "Test Input";
224268
begin
225269
if IsMultiTurn then
226-
TestInputJson := TestInput.GetTestInput(TurnsTok).ElementAt(CurrentTurn).Element(ElementName)
270+
TestInputJson := TestInput.GetTestInput(TurnsTok).ElementAt(CurrentTurn - 1).Element(ElementName)
227271
else
228272
TestInputJson := TestInput.GetTestInput(ElementName);
229273
end;

src/Tools/AI Test Toolkit/src/AITTestRunIteration.Codeunit.al

+40
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,9 @@ codeunit 149042 "AIT Test Run Iteration"
2121
GlobalTestMethodLine: Record "Test Method Line";
2222
NoOfInsertedLogEntries: Integer;
2323
GlobalAITokenUsedByLastTestMethodLine: Integer;
24+
GlobalNumberOfTurnsForLastTestMethodLine: Integer;
25+
GlobalNumberOfTurnsPassedForLastTestMethodLine: Integer;
26+
GlobalTestAccuracy: Decimal;
2427
GlobalSessionAITokenUsed: Integer;
2528

2629
trigger OnRun()
@@ -124,6 +127,21 @@ codeunit 149042 "AIT Test Run Iteration"
124127
exit(GlobalAITokenUsedByLastTestMethodLine);
125128
end;
126129

130+
procedure GetNumberOfTurnsForLastTestMethodLine(): Integer
131+
begin
132+
exit(GlobalNumberOfTurnsForLastTestMethodLine);
133+
end;
134+
135+
procedure GetNumberOfTurnsPassedForLastTestMethodLine(): Integer
136+
begin
137+
exit(GlobalNumberOfTurnsPassedForLastTestMethodLine);
138+
end;
139+
140+
procedure GetAccuracyForLastTestMethodLine(): Decimal
141+
begin
142+
exit(GlobalTestAccuracy);
143+
end;
144+
127145
[InternalEvent(false)]
128146
procedure OnBeforeRunIteration(var AITTestSuite: Record "AIT Test Suite"; var AITTestMethodLine: Record "AIT Test Method Line")
129147
begin
@@ -144,6 +162,14 @@ codeunit 149042 "AIT Test Run Iteration"
144162

145163
// Update AI Token Consumption
146164
GlobalAITokenUsedByLastTestMethodLine := 0;
165+
166+
// Update Turns
167+
GlobalNumberOfTurnsPassedForLastTestMethodLine := 0;
168+
GlobalNumberOfTurnsForLastTestMethodLine := 1;
169+
170+
// Update Test Accuracy
171+
GlobalTestAccuracy := 0;
172+
147173
GlobalSessionAITokenUsed := AOAIToken.GetTotalServerSessionTokensConsumed();
148174

149175
AITContextCU.StartRunProcedureScenario();
@@ -154,6 +180,7 @@ codeunit 149042 "AIT Test Run Iteration"
154180
var
155181
AITContextCU: Codeunit "AIT Test Context Impl.";
156182
AOAIToken: Codeunit "AOAI Token";
183+
Accuracy: Decimal;
157184
begin
158185
if ActiveAITTestSuite.Code = '' then
159186
exit;
@@ -166,6 +193,19 @@ codeunit 149042 "AIT Test Run Iteration"
166193
// Update AI Token Consumption
167194
GlobalAITokenUsedByLastTestMethodLine := AOAIToken.GetTotalServerSessionTokensConsumed() - GlobalSessionAITokenUsed;
168195

196+
// Update Turns
197+
GlobalNumberOfTurnsForLastTestMethodLine := AITContextCU.GetNumberOfTurns();
198+
GlobalNumberOfTurnsPassedForLastTestMethodLine := AITContextCU.GetCurrentTurn();
199+
200+
if not IsSuccess then
201+
GlobalNumberOfTurnsPassedForLastTestMethodLine -= 1;
202+
203+
// Update Test Accuracy
204+
if AITContextCU.GetAccuracy(Accuracy) then
205+
GlobalTestAccuracy := Accuracy
206+
else
207+
GlobalTestAccuracy := GlobalNumberOfTurnsPassedForLastTestMethodLine / GlobalNumberOfTurnsForLastTestMethodLine;
208+
169209
AITContextCU.EndRunProcedureScenario(CurrentTestMethodLine, IsSuccess);
170210
Commit();
171211
end;

src/Tools/AI Test Toolkit/src/Logs/AITLogEntries.Page.al

+51
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,23 @@ page 149033 "AIT Log Entries"
6868
{
6969
StyleExpr = StatusStyleExpr;
7070
}
71+
field(Accuracy; Rec."Test Method Line Accuracy")
72+
{
73+
}
74+
field("No. of Turns Passed"; Rec."No. of Turns Passed")
75+
{
76+
Visible = false;
77+
}
78+
field("No. of Turns"; Rec."No. of Turns")
79+
{
80+
Visible = false;
81+
}
82+
field(TurnsText; TurnsText)
83+
{
84+
StyleExpr = TurnsStyleExpr;
85+
Caption = 'No. of Turns Passed';
86+
ToolTip = 'Specifies the number of turns that passed out of the total number of turns.';
87+
}
7188
field("Orig. Status"; Rec."Original Status")
7289
{
7390
Visible = false;
@@ -253,6 +270,19 @@ page 149033 "AIT Log Entries"
253270
Page.Run(Page::"AIT Test Data Compare", Rec);
254271
end;
255272
}
273+
action("Download Test Summary")
274+
{
275+
Caption = 'Download Test Summary';
276+
Image = Export;
277+
ToolTip = 'Downloads a summary of the test results.';
278+
279+
trigger OnAction()
280+
var
281+
AITTestSuiteMgt: Codeunit "AIT Test Suite Mgt.";
282+
begin
283+
AITTestSuiteMgt.DownloadTestSummary(Rec);
284+
end;
285+
}
256286
}
257287
area(Promoted)
258288
{
@@ -279,6 +309,9 @@ page 149033 "AIT Log Entries"
279309
actionref("View Test Data_Promoted"; "View Test Data")
280310
{
281311
}
312+
actionref("Export Results_Promoted"; "Download Test Summary")
313+
{
314+
}
282315
}
283316
}
284317
}
@@ -287,20 +320,26 @@ page 149033 "AIT Log Entries"
287320
ClickToShowLbl: Label 'Show data input';
288321
DoYouWantToDeleteQst: Label 'Do you want to delete all entries within the filter?';
289322
InputText: Text;
323+
TurnsText: Text;
290324
OutputText: Text;
291325
ErrorMessage: Text;
292326
ErrorCallStack: Text;
293327
StatusStyleExpr: Text;
328+
TurnsStyleExpr: Text;
294329
TestRunDuration: Duration;
295330
IsFilteredToErrors: Boolean;
296331
ShowSensitiveData: Boolean;
297332

298333
trigger OnAfterGetRecord()
334+
var
335+
AITTestSuiteMgt: Codeunit "AIT Test Suite Mgt.";
299336
begin
300337
TestRunDuration := Rec."Duration (ms)";
338+
TurnsText := AITTestSuiteMgt.GetTurnsAsText(Rec);
301339
SetInputOutputDataFields();
302340
SetErrorFields();
303341
SetStatusStyleExpr();
342+
SetTurnsStyleExpr();
304343
end;
305344

306345
local procedure SetStatusStyleExpr()
@@ -315,6 +354,18 @@ page 149033 "AIT Log Entries"
315354
end;
316355
end;
317356

357+
local procedure SetTurnsStyleExpr()
358+
begin
359+
case Rec."No. of Turns Passed" of
360+
Rec."No. of Turns":
361+
TurnsStyleExpr := 'Favorable';
362+
0:
363+
TurnsStyleExpr := 'Unfavorable';
364+
else
365+
TurnsStyleExpr := 'Ambiguous';
366+
end;
367+
end;
368+
318369
local procedure SetErrorFields()
319370
begin
320371
ErrorMessage := '';

src/Tools/AI Test Toolkit/src/Logs/AITLogEntry.Table.al

+15
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,21 @@ table 149034 "AIT Log Entry"
159159
{
160160
Caption = 'Output Data';
161161
}
162+
field(40; "No. of Turns"; Integer)
163+
{
164+
Caption = 'Total number of turns';
165+
ToolTip = 'Specifies the total number of turns.';
166+
}
167+
field(41; "No. of Turns Passed"; Integer)
168+
{
169+
Caption = 'Number of turns passed';
170+
ToolTip = 'Specifies the number of turns passed.';
171+
}
172+
field(45; "Test Method Line Accuracy"; Decimal)
173+
{
174+
Caption = 'Test Method Line Accuracy';
175+
ToolTip = 'Specifies the accuracy of the test line. The accuracy is calculated as the percentage of turns that passed or can be set manually in the test.';
176+
}
162177
field(50; "Tokens Consumed"; Integer)
163178
{
164179
Caption = 'Total Tokens Consumed';

src/Tools/AI Test Toolkit/src/Logs/AITRunHistory.Page.al

+12
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,12 @@ page 149032 "AIT Run History"
121121
AITLogEntryCodeunit.DrillDownFailedAITLogEntries(Rec."Test Suite Code", Rec."Line No. Filter", Rec.Version);
122122
end;
123123
}
124+
field("Accuracy - By Version"; Rec."Accuracy Per Version")
125+
{
126+
Visible = ViewBy = ViewBy::Version;
127+
Caption = 'Accuracy';
128+
ToolTip = 'Specifies the average accuracy of the version.';
129+
}
124130
field("Duration - By Version"; Rec."Total Duration (ms)")
125131
{
126132
Visible = ViewBy = ViewBy::Version;
@@ -161,6 +167,12 @@ page 149032 "AIT Run History"
161167
AITLogEntryCodeunit.DrillDownFailedAITLogEntries(Rec."Test Suite Code", Rec."Line No. Filter", Rec.Tag);
162168
end;
163169
}
170+
field("Accuracy - By Tag"; Rec."Accuracy - By Tag")
171+
{
172+
Visible = ViewBy = ViewBy::Tag;
173+
Caption = 'Accuracy';
174+
ToolTip = 'Specifies the average accuracy of the tag.';
175+
}
164176
field("Duration - By Tag"; Rec."Total Duration (ms) - By Tag")
165177
{
166178
Visible = ViewBy = ViewBy::Tag;

src/Tools/AI Test Toolkit/src/Logs/AITRunHistory.Table.al

+16
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,14 @@ table 149036 "AIT Run History"
7373
FieldClass = FlowField;
7474
CalcFormula = sum("AIT Log Entry"."Tokens Consumed" where("Test Suite Code" = field("Test Suite Code"), Version = field("Version"), "Test Method Line No." = field("Line No. Filter"), Operation = const('Run Procedure'), "Procedure Name" = filter(<> '')));
7575
}
76+
field(14; "Accuracy Per Version"; Decimal)
77+
{
78+
Caption = 'Accuracy';
79+
ToolTip = 'Specifies the average accuracy of the version.';
80+
Editable = false;
81+
FieldClass = FlowField;
82+
CalcFormula = average("AIT Log Entry"."Test Method Line Accuracy" where("Test Suite Code" = field("Test Suite Code"), "Test Method Line No." = field("Line No. Filter"), Version = field("Version"), Operation = const('Run Procedure'), "Procedure Name" = filter(<> '')));
83+
}
7684
field(20; "No. of Tests Executed - By Tag"; Integer)
7785
{
7886
Caption = 'No. of Tests Executed';
@@ -105,6 +113,14 @@ table 149036 "AIT Run History"
105113
FieldClass = FlowField;
106114
CalcFormula = sum("AIT Log Entry"."Tokens Consumed" where("Test Suite Code" = field("Test Suite Code"), "Test Method Line No." = field("Line No. Filter"), Tag = field(Tag), Operation = const('Run Procedure'), "Procedure Name" = filter(<> '')));
107115
}
116+
field(24; "Accuracy - By Tag"; Decimal)
117+
{
118+
Caption = 'Accuracy';
119+
ToolTip = 'Specifies the average accuracy of the tag.';
120+
Editable = false;
121+
FieldClass = FlowField;
122+
CalcFormula = average("AIT Log Entry"."Test Method Line Accuracy" where("Test Suite Code" = field("Test Suite Code"), "Test Method Line No." = field("Line No. Filter"), Tag = field(Tag), Operation = const('Run Procedure'), "Procedure Name" = filter(<> '')));
123+
}
108124
}
109125

110126
keys

0 commit comments

Comments
 (0)