mirror of
https://github.com/microsoft/BCQuality.git
synced 2026-08-06 09:26:52 +01:00
update
This commit is contained in:
parent
822cae1b27
commit
c4a9f8e88e
2 changed files with 136 additions and 0 deletions
|
|
@ -0,0 +1,65 @@
|
|||
---
|
||||
bc-version: [all]
|
||||
domain: architecture
|
||||
keywords: [page, trigger, onaction, modify, codeunit, logic]
|
||||
technologies: [al]
|
||||
countries: [w1]
|
||||
application-area: [all]
|
||||
---
|
||||
|
||||
## Description
|
||||
|
||||
In CURABIS codebases, pages are pure presentation. Business logic, calculations,
|
||||
validations, and record modifications belong in codeunits — not in page triggers
|
||||
or actions. This is stricter than the general BC guidance and applies to all
|
||||
CURABIS PTE apps.
|
||||
|
||||
A page procedure that calculates a value and assigns it to a field, calls
|
||||
`Rec.Modify()` directly, or implements business rules is an architecture violation
|
||||
even if it compiles.
|
||||
|
||||
**Exceptions:**
|
||||
- Setup pages may read and write their own setup record directly.
|
||||
- The designated "Run Conversion" page may call the conversion codeunit directly.
|
||||
|
||||
## Anti Pattern
|
||||
|
||||
```al
|
||||
// WRONG: calculation and Modify in a page action
|
||||
trigger OnAction()
|
||||
begin
|
||||
Rec."Total Amount" := Rec.Quantity * Rec."Unit Price";
|
||||
Rec."VAT Amount" := Rec."Total Amount" * 0.25;
|
||||
Rec.Modify();
|
||||
end;
|
||||
```
|
||||
|
||||
```al
|
||||
// WRONG: validation logic in page trigger
|
||||
trigger OnValidate()
|
||||
begin
|
||||
if Rec.Quantity < 0 then
|
||||
Error('Quantity cannot be negative');
|
||||
Rec."Total Amount" := Rec.Quantity * Rec."Unit Price";
|
||||
end;
|
||||
```
|
||||
|
||||
## Best Practice
|
||||
|
||||
```al
|
||||
// CORRECT: page delegates to codeunit
|
||||
trigger OnAction()
|
||||
begin
|
||||
SVManagement.RecalculateLine(Rec);
|
||||
end;
|
||||
```
|
||||
|
||||
```al
|
||||
// CORRECT: validation belongs in table or codeunit
|
||||
trigger OnValidate()
|
||||
begin
|
||||
SVManagement.ValidateAndRecalculate(Rec);
|
||||
end;
|
||||
```
|
||||
|
||||
The codeunit owns the logic. The page owns the presentation.
|
||||
|
|
@ -0,0 +1,71 @@
|
|||
---
|
||||
bc-version: [all]
|
||||
domain: testing
|
||||
keywords: [test, library, setup, initialize, suppresscommit, asserterror]
|
||||
technologies: [al]
|
||||
countries: [w1]
|
||||
application-area: [all]
|
||||
---
|
||||
|
||||
## Description
|
||||
|
||||
In CURABIS test apps, all test setup is centralized in a dedicated Test Library
|
||||
codeunit (e.g. `SV Test Library`). Individual test procedures must not call
|
||||
BC standard library codeunits (`LibrarySales`, `LibraryInventory`, etc.) directly.
|
||||
|
||||
Additionally, two rules apply to every test that calls a posting codeunit:
|
||||
|
||||
1. `SetSuppressCommit(true)` must be called before `Run()` to prevent data
|
||||
from leaking between tests.
|
||||
2. `asserterror` must always be followed by `Assert.ExpectedErrorCode()` or
|
||||
`Assert.ExpectedError()` — a naked `asserterror` passes on any error,
|
||||
not just the expected one.
|
||||
|
||||
## Anti Pattern
|
||||
|
||||
```al
|
||||
// WRONG: inline setup bypassing the test library
|
||||
procedure MyTest()
|
||||
var
|
||||
Item: Record Item;
|
||||
begin
|
||||
LibraryInventory.CreateItem(Item); // do not call directly
|
||||
// ...
|
||||
end;
|
||||
```
|
||||
|
||||
```al
|
||||
// WRONG: posting without SuppressCommit
|
||||
SVPost.Run(SVHeader); // commits to test database
|
||||
```
|
||||
|
||||
```al
|
||||
// WRONG: naked asserterror
|
||||
asserterror SVPost.Run(SVHeader);
|
||||
// no assertion follows — passes on any error
|
||||
```
|
||||
|
||||
## Best Practice
|
||||
|
||||
```al
|
||||
// CORRECT: delegate to test library
|
||||
procedure MyTest()
|
||||
var
|
||||
Item: Record Item;
|
||||
begin
|
||||
SVLib.GivenScrapItem(Item); // test library owns setup
|
||||
// ...
|
||||
end;
|
||||
```
|
||||
|
||||
```al
|
||||
// CORRECT: SuppressCommit before Run
|
||||
SVPost.SetSuppressCommit(true);
|
||||
SVPost.Run(SVHeader);
|
||||
```
|
||||
|
||||
```al
|
||||
// CORRECT: asserterror followed by assertion
|
||||
asserterror SVPost.Run(SVHeader);
|
||||
Assert.ExpectedErrorCode('Dialog');
|
||||
```
|
||||
Loading…
Add table
Add a link
Reference in a new issue