mirror of
https://github.com/microsoft/BCQuality.git
synced 2026-08-06 09:26:52 +01:00
newrules
This commit is contained in:
parent
5c13823850
commit
a49823a542
4 changed files with 258 additions and 0 deletions
16
.altestrunner/config.json
Normal file
16
.altestrunner/config.json
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
{
|
||||
"containerResultPath": "",
|
||||
"launchConfigName": "",
|
||||
"securePassword": "",
|
||||
"userName": "",
|
||||
"companyName": "",
|
||||
"testSuiteName": "",
|
||||
"vmUserName": "",
|
||||
"vmSecurePassword": "",
|
||||
"remoteContainerName": "",
|
||||
"dockerHost": "",
|
||||
"newPSSessionOptions": "",
|
||||
"testRunnerServiceUrl": "",
|
||||
"codeCoveragePath": ".altestrunner\\codecoverage.json",
|
||||
"culture": "en-US"
|
||||
}
|
||||
|
|
@ -0,0 +1,81 @@
|
|||
---
|
||||
bc-version: [all]
|
||||
domain: architecture
|
||||
keywords: [naming, english, enu, variable, procedure, field, caption, translation, xliff]
|
||||
technologies: [al]
|
||||
countries: [w1]
|
||||
application-area: [all]
|
||||
---
|
||||
|
||||
## Description
|
||||
|
||||
All AL identifiers must be written in English (ENU) regardless of the language
|
||||
used in conversation with the developer. Translations are handled separately
|
||||
via XLIFF files — never by writing Danish, German or other language identifiers
|
||||
in AL source code.
|
||||
|
||||
This applies to:
|
||||
- Variable names
|
||||
- Procedure names
|
||||
- Parameter names
|
||||
- Field names
|
||||
- Object names (tables, codeunits, pages, enums, reports)
|
||||
- Enum value names
|
||||
- Local and global labels (Label data type) — both the identifier and the default text
|
||||
|
||||
**Captions and ToolTips** may be in the target language in the source file,
|
||||
but must also be covered by XLIFF translations for all supported locales.
|
||||
|
||||
## Anti Pattern
|
||||
|
||||
```al
|
||||
// WRONG: Danish identifiers
|
||||
var
|
||||
Kreditor: Record Vendor;
|
||||
Beløb: Decimal;
|
||||
AntalKilo: Decimal;
|
||||
|
||||
procedure BeregnTotalbeløb(Antal: Decimal; Pris: Decimal): Decimal
|
||||
begin
|
||||
exit(Antal * Pris);
|
||||
end;
|
||||
|
||||
field(50101; "Indgående Mængde"; Decimal) { Caption = 'Indgående Mængde'; }
|
||||
```
|
||||
|
||||
## Best Practice
|
||||
|
||||
```al
|
||||
// CORRECT: English identifiers, Danish captions handled via XLIFF
|
||||
var
|
||||
Vendor: Record Vendor;
|
||||
Amount: Decimal;
|
||||
QuantityKg: Decimal;
|
||||
|
||||
procedure CalculateTotalAmount(Quantity: Decimal; UnitPrice: Decimal): Decimal
|
||||
begin
|
||||
exit(Quantity * UnitPrice);
|
||||
end;
|
||||
|
||||
field(50101; "Inbound Quantity"; Decimal) { Caption = 'Inbound Quantity'; }
|
||||
// Caption translation → da-DK XLIFF: 'Indgående Mængde'
|
||||
|
||||
// WRONG: Danish label identifier and text
|
||||
var
|
||||
BeløbFejlTxt: Label 'Beløbet må ikke være negativt';
|
||||
|
||||
// CORRECT: English label identifier and default text — translated via XLIFF
|
||||
var
|
||||
AmountMustNotBeNegativeErr: Label 'Amount must not be negative.', Comment = '%1 = Amount';
|
||||
```
|
||||
|
||||
## Conversation vs. code
|
||||
|
||||
The developer may describe requirements in Danish. The agent must translate
|
||||
the intent into English identifiers when writing AL code:
|
||||
|
||||
- "opret en variabel til beløbet" → `var Amount: Decimal;`
|
||||
- "procedure der beregner lagerværdien" → `procedure CalculateInventoryValue(...)`
|
||||
- "felt til indgående mængde" → `field(... ; "Inbound Quantity"; Decimal)`
|
||||
|
||||
Never echo Danish words from the conversation directly into AL identifiers.
|
||||
|
|
@ -0,0 +1,86 @@
|
|||
---
|
||||
bc-version: [all]
|
||||
domain: architecture
|
||||
keywords: [namespace, using, compile, al-language, tablerelation, variable, codeunit]
|
||||
technologies: [al]
|
||||
countries: [w1]
|
||||
application-area: [all]
|
||||
---
|
||||
|
||||
## Description
|
||||
|
||||
When an agent adds a variable referencing a BC or custom object, it must verify
|
||||
the correct namespace by reading the source file of that object — not by guessing
|
||||
or relying on its training data.
|
||||
|
||||
An AL file that "compiles" in the agent's own build may still show as red in
|
||||
VS Code because the AL Language Server resolves namespaces differently.
|
||||
The authoritative source for a namespace is always the object's own source file.
|
||||
|
||||
This rule applies to:
|
||||
- `using` declarations at the top of a codeunit, table, page or enum
|
||||
- Variable declarations that reference tables, codeunits, pages or enums
|
||||
- `TableRelation` and `CalcFormula` references
|
||||
|
||||
## How to verify a namespace
|
||||
|
||||
Before adding a `using` statement or a variable referencing an object, the agent
|
||||
must locate and read the source file for that object:
|
||||
|
||||
```
|
||||
// Step 1: Find the source file
|
||||
Glob: "**/[ObjectName].*.al" or al_symbolsearch query: "[ObjectName]"
|
||||
|
||||
// Step 2: Read the first line — the namespace declaration
|
||||
namespace SettlementVoucher.SettlementVoucher; ← this is what to use
|
||||
|
||||
// Step 3: Add the using statement in the consuming file
|
||||
using SettlementVoucher.SettlementVoucher;
|
||||
```
|
||||
|
||||
If the object is a Microsoft base application object, use `al_symbolsearch` to
|
||||
look up the correct namespace — do not assume it from the object name alone.
|
||||
Microsoft namespaces changed significantly from BC24 onwards.
|
||||
|
||||
## Anti Pattern
|
||||
|
||||
```al
|
||||
// WRONG: Guessing the namespace from the object name
|
||||
using Microsoft.Purchases.Vendor; // guessed — may be wrong
|
||||
using SettlementVoucher; // incomplete — missing sub-namespace
|
||||
|
||||
var
|
||||
Vendor: Record Vendor; // missing using → red in AL Language Server
|
||||
SVPost: Codeunit "SV Post"; // wrong namespace → unresolved reference
|
||||
```
|
||||
|
||||
## Best Practice
|
||||
|
||||
```al
|
||||
// CORRECT: Read SVPost.Codeunit.al first → find: namespace SettlementVoucher.SettlementVoucher
|
||||
// CORRECT: Use al_symbolsearch to find Vendor → namespace Microsoft.Purchases.Vendor
|
||||
|
||||
using Microsoft.Purchases.Vendor;
|
||||
using Microsoft.Finance.GeneralLedger.Ledger;
|
||||
using SettlementVoucher.SettlementVoucher;
|
||||
|
||||
codeunit 50204 "SV Incoming Item Flow Tests"
|
||||
{
|
||||
var
|
||||
Vendor: Record Vendor;
|
||||
GLEntry: Record "G/L Entry";
|
||||
SVPost: Codeunit "SV Post";
|
||||
```
|
||||
|
||||
## Verification step before delivering code
|
||||
|
||||
After writing any AL file, the agent must:
|
||||
|
||||
1. List every `using` statement in the file
|
||||
2. For each one: confirm the namespace was read from the actual source file
|
||||
or looked up via `al_symbolsearch` — not assumed
|
||||
3. If any namespace was assumed rather than verified, re-read the source and correct it
|
||||
|
||||
Never report "compiled successfully" based on a build that did not go through
|
||||
the AL Language Server in VS Code. The definitive compilation result is what
|
||||
VS Code shows — not the agent's internal build.
|
||||
|
|
@ -0,0 +1,75 @@
|
|||
---
|
||||
bc-version: [all]
|
||||
domain: testing
|
||||
keywords: [test, refactor, adapt, existing-code, green, failing, tdd]
|
||||
technologies: [al]
|
||||
countries: [w1]
|
||||
application-area: [all]
|
||||
---
|
||||
|
||||
## Description
|
||||
|
||||
When a CURABIS developer asks for a test that "must work" or "must pass",
|
||||
the agent's job is to write a test that passes against the **existing production code**
|
||||
— not to write an idealized test and then report that the code needs changing.
|
||||
|
||||
This rule applies in two distinct scenarios:
|
||||
|
||||
**Scenario A — New test for existing behaviour**
|
||||
The production code is correct and stable. Write the test to match what the code
|
||||
actually does. Read the relevant codeunits before writing assertions. If the
|
||||
expected value in the story differs from what the code produces, surface the
|
||||
discrepancy and ask before assuming either is wrong.
|
||||
|
||||
**Scenario B — Refactoring an existing test**
|
||||
The test exists but fails because the production code was changed. Adapt the
|
||||
test to match the new behaviour. Do not rewrite the production code to make
|
||||
the old test pass unless explicitly asked to refactor production code.
|
||||
|
||||
## The distinction that matters
|
||||
|
||||
Writing a test that adapts to existing code is **not** the same as writing a
|
||||
test that accepts wrong behaviour silently. If the production code contains a
|
||||
bug that contradicts the business specification, flag it explicitly:
|
||||
|
||||
```
|
||||
// ⚠️ NOTE: This assertion reflects current code behaviour.
|
||||
// Business spec says 1792,00 but code currently produces 1800,00.
|
||||
// Flagged for review — do not merge until resolved.
|
||||
```
|
||||
|
||||
Never silently adjust an assertion to make a test green when the discrepancy
|
||||
is a real business logic error.
|
||||
|
||||
## Anti Pattern
|
||||
|
||||
```al
|
||||
// WRONG: Writing the "ideal" test without reading the production code,
|
||||
// then leaving it failing and saying "the code needs to be fixed"
|
||||
[THEN]
|
||||
Assert.AreEqual(1792, ActualAmount, 'Total should be 1792');
|
||||
// Test fails. Agent says: "You need to fix SVPost to produce 1792."
|
||||
// This is not what was asked for.
|
||||
```
|
||||
|
||||
## Best Practice
|
||||
|
||||
```al
|
||||
// CORRECT: Read SVPost, understand what it produces, write the test to match.
|
||||
// If the number is 1792 in both spec and code → assert 1792.
|
||||
// If the number differs → flag it, don't silently change it.
|
||||
|
||||
// [GIVEN] Read SVPost.Codeunit.al and SV Test Library before writing assertions.
|
||||
// [THEN] Assert what the code actually produces, verified by reading the source.
|
||||
Assert.AreEqual(ExpectedAmount, ActualAmount, 'Net payout to vendor must match');
|
||||
```
|
||||
|
||||
## Workflow when asked to write a passing test
|
||||
|
||||
1. Read the relevant production codeunits (SVPost, SVApplyMgt, etc.)
|
||||
2. Trace the calculation path for the specific scenario
|
||||
3. Derive the expected values from the code — not only from the story
|
||||
4. If code and story agree → write the test with those values
|
||||
5. If code and story disagree → write the test with the code's values AND add
|
||||
a clearly visible `// ⚠️ NOTE` comment explaining the discrepancy
|
||||
6. Never leave a test failing when the task was to write a passing test
|
||||
Loading…
Add table
Add a link
Reference in a new issue