- 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.
3.5 KiB
| bc-version | domain | keywords | technologies | countries | application-area | |||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
testing |
|
|
|
|
Exclude a known-valid TableRelation exception via OnAfterRemoveTableRelation
Description
Codeunit 134926 "Table Relation Test" (shipped in BCApps' test app — only consumers that depend on the BC test libraries can subscribe to it) reads Table Relations Metadata tenant-wide across every installed app, not just the current one, and validates each field's type and length against what its relations require — but the exact rule depends on whether that field has an unconditional relation (a Table Relations Metadata row with Condition Field No. = 0) among its relations, or only conditional ones:
- If any relation is unconditional, the field's length must equal exactly the largest related field's length, and its type must exactly match the required type — resolved to
Textwhen the related fields themselves mixCodeandText. - If every relation for that field is conditional, the requirement relaxes: the field only needs to be at least as long as the largest related field (longer is accepted; only shorter fails), and when the required type is specifically
Code, both aCodeand aTextsource field pass. ThatCode/Texttolerance is conditional-only — it does not apply on the unconditional side, and it does not extend to a required type ofText(aCodesource field does not satisfy a requiredText).
A field with a legitimate, intentional relation shape outside both of these tolerances has no per-field override in its own object definition; the check runs with no built-in escape hatch beyond them. The validation test method itself is [Scope('OnPrem')]: it only runs from an on-premises test surface, not from a cloud-targeted test app, so this whole exception mechanism — and the check it works around — is only reachable where that test can actually execute.
Best Practice
Subscribe to OnAfterRemoveTableRelation and call the codeunit's own RemoveTableRelation(TableRelationsMetadata, TableID, FieldID, RelatedTableID, RelatedFieldID) to strike the one known-valid relation before the test evaluates it, scoped as narrowly as the exception actually is. Because the test itself is [Scope('OnPrem')], do not recommend subscribing to it as a way to guard a cloud-targeted app's test suite — the subscription has no effect where the test never runs.
See sample: table-relation-test-exclude-known-invalid-relations-via-event.good.al.
Anti Pattern
Excluding an entire table's relations (or disabling the whole test codeunit) to work around one known exception. This discards the check's coverage for every other relation on that table, or in the app, not just the one that needed an exception.
See sample: table-relation-test-exclude-known-invalid-relations-via-event.bad.al.
Source
The OnAfterRemoveTableRelation exclusion technique is drawn from Luc van Vugt's "How-to: Test your Table Relations (2)": https://www.fluxxus.nl/index.php/bc/how-to-test-your-table-relations-2/. The codeunit/event signature, the [Scope('OnPrem')] boundary, and the tenant-wide Table Relations Metadata scope described above were verified directly against BCApps' codeunit 134926 "Table Relation Test" source, not taken from the post.