- commit-shared-test-fixture-inside-lazy-initialize: three sub-issues.
Recommended TestIsolation = Codeunit instead of listing Disabled as an
equal option - Disabled never rolls back at all ("tests are not
isolated from each other" per the property's own docs), so a fixture
this pattern commits under Disabled is permanent database
contamination unless something else tears it down; Disabled is now
only mentioned alongside that explicit teardown requirement. Added
precedence in al-testing-review.md so the deliberate end-of-test
asserterror Error(...) rollback sentinel isn't also flagged by the
generic asserterror-needs-expectederror-and-code rule. Rewrote both
fixtures to actually demonstrate the pattern: persisted fixture data
(an Item record) instead of an empty comment, a second [Test] method
that depends on the fixture surviving into it, and an explicit
Subtype = TestRunner / TestIsolation = Codeunit runner codeunit.
- table-relation-test-exclude-known-invalid-relations-via-event:
the length/type rule was stated as one global requirement. Verified
ValidateFieldRelation in codeunit 134926 directly (BCApps reference
clone) and split it into the two branches the source actually has:
a field with any unconditional relation needs exact length and exact
resolved type; a field whose relations are all conditional only fails
on being shorter (longer is fine) than the largest related field, and
when the required type is specifically Code, a Text source passes too
- a tolerance that does not apply on the unconditional side and does
not extend to a required Text.
Rebased onto upstream/main (one conflict in
transactionmodel-attribute-governs-test-transactions.md - upstream had
already linked its sample references via the READ convention, ours
added a Source section; merged both). Also converted the 3 remaining
plain-backtick sample references in this PR to the READ-convention
markdown-link form, same fix as #156/#157/#158.
- commit-shared-test-fixture-inside-lazy-initialize.md: fundamentally
rewritten. AutoCommit is the documented default TransactionModel, not
AutoRollback. Explains the real mechanism (Commit() protects a fixture
from the test method's own later deliberate rollback, per Codeunit.Run/
TransactionModel-property semantics) and the TestIsolation dependency
(Disabled/Codeunit survive across methods, Function does not). Fixtures
rewritten to demonstrate the actual failure/success shape.
- transactionmodel-attribute-governs-test-transactions.md: now states the
AutoCommit default explicitly and agrees with the article above, closing
the contradiction Jesper flagged between the two testing articles.
- Deleted confirm-needs-strsubstno-before-confirmhandler-sees-substituted-text
(.md/.good.al/.bad.al): the underlying platform bug (microsoft/
ALAppExtensions#23935) was closed as completed in Feb 2024; cannot be
reproduced or bc-version-pinned on any currently supported version.
- table-relation-test-exclude-known-invalid-relations-via-event.md: added
the [Scope('OnPrem')] boundary verified against BCApps' Table Relation
Test codeunit.
- use-assert-isfalse-not-asserterror-for-boolean-checks.md: added a Scope
section resolving the overlap with asserterror-needs-expectederror-and-code.
- al-testing-review.md: fixed the shared-fixture cue to catch the actual
anti-pattern instead of the compliant shape, added the missing cue for
use-assert-isfalse-not-asserterror-for-boolean-checks, wired precedence
between it and the generic asserterror rule, and removed the cue for the
deleted article.
- Added in-file Source provenance (specific fluxxus.nl post per article,
with what was independently verified vs. taken from the post) to the
three surviving externally-inspired articles, per Jesper's request that
provenance live in the knowledge file itself, not only the PR description.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
- transactionmodel-attribute-governs-test-transactions.md: the "Commit
causes an error" behavior is specific to an explicitly declared
AutoRollback attribute. A test method with no TransactionModel
attribute at all is a distinct, valid shape — BCApps' own
codeunit 134915 "ERM Online Mapping Setup" commits inside a lazy
Initialize() with no attribute declared, cleaning up via a manual
asserterror at the end. Evidence for commit-shared-test-fixture-
inside-lazy-initialize.md (this PR), which is correct as submitted.
- confirm-needs-strsubstno-before-confirmhandler-sees-substituted-text.md:
reframe as a known, unconfirmed-fix platform defect
(microsoft/ALAppExtensions#23935) rather than designed behavior; add
the Message/MessageHandler asymmetry as supporting evidence.
- table-relation-test-exclude-known-invalid-relations-via-event.md:
note the test-app-only consumer dependency; correct "walks every
TableRelation field property in the app" to the actual tenant-wide
Table Relations Metadata scope across installed apps.
- Wire confirm-needs-strsubstno, commit-shared-test-fixture-inside-
lazy-initialize, and table-relation-test-exclude-known-invalid-
relations-via-event into al-testing-review.md's candidate-selection
cues.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Fourth batch from CURABIS ApS, mined from an external BC/NAV testing expert's blog archive (fluxxus.nl). Confirm+StrSubstNo interaction with ConfirmHandler, Table Relation Test's OnAfterRemoveTableRelation exclusion hook (verified against BCApps source, codeunit 134926), committing shared lazy-Initialize fixture data, and Assert.IsFalse vs asserterror for boolean checks.
The narrowed UI-handler guidance still stated the execution rule without the
qualifier the linked Microsoft reference uses. The article said every listed
handler must execute at least once, and the testing leaf skill asked for
`[HandlerFunctions(...)]` to match the invoked handlers exactly. The reference
says every *nonoptional* listed handler must execute, and that send-notification
and recall-notification handlers can be optional. As written, an agent could
flag a deliberately unused optional notification handler.
The discriminator is narrower than the handler type. Both
`[SendNotificationHandler([HandlerIsOptional: Boolean])]` and
`[RecallNotificationHandler([HandlerIsOptional: Boolean])]` take an explicit
optionality argument, so `[SendNotificationHandler(true)]` is exempt while the
same attribute written without the argument stays nonoptional like every other
handler type. Keying the exemption on the argument rather than the type keeps it
checkable from the diff and avoids the opposite false positive, where an agent
stops flagging genuinely nonoptional notification handlers.
Changes:
- The article now states the nonoptional qualifier, explains that optionality is
declared rather than inferred, and adds an explicit do-not-flag clause. That
clause also forbids proposing removal, because the listed entry is what keeps
the test passing on the runs where the notification does fire.
- The testing leaf skill carries the same boundary in its `ui-handlers-in-tests`
cue, and its mechanical-fix list no longer allows removing a listed optional
notification handler as a one-click suggestion.
- `SendNotificationHandler` and `RecallNotificationHandler` were missing from the
skill's testing token list, so notification handlers were not reliably
surfaced to the relevance step at all. Both are now listed.
- The good sample gains a test that lists an unreached
`[SendNotificationHandler(true)]`; the bad sample gains the mirror image, an
unreached `[SendNotificationHandler]` with no optionality argument. The pair
differs only by that argument, which is the point.
- `evaluation/review-fixtures.json` pins the testing domain to
`ui-handlers-in-tests` so the boundary is exercised: the good sample is the
clean control at `minimumCleanRate` 1.0 and the bad sample is the expected
finding. Keywords were retagged with `notification` and `optional-handler`.
validate_frontmatter.py reports 0 errors; Test-ReviewFixtures.ps1 passes with
32 cases across 16 leaf domains and resolves the testing fixture to this article.
data-modeling: add insert-only-transfer-may-rely-on-caller-cleanup. A filter-and-insert transfer routine was reported for stale rows and duplicate keys even though the field OnValidate trigger calls a sibling cleanup procedure that clears the same range immediately before it. Deciding this requires reading the caller, so the article asks reviewers to trace call sites and keeps uncleared or mismatched-filter paths reportable.
appsource: scope two-level-namespace-replaces-object-affix-not-extension-member-affix to apps that actually configure a mandatory affix. AS0011 only runs when AppSourceCop is enabled with a mandatory affix; a first-party in-box app that ships no such configuration is not subject to it. The member-affix requirement itself is unchanged for apps that do configure one.
testing: allow permission-tests-must-lower-the-execution-context to accept a composed role. The article demanded the exact permission set under test be assigned directly, so a test that lowered permissions through a role including that set and then asserted WritePermission was false was reported as a coverage gap. What matters is the effective context plus a boundary assertion, not which object the test names.
Co-authored-by: wenjiefan <wenjiefan@microsoft.com>
* 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>
* Add testing knowledge: UI handlers, table relations, asserterror, fixtures (P1+P2)
Six BC-specific testing-domain knowledge articles in community/knowledge/testing/, each with .good.al/.bad.al samples:
- ui-calls-require-test-handlers
- tablerelation-requires-prerequisite-records
- handlers-enqueue-never-assert
- handlerfunctions-attribute-must-match-ui-path
- asserterror-needs-expectederror-and-code
- use-library-codeunits-for-test-fixtures
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Move testing knowledge from community to microsoft layer
Relocates the six P1+P2 testing-domain articles (18 files: .md + .good.al + .bad.al each) from community/knowledge/testing/ to microsoft/knowledge/testing/ per maintainer request. Pure git-mv rename; no content or frontmatter changes.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Address review: merge handler articles, adopt enqueue-driven pattern
Respond to @nikolakukrika's review on #62:
- Merge ui-calls-require-test-handlers, handlerfunctions-attribute-must-match-ui-path
and handlers-enqueue-never-assert into a single ui-handlers-in-tests article.
- Adopt the enqueue-from-test / dequeue-and-assert-in-handler pattern using
Assert.ExpectedConfirm/ExpectedMessage (substring match), with Initialize()
clearing LibraryVariableStorage and AssertEmpty() proving exact call counts.
- asserterror sample now uses Assert.ExpectedTestFieldError + FieldCaption instead
of hardcoded message/code; article text points to the library helpers.
- Drop the tablerelation article and fold its test-relevant ordering point
(relations checked on Validate/Insert(true); build parents first) into
use-library-codeunits-for-test-fixtures.
Article count 198 -> 195.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
---------
Co-authored-by: Jesper Schulz-Wedde <jesper.schulzwedde@microsoft.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>