microsoft/al-test-generation
Guide for creating AL tests for Microsoft Dynamics 365 Business Central. Use this when asked to write, create, or generate AL test codeunits, test procedures, or test automation for Business Central.
npx skills add https://github.com/microsoft/BC-Bench --skill al-test-generation
To create AL tests for Microsoft Dynamics 365 Business Central, follow this process:
Before writing any test code:
CRITICAL: Tests fail with "Unhandled UI" errors when handlers are missing.
Look for these patterns in the code under test:
| Code Pattern | Required Handler |
| ------------------------------------- | --------------------------- |
| Confirm() | [ConfirmHandler] |
| Message() | [MessageHandler] |
| StrMenu() | [StrMenuHandler] |
| Page.Run() | [PageHandler] |
| Page.RunModal() | [ModalPageHandler] |
| Report.Run() or Report.RunModal() | [ReportHandler] |
| Report request page | [RequestPageHandler] |
| Hyperlink() | [HyperlinkHandler] |
| Notification.Send() | [SendNotificationHandler] |
CRITICAL: Tests fail with validation errors when inserting data that violates TableRelation constraints.
Before inserting test data:
TableRelation propertiesLibrarySales, LibraryPurchase) to create prerequisite dataFollow the AAA pattern (Arrange-Act-Assert):
[Test]
[HandlerFunctions('RequiredHandlers')]
procedure TestProcedureName()
begin
// [GIVEN] Setup test data and preconditions
Initialize();
CreateTestData();
// [WHEN] Execute the action being tested
ExecuteAction();
// [THEN] Verify the expected results
VerifyResults();
end;
[ConfirmHandler]
procedure ConfirmHandlerYes(Question: Text[1024]; var Reply: Boolean)
begin
Reply := true;
end;
[MessageHandler]
procedure MessageHandler(Message: Text[1024])
begin
// Empty - suppresses message display
end;
[ModalPageHandler]
procedure ModalPageHandler(var TestPage: TestPage "Page Name")
begin
TestPage.OK().Invoke();
end;
Initialize() procedure to set up common test fixturesTake microsoft/al-test-generation from the repository into ~/.claude/skills for personal
use, or into .claude/skills inside a project.
The agent identifies a skill by the name field in its header. Two skills with the
same name cannot sit side by side — one of them will be ignored.