mirror of
https://github.com/microsoft/BCQuality.git
synced 2026-08-06 17:36:53 +01:00
Add unit tests and knowledge files for BC domain context
- Introduced unit tests for the bc-domain-context implementation, covering various scenarios including filtering by application area, technology mismatches, layer precedence, and conditional applicability. - Added knowledge files related to finance, including topics such as Chart of Accounts, Codeunit 12, Dimension Management, and VAT on prepayment chains, among others. - Each knowledge file includes structured metadata and best practices to enhance the domain knowledge available for Business Central tasks.
This commit is contained in:
parent
0142e1e0de
commit
7fbb121c24
18 changed files with 1170 additions and 1 deletions
297
.github/scripts/tests/test_bc_domain_context.py
vendored
Normal file
297
.github/scripts/tests/test_bc_domain_context.py
vendored
Normal file
|
|
@ -0,0 +1,297 @@
|
|||
#!/usr/bin/env python3
|
||||
"""
|
||||
Tests for the bc-domain-context reference implementation.
|
||||
|
||||
Run with: python -m unittest .github.scripts.tests.test_bc_domain_context
|
||||
Or: cd .github/scripts/tests && python -m unittest test_bc_domain_context
|
||||
|
||||
The tests build fixture knowledge trees in tempfile directories and exercise
|
||||
the skill's Source / Relevance / Worklist / Action pipeline end to end.
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
import os
|
||||
import sys
|
||||
import tempfile
|
||||
import textwrap
|
||||
import unittest
|
||||
from pathlib import Path
|
||||
|
||||
# Add the scripts directory (parent of tests/) to sys.path so we can import
|
||||
# bc_domain_context.py.
|
||||
_SCRIPTS_DIR = Path(__file__).resolve().parent.parent
|
||||
sys.path.insert(0, str(_SCRIPTS_DIR))
|
||||
|
||||
from bc_domain_context import run_bc_domain_context # noqa: E402
|
||||
|
||||
|
||||
def _write(
|
||||
root: Path,
|
||||
layer: str,
|
||||
domain: str,
|
||||
slug: str,
|
||||
*,
|
||||
bc_version: str = "[26..28]",
|
||||
technologies: str = "[al]",
|
||||
countries: str = "[w1]",
|
||||
application_area: str | None = None,
|
||||
keywords: str = "[sample]",
|
||||
domain_value: str | None = None,
|
||||
description: str = "Short description. Another sentence.",
|
||||
title: str | None = None,
|
||||
) -> Path:
|
||||
"""Write a fixture knowledge file and return its path."""
|
||||
if application_area is None:
|
||||
application_area = f"[{domain}]"
|
||||
if domain_value is None:
|
||||
domain_value = domain
|
||||
if title is None:
|
||||
title = slug.replace("-", " ").capitalize()
|
||||
target = root / layer / "knowledge" / domain / f"{slug}.md"
|
||||
target.parent.mkdir(parents=True, exist_ok=True)
|
||||
target.write_text(
|
||||
textwrap.dedent(
|
||||
f"""\
|
||||
---
|
||||
bc-version: {bc_version}
|
||||
domain: {domain_value}
|
||||
keywords: {keywords}
|
||||
technologies: {technologies}
|
||||
countries: {countries}
|
||||
application-area: {application_area}
|
||||
---
|
||||
|
||||
# {title}
|
||||
|
||||
## Description
|
||||
|
||||
{description}
|
||||
"""
|
||||
),
|
||||
encoding="utf-8",
|
||||
)
|
||||
return target
|
||||
|
||||
|
||||
class BcDomainContextTests(unittest.TestCase):
|
||||
def setUp(self):
|
||||
self._tmp = tempfile.TemporaryDirectory()
|
||||
self.root = Path(self._tmp.name)
|
||||
self.addCleanup(self._tmp.cleanup)
|
||||
|
||||
# --- Core filtering ---
|
||||
|
||||
def test_filter_by_area_returns_only_requested_area(self):
|
||||
_write(self.root, "microsoft", "finance", "chart-of-accounts")
|
||||
_write(self.root, "microsoft", "finance", "general-ledger-entries")
|
||||
_write(self.root, "microsoft", "finance", "dimensions")
|
||||
_write(self.root, "microsoft", "sales", "order-to-cash")
|
||||
_write(self.root, "microsoft", "sales", "pricing")
|
||||
|
||||
report = run_bc_domain_context(self.root, {
|
||||
"application-area": ["finance"],
|
||||
"technologies": ["al"],
|
||||
"bc-version": 28,
|
||||
"countries": ["w1"],
|
||||
})
|
||||
|
||||
self.assertEqual(report["outcome"], "completed")
|
||||
paths = sorted(f["id"] for f in report["findings"])
|
||||
self.assertEqual(paths, [
|
||||
"microsoft/knowledge/finance/chart-of-accounts.md",
|
||||
"microsoft/knowledge/finance/dimensions.md",
|
||||
"microsoft/knowledge/finance/general-ledger-entries.md",
|
||||
])
|
||||
for finding in report["findings"]:
|
||||
self.assertEqual(finding["severity"], "info")
|
||||
self.assertEqual(finding["confidence"], "high")
|
||||
|
||||
def test_application_area_all_returns_union(self):
|
||||
_write(self.root, "microsoft", "finance", "chart-of-accounts")
|
||||
_write(self.root, "microsoft", "sales", "order-to-cash")
|
||||
_write(self.root, "microsoft", "manufacturing", "bom")
|
||||
|
||||
report = run_bc_domain_context(self.root, {
|
||||
"application-area": ["all"],
|
||||
"technologies": ["al"],
|
||||
"bc-version": 28,
|
||||
"countries": ["w1"],
|
||||
})
|
||||
|
||||
self.assertEqual(report["outcome"], "completed")
|
||||
self.assertEqual(len(report["findings"]), 3)
|
||||
paths = {f["id"] for f in report["findings"]}
|
||||
self.assertIn("microsoft/knowledge/finance/chart-of-accounts.md", paths)
|
||||
self.assertIn("microsoft/knowledge/sales/order-to-cash.md", paths)
|
||||
self.assertIn("microsoft/knowledge/manufacturing/bom.md", paths)
|
||||
|
||||
def test_technologies_mismatch_drops_file(self):
|
||||
_write(self.root, "microsoft", "finance", "al-concept")
|
||||
_write(
|
||||
self.root,
|
||||
"microsoft",
|
||||
"finance",
|
||||
"kql-only-concept",
|
||||
technologies="[kql]",
|
||||
)
|
||||
|
||||
report = run_bc_domain_context(self.root, {
|
||||
"application-area": ["finance"],
|
||||
"technologies": ["al"],
|
||||
"bc-version": 28,
|
||||
"countries": ["w1"],
|
||||
})
|
||||
|
||||
paths = {f["id"] for f in report["findings"]}
|
||||
self.assertIn("microsoft/knowledge/finance/al-concept.md", paths)
|
||||
self.assertNotIn("microsoft/knowledge/finance/kql-only-concept.md", paths)
|
||||
|
||||
def test_no_matching_knowledge_returns_not_applicable(self):
|
||||
_write(self.root, "microsoft", "finance", "chart-of-accounts")
|
||||
|
||||
report = run_bc_domain_context(self.root, {
|
||||
"application-area": ["manufacturing"],
|
||||
"technologies": ["al"],
|
||||
"bc-version": 28,
|
||||
"countries": ["w1"],
|
||||
})
|
||||
|
||||
self.assertEqual(report["outcome"], "no-knowledge")
|
||||
self.assertEqual(report["findings"], [])
|
||||
|
||||
# --- Layer precedence ---
|
||||
|
||||
def test_layer_precedence_microsoft_wins_over_community(self):
|
||||
_write(self.root, "community", "finance", "vat-on-prepayment")
|
||||
_write(self.root, "microsoft", "finance", "vat-on-prepayment")
|
||||
|
||||
report = run_bc_domain_context(self.root, {
|
||||
"application-area": ["finance"],
|
||||
"technologies": ["al"],
|
||||
"bc-version": 28,
|
||||
"countries": ["w1"],
|
||||
})
|
||||
|
||||
paths = [f["id"] for f in report["findings"]]
|
||||
self.assertEqual(
|
||||
paths, ["microsoft/knowledge/finance/vat-on-prepayment.md"]
|
||||
)
|
||||
suppressed_paths = [s["reference"]["path"] for s in report["suppressed"]]
|
||||
self.assertEqual(
|
||||
suppressed_paths,
|
||||
["community/knowledge/finance/vat-on-prepayment.md"],
|
||||
)
|
||||
self.assertEqual(report["suppressed"][0]["reason"], "layer-precedence")
|
||||
|
||||
def test_layer_precedence_custom_wins_over_microsoft(self):
|
||||
_write(self.root, "microsoft", "finance", "vat-on-prepayment")
|
||||
_write(self.root, "custom", "finance", "vat-on-prepayment")
|
||||
|
||||
report = run_bc_domain_context(self.root, {
|
||||
"application-area": ["finance"],
|
||||
"technologies": ["al"],
|
||||
"bc-version": 28,
|
||||
"countries": ["w1"],
|
||||
})
|
||||
|
||||
paths = [f["id"] for f in report["findings"]]
|
||||
self.assertEqual(
|
||||
paths, ["custom/knowledge/finance/vat-on-prepayment.md"]
|
||||
)
|
||||
|
||||
# --- Conditional applicability (unknown dimensions) ---
|
||||
|
||||
def test_unknown_bc_version_caps_confidence_at_medium(self):
|
||||
_write(self.root, "microsoft", "finance", "chart-of-accounts")
|
||||
_write(self.root, "microsoft", "finance", "dimensions")
|
||||
|
||||
# bc-version omitted from task-context.
|
||||
report = run_bc_domain_context(self.root, {
|
||||
"application-area": ["finance"],
|
||||
"technologies": ["al"],
|
||||
"countries": ["w1"],
|
||||
})
|
||||
|
||||
self.assertTrue(report["findings"])
|
||||
for finding in report["findings"]:
|
||||
self.assertEqual(finding["confidence"], "medium")
|
||||
self.assertIn("bc-version", finding["message"])
|
||||
|
||||
# --- Goal-directed narrowing ---
|
||||
|
||||
def test_goal_tokens_narrow_worklist(self):
|
||||
_write(
|
||||
self.root,
|
||||
"microsoft",
|
||||
"finance",
|
||||
"vat-on-prepayment-chains",
|
||||
keywords="[vat, prepayment, credit-memo]",
|
||||
)
|
||||
_write(
|
||||
self.root,
|
||||
"microsoft",
|
||||
"finance",
|
||||
"dimensions",
|
||||
keywords="[dimensions, default-priority]",
|
||||
)
|
||||
_write(
|
||||
self.root,
|
||||
"microsoft",
|
||||
"finance",
|
||||
"chart-of-accounts",
|
||||
keywords="[chart, account]",
|
||||
)
|
||||
|
||||
report = run_bc_domain_context(self.root, {
|
||||
"goal": "bc-domain-context for finance — VAT wrong on prepayment credit memo",
|
||||
"application-area": ["finance"],
|
||||
"technologies": ["al"],
|
||||
"bc-version": 28,
|
||||
"countries": ["w1"],
|
||||
})
|
||||
|
||||
paths = [f["id"] for f in report["findings"]]
|
||||
self.assertIn(
|
||||
"microsoft/knowledge/finance/vat-on-prepayment-chains.md",
|
||||
paths,
|
||||
)
|
||||
# The highest-scoring file should come first.
|
||||
self.assertEqual(
|
||||
paths[0],
|
||||
"microsoft/knowledge/finance/vat-on-prepayment-chains.md",
|
||||
)
|
||||
|
||||
def test_generic_goal_keeps_full_area(self):
|
||||
_write(self.root, "microsoft", "finance", "chart-of-accounts")
|
||||
_write(self.root, "microsoft", "finance", "dimensions")
|
||||
|
||||
report = run_bc_domain_context(self.root, {
|
||||
"goal": "bc-domain-context for finance",
|
||||
"application-area": ["finance"],
|
||||
"technologies": ["al"],
|
||||
"bc-version": 28,
|
||||
"countries": ["w1"],
|
||||
})
|
||||
|
||||
self.assertEqual(len(report["findings"]), 2)
|
||||
|
||||
# --- Layer disabling ---
|
||||
|
||||
def test_disabled_layer_is_invisible(self):
|
||||
_write(self.root, "community", "finance", "only-in-community")
|
||||
_write(self.root, "microsoft", "finance", "only-in-microsoft")
|
||||
|
||||
report = run_bc_domain_context(self.root, {
|
||||
"application-area": ["finance"],
|
||||
"technologies": ["al"],
|
||||
"bc-version": 28,
|
||||
"countries": ["w1"],
|
||||
"enabled-layers": ["microsoft"],
|
||||
})
|
||||
|
||||
paths = [f["id"] for f in report["findings"]]
|
||||
self.assertEqual(paths, ["microsoft/knowledge/finance/only-in-microsoft.md"])
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
Loading…
Add table
Add a link
Reference in a new issue