Fix remaining correctness issues from Jesper's 2026-09-15 re-review

- 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.
This commit is contained in:
Michael Dieringer 2026-09-21 22:49:39 +02:00
parent 1392521a8e
commit 69b09db3a6
6 changed files with 100 additions and 16 deletions

View file

@ -4,6 +4,7 @@ codeunit 50142 "Sample Test Library"
var
Initialized: Boolean;
SharedItemNo: Code[20];
RollBackMsg: Label 'Revert back the tables to their original state.';
local procedure Initialize()
@ -12,23 +13,62 @@ codeunit 50142 "Sample Test Library"
exit;
CreateSharedFixtureData();
// BUG: no Commit() here. The fixture below is still inside this
// test method's own transaction.
Initialized := true;
end;
local procedure CreateSharedFixtureData()
var
Item: Record Item;
begin
// insert master/setup data shared across every test in this codeunit
Item.Init();
Item."No." := 'SAMPLE-SHARED';
Item.Insert(true);
SharedItemNo := Item."No.";
end;
[Test]
procedure FirstTestUsesSharedFixture()
var
Item: Record Item;
begin
Initialize();
// exercise/verify against the shared fixture, then make scratch changes of its own
Item.Get(SharedItemNo);
Item.Description := 'Scratch change this test makes and does not need to keep.';
Item.Modify();
asserterror Error(RollBackMsg);
// the deliberate rollback above also erases the never-committed fixture;
// Initialized still reads true on the next test, but the rows are gone
// The deliberate rollback above also erases the never-committed
// fixture from CreateSharedFixtureData(). Initialized still reads
// true on the next test, but the row it points at is gone.
end;
[Test]
procedure SecondTestStillFindsSharedFixture()
var
Item: Record Item;
begin
Initialize();
// Fails here: Initialize() saw Initialized = true and returned
// immediately, so it never recreated the fixture - and the first
// test's rollback took the original row with it.
Item.Get(SharedItemNo);
end;
}
codeunit 50143 "Sample Test Runner"
{
// Codeunit isolation alone does not save this fixture: TestIsolation
// only controls whether committed changes survive between methods, and
// this fixture was never committed in the first place.
Subtype = TestRunner;
TestIsolation = Codeunit;
trigger OnRun()
begin
Codeunit.Run(Codeunit::"Sample Test Library");
end;
}