mirror of
https://github.com/microsoft/BCQuality.git
synced 2026-08-06 09:26:52 +01:00
Complete AL review knowledge readiness (#108)
* Complete AL review knowledge readiness Fill telemetry and Query coverage, strengthen thin review domains, correct audited content defects, and add deterministic cheap-model evaluation and reference-integrity safeguards. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 9825b012-e653-496a-9310-c1f4b6f8ac27 * Generalize review fixture discovery Derive smoke cases from the leaf, domain, and paired-sample conventions so new leaves require no scoring-contract changes. Keep only exceptional selection/context overrides and fail when retrieval metadata cannot rank the selected article. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 9825b012-e653-496a-9310-c1f4b6f8ac27 * Preserve published field IDs in sample Keep the existing Email and Contact Email field IDs unchanged, clarify that the sample represents an independent baseline, and use a local breaking-change rule for the generic smoke evaluation. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 9825b012-e653-496a-9310-c1f4b6f8ac27 * Clarify published field identity rules State explicitly that a published field keeps its ID, name, and type while a replacement is added as a separate field under an unused ID. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 9825b012-e653-496a-9310-c1f4b6f8ac27 * Align field obsoletion sample baselines Use Email field ID 3 as the shared baseline so the bad example demonstrates a same-ID rename while the good example retains the original field and adds a separate replacement. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 9825b012-e653-496a-9310-c1f4b6f8ac27 --------- Co-authored-by: Jesper Schulz-Wedde <jesper.schulzwedde@microsoft.com>
This commit is contained in:
parent
ae04938c03
commit
186d8a1314
105 changed files with 2229 additions and 212 deletions
|
|
@ -0,0 +1,26 @@
|
|||
codeunit 50483 "Protected Setup Action Bad"
|
||||
{
|
||||
trigger OnRun()
|
||||
var
|
||||
Customer: Record Customer;
|
||||
begin
|
||||
Customer.Init();
|
||||
Customer."No." := 'SUPER-INSERT';
|
||||
Customer.Insert();
|
||||
end;
|
||||
}
|
||||
|
||||
codeunit 50484 "Permission Test Bad"
|
||||
{
|
||||
Subtype = Test;
|
||||
TestPermissions = Disabled;
|
||||
|
||||
[Test]
|
||||
procedure LimitedUserCannotRunSetup()
|
||||
var
|
||||
SetupAction: Codeunit "Protected Setup Action Bad";
|
||||
begin
|
||||
// Disabled runs as SUPER; no limited-user boundary is exercised.
|
||||
asserterror SetupAction.Run();
|
||||
end;
|
||||
}
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
permissionset 50480 "LIMITED USER"
|
||||
{
|
||||
Assignable = false;
|
||||
Permissions =
|
||||
tabledata Customer = R,
|
||||
codeunit "Protected Setup Action Test" = X;
|
||||
}
|
||||
|
||||
codeunit 50481 "Protected Setup Action Test"
|
||||
{
|
||||
trigger OnRun()
|
||||
var
|
||||
Customer: Record Customer;
|
||||
begin
|
||||
Customer.Init();
|
||||
Customer."No." := 'NO-INSERT';
|
||||
Customer.Insert();
|
||||
end;
|
||||
}
|
||||
|
||||
codeunit 50482 "Permission Test Good"
|
||||
{
|
||||
Subtype = Test;
|
||||
TestPermissions = Restrictive;
|
||||
|
||||
[Test]
|
||||
procedure LimitedUserCannotRunSetup()
|
||||
var
|
||||
PermissionsMock: Codeunit "Permissions Mock";
|
||||
SetupAction: Codeunit "Protected Setup Action Test";
|
||||
begin
|
||||
PermissionsMock.Start();
|
||||
PermissionsMock.SetExactPermissionSet('LIMITED USER');
|
||||
|
||||
asserterror SetupAction.Run();
|
||||
Assert.ExpectedError('permission');
|
||||
|
||||
PermissionsMock.Stop();
|
||||
end;
|
||||
|
||||
var
|
||||
Assert: Codeunit "Library Assert";
|
||||
}
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
---
|
||||
bc-version: [all]
|
||||
domain: testing
|
||||
keywords: [testpermissions, restrictive, disabled, permissions-mock, lower-permissions, super, permission-test]
|
||||
technologies: [al]
|
||||
countries: [w1]
|
||||
application-area: [all]
|
||||
---
|
||||
|
||||
# Permission tests must actually lower the execution context
|
||||
|
||||
## Description
|
||||
|
||||
`TestPermissions` describes how a test runner should establish the permission context; the enum value does not itself assign the business permission set being tested. `Restrictive` is the default and starts from D365 Full Access, requiring the test to lower permissions. `Disabled` leaves the test running as `SUPER`. A test that expects access to be denied while still running with either broad context can pass or fail for the wrong reason and never exercise the intended boundary.
|
||||
|
||||
## Best Practice
|
||||
|
||||
Use `TestPermissions::Restrictive` for a permission-sensitive test and lower the current test user with the test framework's `"Permissions Mock"` or `"Library - Lower Permissions"` before invoking the protected operation. Assign the exact permission set the scenario claims to test and restore or stop the mock afterward. Use `Disabled` only for suites that do not assert permission behavior.
|
||||
|
||||
See sample: `permission-tests-must-lower-the-execution-context.good.al`.
|
||||
|
||||
## Anti Pattern
|
||||
|
||||
Setting `TestPermissions = Disabled` or leaving the effective D365 Full Access context in place while asserting that a limited user is denied, or adding a `[TestPermissions(...)]` attribute without any runner/test-library code that applies the intended permission set.
|
||||
|
||||
See sample: `permission-tests-must-lower-the-execution-context.bad.al`.
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
codeunit 50452 "Isolated Test Runner Bad"
|
||||
{
|
||||
Subtype = TestRunner;
|
||||
TestIsolation = Disabled;
|
||||
}
|
||||
|
||||
codeunit 50453 "Committed Write Test Bad"
|
||||
{
|
||||
Subtype = Test;
|
||||
|
||||
[Test]
|
||||
[TransactionModel(TransactionModel::AutoCommit)]
|
||||
procedure TestCommittedWrite()
|
||||
var
|
||||
Customer: Record Customer;
|
||||
begin
|
||||
Customer.Init();
|
||||
Customer."No." := 'PERSISTS';
|
||||
Customer.Insert();
|
||||
Commit();
|
||||
end;
|
||||
}
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
codeunit 50450 "Isolated Test Runner Good"
|
||||
{
|
||||
Subtype = TestRunner;
|
||||
TestIsolation = Codeunit;
|
||||
}
|
||||
|
||||
codeunit 50451 "Committed Write Test Good"
|
||||
{
|
||||
Subtype = Test;
|
||||
|
||||
[Test]
|
||||
[TransactionModel(TransactionModel::AutoCommit)]
|
||||
procedure TestCommittedWrite()
|
||||
var
|
||||
Customer: Record Customer;
|
||||
begin
|
||||
Customer.Init();
|
||||
Customer."No." := 'ISOLATED';
|
||||
Customer.Insert();
|
||||
Commit();
|
||||
end;
|
||||
}
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
---
|
||||
bc-version: [all]
|
||||
domain: testing
|
||||
keywords: [testisolation, testrunner, autocommit, commit, rollback, test-order, database-state]
|
||||
technologies: [al]
|
||||
countries: [w1]
|
||||
application-area: [all]
|
||||
---
|
||||
|
||||
# Configure TestIsolation on the test runner
|
||||
|
||||
## Description
|
||||
|
||||
`TestIsolation` is a property of a `Subtype = TestRunner` codeunit, not of the test codeunit being executed. Its default is `Disabled`. `Codeunit` rolls back database changes after each test codeunit and `Function` after each test method, including changes that the code under test explicitly committed. Without runner isolation, an `AutoCommit` test can leave data behind and make later tests order-dependent.
|
||||
|
||||
## Best Practice
|
||||
|
||||
Run independent suites with `TestIsolation = Codeunit` or `Function`, choosing the narrowest boundary the runner supports. Pair this with the appropriate method-level `TransactionModel`: `AutoCommit` permits code under test to commit, while runner isolation still restores the database afterward. Keep isolation disabled only for an intentionally shared-state suite whose ordering and cleanup are explicit.
|
||||
|
||||
See sample: `testisolation-belongs-on-the-test-runner.good.al`.
|
||||
|
||||
## Anti Pattern
|
||||
|
||||
An `AutoCommit` test exercises committed writes under a test runner that omits `TestIsolation` or sets it to `Disabled`, then assumes the database is restored automatically. This article owns runner-level rollback; `transactionmodel-attribute-governs-test-transactions.md` separately owns the method attribute.
|
||||
|
||||
See sample: `testisolation-belongs-on-the-test-runner.bad.al`.
|
||||
Loading…
Add table
Add a link
Reference in a new issue