mirror of
https://github.com/microsoft/BCQuality.git
synced 2026-10-05 22:56:55 +01:00
Clarify restart-safe batches and scripted UI handler tests
Address Nikola's batching and UI-handler feedback on PR #132. Preserve existing false-positive guards and defer the unconfirmed IsHandled policy. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: f841a18b-535a-498e-96f2-f279b5378da5
This commit is contained in:
parent
35d0966a8d
commit
0561b12c96
7 changed files with 155 additions and 46 deletions
|
|
@ -13,7 +13,6 @@ codeunit 50401 "Test UI Handler Proof Bad"
|
|||
|
||||
Page.RunModal(Page::"Customer Card", Customer);
|
||||
|
||||
// This only proves a value assigned before the action stayed true.
|
||||
Assert.IsTrue(ActionSucceeded, 'The customer card action failed.');
|
||||
end;
|
||||
|
||||
|
|
@ -51,6 +50,32 @@ codeunit 50401 "Test UI Handler Proof Bad"
|
|||
Page.RunModal(Page::"Customer Card", Customer);
|
||||
end;
|
||||
|
||||
[Test]
|
||||
[HandlerFunctions('ConfirmHandler,PostMessageHandler')]
|
||||
procedure ConfirmPostingAndShowMessage()
|
||||
begin
|
||||
Assert.IsTrue(RunPostingThatConfirmsAndMessages(), 'The posting confirmation was declined.');
|
||||
end;
|
||||
|
||||
local procedure RunPostingThatConfirmsAndMessages(): Boolean
|
||||
begin
|
||||
if not Confirm('Post this document?', false) then
|
||||
exit(false);
|
||||
Message('Posting completed.');
|
||||
exit(true);
|
||||
end;
|
||||
|
||||
[ConfirmHandler]
|
||||
procedure ConfirmHandler(Question: Text[1024]; var Reply: Boolean)
|
||||
begin
|
||||
Reply := true;
|
||||
end;
|
||||
|
||||
[MessageHandler]
|
||||
procedure PostMessageHandler(MessageText: Text[1024])
|
||||
begin
|
||||
end;
|
||||
|
||||
[ModalPageHandler]
|
||||
procedure CustomerCardHandler(var CustomerCard: TestPage "Customer Card")
|
||||
begin
|
||||
|
|
|
|||
|
|
@ -30,6 +30,41 @@ codeunit 50400 "Test UI Handler Capture Good"
|
|||
Assert.AreEqual(Customer."No.", CapturedCustomerNo, 'The customer card opened for the wrong customer.');
|
||||
end;
|
||||
|
||||
[Test]
|
||||
[HandlerFunctions('ConfirmHandler,PostMessageHandler')]
|
||||
procedure ConfirmPostingAndShowMessage()
|
||||
begin
|
||||
LibraryVariableStorage.Clear();
|
||||
LibraryVariableStorage.Enqueue('Post this document?');
|
||||
LibraryVariableStorage.Enqueue(true);
|
||||
LibraryVariableStorage.Enqueue('Posting completed.');
|
||||
|
||||
Assert.IsTrue(RunPostingThatConfirmsAndMessages(), 'The posting confirmation was declined.');
|
||||
|
||||
LibraryVariableStorage.AssertEmpty();
|
||||
end;
|
||||
|
||||
local procedure RunPostingThatConfirmsAndMessages(): Boolean
|
||||
begin
|
||||
if not Confirm('Post this document?', false) then
|
||||
exit(false);
|
||||
Message('Posting completed.');
|
||||
exit(true);
|
||||
end;
|
||||
|
||||
[ConfirmHandler]
|
||||
procedure ConfirmHandler(Question: Text[1024]; var Reply: Boolean)
|
||||
begin
|
||||
Assert.ExpectedConfirm(LibraryVariableStorage.DequeueText(), Question);
|
||||
Reply := LibraryVariableStorage.DequeueBoolean();
|
||||
end;
|
||||
|
||||
[MessageHandler]
|
||||
procedure PostMessageHandler(MessageText: Text[1024])
|
||||
begin
|
||||
Assert.ExpectedMessage(LibraryVariableStorage.DequeueText(), MessageText);
|
||||
end;
|
||||
|
||||
[ModalPageHandler]
|
||||
procedure CustomerCardHandler(var CustomerCard: TestPage "Customer Card")
|
||||
begin
|
||||
|
|
@ -45,5 +80,6 @@ codeunit 50400 "Test UI Handler Capture Good"
|
|||
var
|
||||
Assert: Codeunit "Library Assert";
|
||||
LibrarySales: Codeunit "Library - Sales";
|
||||
LibraryVariableStorage: Codeunit "Library - Variable Storage";
|
||||
CapturedCustomerNo: Code[20];
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,12 +19,16 @@ Beyond that wiring guarantee, the test must verify the behavior it cares about.
|
|||
|
||||
## Best Practice
|
||||
|
||||
List the handlers the scenario triggers, keep an optional notification handler listed for a notification the scenario may conditionally raise, and make each executed handler contribute meaningful evidence. For a single modal page, reset a capture variable before the action, capture a concrete value from the page in the handler, and assert the expected value after `RunModal`. For ordered or repeated interactions, let the test enqueue expectations, let handlers dequeue and verify them, clear storage during initialization, and finish with `AssertEmpty`.
|
||||
List the handlers the scenario triggers and keep an optional notification handler listed for a notification the scenario may conditionally raise. Make the test and its handlers prove the scenario's contract. For a single modal page, reset a capture variable before the action, capture a concrete value from the page in the handler, and assert the expected value after `RunModal`. This proves the captured result, not an exact call count or sequence: repeated calls can overwrite earlier captures.
|
||||
|
||||
When interaction count, text, order, or replies are part of the contract, drive the handlers with the `Library - Variable Storage` codeunit. Clear `LibraryVariableStorage` during test initialization, then enqueue expected text and replies in interaction order. A shared `ConfirmHandler` dequeues the expected question, verifies it with `Assert.ExpectedConfirm`, and dequeues the Boolean reply to return; a message handler can use `Assert.ExpectedMessage` with the next expected text. These asserts match a stable text fragment. Finish with `LibraryVariableStorage.AssertEmpty` to catch unconsumed expectations; each handler must also dequeue and verify its interaction so unexpected calls cannot pass silently. Equivalent explicit assertions are valid; absence of this library alone is not a finding.
|
||||
|
||||
Prefer one reusable handler of each type within a test codeunit where practical, with individual tests supplying their expectations and replies. This is a maintainability recommendation, not a platform requirement; specialized handlers remain valid when their contracts differ. The paired confirmation-and-message samples run the same flow and check its Boolean result, but only the good sample verifies the expected interactions. The modal capture and optional notification scenarios illustrate contracts that do not require a scripted queue.
|
||||
|
||||
See sample: [`ui-handlers-in-tests.good.al`](ui-handlers-in-tests.good.al).
|
||||
|
||||
## Anti Pattern
|
||||
|
||||
Omitting a handler for a UI call, listing a nonoptional handler the path never reaches, or claiming action success from a Boolean set before the action runs. A handler that only closes a page can also leave the test without a semantic assertion. Do not flag the absence of queue storage by itself; require it only when the test needs to prove interaction order, count, text, replies, or a scripted sequence. Do not flag a listed `[SendNotificationHandler(true)]` or `[RecallNotificationHandler(true)]` that the run does not reach, and never propose removing one: the entry is what keeps the test passing on the runs where the notification does fire.
|
||||
Omitting a handler for a UI call, listing a nonoptional handler the path never reaches, or claiming action success from a Boolean set before the action runs. A handler that only closes a page can also leave the test without a semantic assertion. Blindly confirming or dismissing messages does not verify a contract that requires specific interactions. Do not flag the absence of queue storage by itself; require interaction verification only when the test needs to prove order, count, text, replies, or a scripted sequence. Do not flag a listed `[SendNotificationHandler(true)]` or `[RecallNotificationHandler(true)]` that the run does not reach, and never propose removing one: the entry is what keeps the test passing on the runs where the notification does fire.
|
||||
|
||||
See sample: [`ui-handlers-in-tests.bad.al`](ui-handlers-in-tests.bad.al).
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue