3 AL/BC patterns from CURABIS's internal automated-testing training material - #158
Conversation
Third batch from CURABIS ApS: item-ledger-entry document-no lookup after Ship-and-Invoice posting, TestPage.Visible()/.Enabled() as the mechanism for verifying field UI state, and LibraryUtility.GenerateGUID() for collision-free test fixture values.
Jesper Schulz-Wedde (JesperSchulz)
left a comment
There was a problem hiding this comment.
The Item Ledger Entry pattern checks out against current BCApps source: combined Ship+Invoice posting stamps the item journal line with the posted shipment number, while LibrarySales.PostSalesDocument returns Last Posting No. because the invoice branch overwrites its return-field selection.
I found two accuracy blockers in the testing guidance (called out inline) and one consumption gap: the current al-testing-review worklist has no GenerateGUID/CopyStr or TestPage Visible/Enabled/Editable cues or targeted checks, and al-data-modeling-review scopes relevance to setup/master-table surfaces without any Item Ledger Entry/posting cue. Please wire all three articles into their corresponding review-skill worklists so agents can actually select them; coordinate this with #155, whose contracts state that targeted checks cover every current article.
The CLA is also still pending. Because the PR says the material was mined from CURABIS's internal Academy course book, the contributor needs to use the applicable company/employer declaration, confirm authorization to contribute the derived material, and make any third-party-material disclosure required by the CLA.
|
@microsoft-github-policy-service agree [company="CURABIS ApS"] |
|
@microsoft-github-policy-service agree company="CURABIS ApS" |
- use-generateguid-for-unique-test-fixture-values.md: GenerateGUID() is a Code[10] number-series value, not a real GUID; truncating it with CopyStr for a shorter field cuts off the changing digits. Point to GenerateRandomCode/GenerateRandomCodeWithLength/GenerateRandomXMLText instead, which verify uniqueness against the actual table. - Split use-testpage-visible-enabled-to-verify-field-ui-state.md: drop its editability claim (the sample opens with OpenView() and asserts Enabled(), which verifies enabled state, not editability — Editable() and Enabled() are distinct TestField methods). New companion article use-testpage-editable-to-verify-field-editability.md covers Editable() with OpenEdit() specifically. - Wire GenerateGUID/CopyStr and TestPage Visible/Enabled/Editable cues into al-testing-review.md, and the Item Ledger Entry/Last Shipping No. posting cue into al-data-modeling-review.md. The Item Ledger Entry article itself was independently verified against current BCApps source and needs no changes. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Jesper Schulz-Wedde (JesperSchulz)
left a comment
There was a problem hiding this comment.
Follow-up after ab4ed50: the Visible/Enabled scope and the Editable/OpenEdit distinction now look sound, and the Item Ledger Entry article is reasonable for combined sales Ship+Invoice posting. The three remaining substantive issues are inline.
Please also update the PR description: it still advertises the superseded GenerateGUID() + CopyStr recommendation and no longer describes the current change.
- use-generateguid-for-unique-test-fixture-values.md/.good.al: documented each LibraryUtility helper's actual behavior, verified against LibraryUtility.Codeunit.al. GenerateRandomCode opens the target table as a temporary RecordRef, so despite taking TableNo it never checks real data. GenerateRandomXMLText performs no table lookup at all. Only GenerateRandomCodeWithLength/GenerateRandomCode20 (capped at Code[10]/ Code[20]) genuinely verify against the real table. Fixture switched to GenerateRandomCodeWithLength where the comment claims verified uniqueness. - al-testing-review.md: rewired the cue to catch the actual anti-pattern (hardcoded literals, hand-built uniqueness, short-field GUID truncation) instead of only matching the compliant GenerateGUID()+CopyStr shape; broadened tokens to include TestPage, Library - Utility, and .Visible()/.Enabled()/.Editable(). - al-data-modeling-review.md: restricted the Item Ledger Entry Last-Shipping-No. cue to sales combined posting; purchase combined posting is Receive+Invoice and uses different fields entirely. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
|
Jesper Schulz-Wedde (@JesperSchulz) Addressed in 1d05811 (pushed 2026-09-08): the 4 inline issues above, plus the PR description — updated to describe the actual current recommendation (pick the |
Jesper Schulz-Wedde (JesperSchulz)
left a comment
There was a problem hiding this comment.
Thank you—the helper behavior, fixture implementation, review relevance, sales-only posting scope, and PR description are all much improved. This PR is very close.
Two factual points remain in the uniqueness article. We recognize that another round is inconvenient, but these claims directly determine which test code agents will flag and which helper guarantees they will trust, so they need to be precise. We have limited the feedback to those two points and omitted optional cleanup.
|
|
||
| ## Description | ||
|
|
||
| A fixture helper that assigns a hardcoded literal to a primary-key or descriptive field collides the moment two tests, or two runs of the same test, create that fixture without cleanup, and a literal longer than the field allows raises a truncation or insert error. `LibraryUtility.GenerateGUID()` is not a real GUID — it is a `Code[10]` number-series value (`GU00000000`–`GU99999999`) — and it returns the full 10 characters unshortened. Truncating it yourself with `CopyStr(..., 1, MaxStrLen(ShorterField))` for a field under 10 characters is unsafe: the changing digits sit at the right end and are exactly what gets cut off, so consecutive calls into a short field can produce the same truncated value. `GenerateGUID()` is only safe as-is for a field that holds the full 10 characters. |
There was a problem hiding this comment.
Please restrict the collision rule to primary/unique-key fields or values the test explicitly relies on as unique lookup identifiers. An ordinary descriptive field is not unique, so two rows with the same description do not collide on insert; deterministic descriptive text is also often required for exact assertions. The anti-pattern at line 31 and the testing review cue should be narrowed consistently so agents do not flag valid descriptive test data.
|
|
||
| For a field that holds the full 10 characters, assign `LibraryUtility.GenerateGUID()` directly. For a shorter field, do not truncate a GUID yourself — but also do not assume every `LibraryUtility` helper verifies uniqueness against the real table, because they don't all behave the same way: | ||
|
|
||
| - `GenerateRandomCode(FieldNo, TableNo)` opens the target table as a **temporary** `RecordRef`, so its own emptiness check never inspects real rows — despite taking `TableNo`, it does not verify against the actual table. It's safe to use for its non-colliding-*within-a-single-test-run* value (derived from `GenerateGUID()`'s own number series), not for a guarantee against pre-existing or leftover data. |
There was a problem hiding this comment.
GenerateRandomCode cannot guarantee non-collision even within one test run for short fields. It takes the rightmost FieldRef.Length characters of the sequential GenerateGUID() value but does not remember earlier temporary results; a Code[1] value repeats every 10 calls, Code[2] every 100, and so on. Please remove the within-run guarantee and describe it consistently with line 25 as a finite short-field namespace with only a low collision chance. Keep the real-table helpers for cases that require verified uniqueness.
Summary
Third batch from CURABIS ApS, mined from CURABIS's own internal Academy course book on automated/BDD testing in Business Central. Same format as #156/#157 (6-key frontmatter, Description/Best Practice/Anti Pattern, sibling
.good.al/.bad.alsamples, no fenced code in the .md).Sales Header."Last Shipping No."), not the posted invoice number — a lookup filtered on the invoice number silently matches zero rows. Sales-specific; purchase combined posting (Receive+Invoice) uses different fields.TestPagefield.Visible()/.Enabled(), and its editability specifically with.Editable()opened viaOpenEdit()— these are distinct states requiring different verification. Generate test fixture values via the rightLibraryUtilityhelper for the guarantee actually needed:GenerateRandomCodeWithLength/GenerateRandomCode20when uniqueness against the real table must be verified,GenerateGUID()(untruncated, full-length fields only) orGenerateRandomCode/GenerateRandomXMLTextfor incidental values — not hardcoded literals or a truncated GUID.Most of the source book turned out to be BDD philosophy and CURABIS process content that doesn't clear BCQuality's admission test — these 4 are the genuinely atomic, non-obvious AL-specific patterns that survived a full read-through, checked against the current
microsoft/knowledge/corpus and CURABIS's own two prior PRs for overlap.Test plan
🤖 Generated with Claude Code