From 8ad4899d75940dbe270b9d0e8058ee58088c0006 Mon Sep 17 00:00:00 2001 From: Malcolm Nixon Date: Tue, 5 May 2026 15:49:23 -0400 Subject: [PATCH] Move category files into correct locations and update references. --- .github/standards/design-documentation.md | 66 ++++++++++------ .github/standards/reqstream-usage.md | 31 ++++---- .github/standards/reviewmark-usage.md | 48 +++++++++--- .github/standards/software-items.md | 8 ++ .github/standards/technical-documentation.md | 17 ++++ .../standards/verification-documentation.md | 62 +++++++++------ .reviewmark.yaml | 45 ++++++----- AGENTS.md | 6 +- docs/design/definition.yaml | 12 +-- docs/design/{file-assert => }/file-assert.md | 0 docs/design/file-assert/{cli => }/cli.md | 12 +-- docs/design/file-assert/cli/context.md | 16 ++-- .../{configuration => }/configuration.md | 14 ++-- .../configuration/file-assert-config.md | 20 ++--- .../configuration/file-assert-data.md | 24 +++--- .../file-assert/{modeling => }/modeling.md | 14 ++-- .../file-assert/modeling/file-assert-file.md | 20 ++--- .../modeling/file-assert-html-assert.md | 22 +++--- .../modeling/file-assert-json-assert.md | 22 +++--- .../modeling/file-assert-pdf-assert.md | 42 +++++----- .../file-assert/modeling/file-assert-rule.md | 32 ++++---- .../file-assert/modeling/file-assert-test.md | 18 ++--- .../modeling/file-assert-text-assert.md | 18 ++--- .../modeling/file-assert-xml-assert.md | 22 +++--- .../modeling/file-assert-yaml-assert.md | 22 +++--- docs/design/file-assert/ots-dependencies.md | 20 ++--- docs/design/file-assert/program.md | 18 ++--- .../file-assert/{selftest => }/selftest.md | 12 +-- .../design/file-assert/selftest/validation.md | 18 ++--- .../file-assert/{utilities => }/utilities.md | 12 +-- .../file-assert/utilities/path-helpers.md | 10 +-- docs/design/introduction.md | 17 ++++ .../{file-assert => }/file-assert.yaml | 0 docs/reqstream/file-assert/{cli => }/cli.yaml | 0 .../{configuration => }/configuration.yaml | 0 .../file-assert/{modeling => }/modeling.yaml | 0 .../file-assert/{selftest => }/selftest.yaml | 0 .../{utilities => }/utilities.yaml | 0 docs/verification/definition.yaml | 20 ++--- .../{file-assert => }/file-assert.md | 0 .../verification/file-assert/{cli => }/cli.md | 22 +++--- docs/verification/file-assert/cli/context.md | 78 +++++++++---------- .../{configuration => }/configuration.md | 16 ++-- .../configuration/file-assert-config.md | 28 +++---- .../configuration/file-assert-data.md | 10 +-- .../file-assert/{modeling => }/modeling.md | 18 ++--- .../file-assert/modeling/file-assert-file.md | 40 +++++----- .../modeling/file-assert-html-assert.md | 32 ++++---- .../modeling/file-assert-json-assert.md | 36 ++++----- .../modeling/file-assert-pdf-assert.md | 38 ++++----- .../file-assert/modeling/file-assert-rule.md | 38 ++++----- .../file-assert/modeling/file-assert-test.md | 36 ++++----- .../modeling/file-assert-text-assert.md | 22 +++--- .../modeling/file-assert-xml-assert.md | 32 ++++---- .../modeling/file-assert-yaml-assert.md | 36 ++++----- docs/verification/file-assert/program.md | 20 ++--- .../file-assert/{selftest => }/selftest.md | 16 ++-- .../file-assert/selftest/validation.md | 30 +++---- .../file-assert/{utilities => }/utilities.md | 12 +-- .../file-assert/utilities/path-helpers.md | 30 +++---- docs/verification/introduction.md | 14 ++-- docs/verification/ots.md | 40 ++++++++++ docs/verification/ots/buildmark.md | 12 +-- docs/verification/ots/fileassert.md | 14 ++-- docs/verification/ots/pandoc.md | 24 +++--- docs/verification/ots/reqstream.md | 12 +-- docs/verification/ots/reviewmark.md | 14 ++-- docs/verification/ots/sarifmark.md | 14 ++-- docs/verification/ots/sonarmark.md | 18 ++--- docs/verification/ots/versionmark.md | 14 ++-- docs/verification/ots/weasyprint.md | 24 +++--- docs/verification/ots/xunit.md | 26 +++---- requirements.yaml | 12 +-- 73 files changed, 856 insertions(+), 712 deletions(-) rename docs/design/{file-assert => }/file-assert.md (100%) rename docs/design/file-assert/{cli => }/cli.md (93%) rename docs/design/file-assert/{configuration => }/configuration.md (92%) rename docs/design/file-assert/{modeling => }/modeling.md (96%) rename docs/design/file-assert/{selftest => }/selftest.md (92%) rename docs/design/file-assert/{utilities => }/utilities.md (89%) rename docs/reqstream/{file-assert => }/file-assert.yaml (100%) rename docs/reqstream/file-assert/{cli => }/cli.yaml (100%) rename docs/reqstream/file-assert/{configuration => }/configuration.yaml (100%) rename docs/reqstream/file-assert/{modeling => }/modeling.yaml (100%) rename docs/reqstream/file-assert/{selftest => }/selftest.yaml (100%) rename docs/reqstream/file-assert/{utilities => }/utilities.yaml (100%) rename docs/verification/{file-assert => }/file-assert.md (100%) rename docs/verification/file-assert/{cli => }/cli.md (84%) rename docs/verification/file-assert/{configuration => }/configuration.md (84%) rename docs/verification/file-assert/{modeling => }/modeling.md (83%) rename docs/verification/file-assert/{selftest => }/selftest.md (83%) rename docs/verification/file-assert/{utilities => }/utilities.md (83%) create mode 100644 docs/verification/ots.md diff --git a/.github/standards/design-documentation.md b/.github/standards/design-documentation.md index 3b448f3..768bf3f 100644 --- a/.github/standards/design-documentation.md +++ b/.github/standards/design-documentation.md @@ -35,16 +35,21 @@ design to implementation: ```text docs/design/ -├── introduction.md # Design overview with software structure -└── {system-name}/ # System-level design folder (one per system) - ├── {system-name}.md # System-level design documentation - ├── {subsystem-name}/ # Subsystem (kebab-case); may nest recursively - │ ├── {subsystem-name}.md # Subsystem overview and design - │ ├── {child-subsystem}/ # Child subsystem (same structure as parent) - │ └── {unit-name}.md # Unit-level design documents - └── {unit-name}.md # Top-level unit design documents (if not in subsystem) +├── introduction.md # Document overview - heading depth # +├── {system-name}.md # System-level design - heading depth # +└── {system-name}/ # System folder (one per system) + ├── {subsystem-name}.md # Subsystem overview - heading depth ## + ├── {subsystem-name}/ # Subsystem folder (kebab-case); may nest recursively + │ ├── {child-subsystem}.md # Child subsystem overview - heading depth ### + │ ├── {child-subsystem}/ # Child subsystem folder (same structure as parent) + │ └── {unit-name}.md # Unit design - heading depth ### + └── {unit-name}.md # System-level unit design - heading depth ## ``` +Each scope's overview file lives in its **parent** folder, not inside the scope's own +subfolder - this aligns heading depth with folder depth so the compiled PDF has a +meaningful multi-level outline (see Heading Depth Rule in `technical-documentation.md`). + ## introduction.md (MANDATORY) The `introduction.md` file serves as the design entry point and MUST include @@ -124,23 +129,30 @@ artifact to all related files: Example format: ```text -Each software item in the structure above has corresponding artifacts in -parallel directory trees: - -- Requirements: `docs/reqstream/{system}/.../{item}.yaml` (kebab-case) -- Design docs: `docs/design/{system}/.../{item}.md` (kebab-case) -- Verification design: `docs/verification/{system}/.../{item}.md` (kebab-case) -- Source code: `src/{System}/.../{Item}.{ext}` (cased per language - see `software-items.md`) -- Tests: `test/{System}.Tests/.../{Item}Tests.{ext}` (cased per language - see `software-items.md`) -- Review-sets: defined in `.reviewmark.yaml` +Each in-house software item has corresponding artifacts in parallel directory trees: + +- Requirements: `docs/reqstream/{system-name}.yaml`, `docs/reqstream/{system-name}/.../{item}.yaml` +- Design docs: `docs/design/{system-name}.md`, `docs/design/{system-name}/.../{item}.md` +- Verification: `docs/verification/{system-name}.md`, `docs/verification/{system-name}/.../{item}.md` +- Source code: `src/{SystemName}/.../{Item}.{ext}` (cased per language - see `software-items.md`) +- Tests: `test/{SystemName}.Tests/.../{Item}Tests.{ext}` (cased per language) + +OTS items have no design documentation; their artifacts sit parallel to system folders: + +- Requirements: `docs/reqstream/ots/{ots-name}.yaml` +- Verification: `docs/verification/ots/{ots-name}.md` +- Tests (optional): `test/{OtsSoftwareTests}/...` (cased per language - see `software-items.md`) + +Review-sets: defined in `.reviewmark.yaml` ``` ## System Design Documentation (MANDATORY) For each system identified in the repository: -- Create a kebab-case folder matching the system name -- Include `{system-name}.md` with system-level design documentation such as: +- Create `{system-name}.md` directly under `docs/design/` (heading depth `#`) +- Create a kebab-case folder `{system-name}/` to hold its subsystems and units +- `{system-name}.md` must cover: - System architecture and major components - External interfaces and dependencies - Data flow and control flow @@ -151,16 +163,20 @@ For each system identified in the repository: For each subsystem identified in the software structure: -- Create a kebab-case folder matching the subsystem name (enables automated tooling) -- Include `{subsystem-name}.md` with subsystem overview and design -- Include unit design documents for ALL units within the subsystem +- Place `{subsystem-name}.md` inside the **parent** folder (the system folder, or parent + subsystem folder) - not inside its own subfolder +- Create a kebab-case folder `{subsystem-name}/` to hold its child units and subsystems +- `{subsystem-name}.md` must cover subsystem overview and design For every unit identified in the software structure: +- Place `{unit-name}.md` inside its parent scope's folder (system or subsystem folder) - Document data models, algorithms, and key methods - Describe interactions with other units - Include sufficient detail for formal code review -- Place in appropriate subsystem folder or at design root level + +Follow the Heading Depth Rule from `technical-documentation.md` - a file's top-level +heading depth equals its folder depth under `docs/design/`. # Software Items Integration (CRITICAL) @@ -191,9 +207,11 @@ Before submitting design documentation, verify: - [ ] `introduction.md` includes both Software Structure and Folder Layout sections - [ ] Software structure correctly categorizes items as System/Subsystem/Unit per `software-items.md` - [ ] Folder layout mirrors software structure organization +- [ ] Files organized under `docs/design/` following the folder structure pattern above +- [ ] Each file's top-level heading depth matches its folder depth per the Heading Depth Rule - [ ] Design documents provide sufficient detail for code review - [ ] System documentation provides comprehensive system-level design -- [ ] Subsystem documentation folders use kebab-case names while mirroring source subsystem names and structure +- [ ] All documentation folders use kebab-case names mirroring source code structure - [ ] All documents follow technical documentation formatting standards - [ ] Content is current with implementation and requirements - [ ] Documents are integrated into ReviewMark review-sets for formal review diff --git a/.github/standards/reqstream-usage.md b/.github/standards/reqstream-usage.md index 58b08b4..303bb43 100644 --- a/.github/standards/reqstream-usage.md +++ b/.github/standards/reqstream-usage.md @@ -18,20 +18,25 @@ because ReqStream discovers files via the includes chain in `requirements.yaml` and organizes report output by this hierarchy: ```text -requirements.yaml # Root file (includes only) +requirements.yaml # Root file (includes only) docs/reqstream/ -├── {system-name}/ # System-level requirements folder (one per system) -│ ├── {system-name}.yaml # System-level requirements +├── {system-name}.yaml # System-level requirements +├── {system-name}/ # System folder (one per system) │ ├── platform-requirements.yaml # Platform support requirements -│ ├── {subsystem-name}/ # Subsystem (kebab-case); may nest recursively -│ │ ├── {subsystem-name}.yaml # Requirements for this subsystem -│ │ ├── {child-subsystem}/ # Child subsystem (same structure as parent) -│ │ └── {unit-name}.yaml # Requirements for units within this subsystem -│ └── {unit-name}.yaml # Requirements for top-level units (outside subsystems) -└── ots/ # OTS items appear as a distinct section in reports - └── {ots-name}.yaml # Requirements for OTS components +│ ├── {subsystem-name}.yaml # Subsystem requirements +│ ├── {subsystem-name}/ # Subsystem folder (kebab-case); may nest recursively +│ │ ├── {child-subsystem}.yaml # Child subsystem requirements +│ │ ├── {child-subsystem}/ # Child subsystem folder +│ │ └── {unit-name}.yaml # Unit requirements +│ └── {unit-name}.yaml # System-level unit requirements +└── ots/ # OTS items appear as a distinct section in reports + └── {ots-name}.yaml # Requirements for OTS components ``` +In-house items have matching relative paths across `docs/reqstream/`, `docs/design/`, and +`docs/verification/`. OTS items appear only in `docs/reqstream/ots/` and +`docs/verification/ots/` - they have no design documentation. + # Requirements File Format ```yaml @@ -62,7 +67,7 @@ sections: sections: - title: System.Text.Json requirements: - - id: TemplateTool-SystemTextJson-ReadJson + - id: SystemTextJson-Core-ReadJson title: System.Text.Json shall be able to read JSON files. tests: - JsonReaderTests.TestReadValidJson @@ -124,8 +129,8 @@ Before submitting requirements, verify: - [ ] Every requirement links to at least one passing test - [ ] Platform-specific requirements use source filters (`platform@TestName`) - [ ] Comprehensive justification explains business/regulatory need -- [ ] Files organized under `docs/reqstream/` following folder structure patterns -- [ ] Subsystem folders use kebab-case naming matching source code +- [ ] Files organized under `docs/reqstream/` following the folder structure pattern above +- [ ] All documentation folders use kebab-case names matching source code structure - [ ] OTS requirements placed in `ots/` subfolder - [ ] Valid YAML syntax passes yamllint validation - [ ] Test result formats compatible (TRX, JUnit XML) diff --git a/.github/standards/reviewmark-usage.md b/.github/standards/reviewmark-usage.md index 2f778dc..2d95832 100644 --- a/.github/standards/reviewmark-usage.md +++ b/.github/standards/reviewmark-usage.md @@ -61,6 +61,17 @@ needs-review: # Source of review evidence evidence-source: type: none + +# Review-sets (each focuses on a single compliance question) +reviews: + - id: Purpose + title: Review of user-facing capabilities and system promises + paths: + - "README.md" + - "docs/user_guide/**/*.md" + - "docs/reqstream/{system-name}.yaml" + - "docs/design/introduction.md" + - "docs/design/{system-name}.md" ``` # Review-Set Design Principles @@ -95,9 +106,9 @@ Reviews user-facing capabilities and system promises: - **File Path Patterns**: - README: `README.md` - User guide: `docs/user_guide/**/*.md` - - System requirements: `docs/reqstream/{system-name}/{system-name}.yaml` + - System requirements: `docs/reqstream/{system-name}.yaml` - Design introduction: `docs/design/introduction.md` - - System design: `docs/design/{system-name}/{system-name}.md` + - System design: `docs/design/{system-name}.md` ## `{System}-Architecture` Review (one per system) @@ -108,11 +119,11 @@ Reviews system architecture and operational validation: - **Scope**: Excludes subsystem and unit files, relying on system-level design to describe what subsystems and units it uses - **File Path Patterns**: - - System requirements: `docs/reqstream/{system-name}/{system-name}.yaml` + - System requirements: `docs/reqstream/{system-name}.yaml` - Design introduction: `docs/design/introduction.md` - - System design: `docs/design/{system-name}/{system-name}.md` + - System design: `docs/design/{system-name}.md` - Verification introduction: `docs/verification/introduction.md` - - System verification design: `docs/verification/{system-name}/{system-name}.md` + - System verification design: `docs/verification/{system-name}.md` - System integration tests: `test/{SystemName}.Tests/{SystemName}Tests.{ext}` ## `{System}-Design` Review (one per system) @@ -123,9 +134,10 @@ Reviews architectural and design consistency: - **Title**: "Review that {System} Design is Consistent and Complete" - **Scope**: Only brings in top-level requirements and relies on brevity of design documentation - **File Path Patterns**: - - System requirements: `docs/reqstream/{system-name}/{system-name}.yaml` + - System requirements: `docs/reqstream/{system-name}.yaml` - Platform requirements: `docs/reqstream/{system-name}/platform-requirements.yaml` - Design introduction: `docs/design/introduction.md` + - System design: `docs/design/{system-name}.md` - System design files: `docs/design/{system-name}/**/*.md` ## `{System}-AllRequirements` Review (one per system) @@ -137,8 +149,8 @@ Reviews requirements quality and traceability: - **Scope**: Only brings in requirements files to keep review manageable - **File Path Patterns**: - Root requirements: `requirements.yaml` - - System requirements: `docs/reqstream/{system-name}/**/*.yaml` - - OTS requirements: `docs/reqstream/ots/**/*.yaml` (if applicable) + - System requirements: `docs/reqstream/{system-name}.yaml` + - Subsystem/unit requirements: `docs/reqstream/{system-name}/**/*.yaml` ## `{System}-{Subsystem[-Child...]}` Review (one per subsystem at any depth) @@ -149,9 +161,9 @@ Reviews subsystem architecture and interfaces: - **Scope**: Excludes units under the subsystem, relying on subsystem design to describe what units it uses - **File Path Patterns**: - - Requirements: `docs/reqstream/{system-name}/.../{subsystem-name}/{subsystem-name}.yaml` - - Design: `docs/design/{system-name}/.../{subsystem-name}/{subsystem-name}.md` - - Verification design: `docs/verification/{system-name}/.../{subsystem-name}/{subsystem-name}.md` + - Requirements: `docs/reqstream/{system-name}/.../{subsystem-name}.yaml` + - Design: `docs/design/{system-name}/.../{subsystem-name}.md` + - Verification design: `docs/verification/{system-name}/.../{subsystem-name}.md` - Tests: `test/{SystemName}.Tests/.../{SubsystemName}/{SubsystemName}Tests.{ext}` ## `{System}-{Subsystem[-Child...]}-{Unit}` Review (one per unit) @@ -168,6 +180,19 @@ Reviews individual software unit implementation: - Source: `src/{SystemName}/.../{UnitName}.{ext}` - Tests: `test/{SystemName}.Tests/.../{UnitName}Tests.{ext}` +## `OTS-{OtsName}` Review (one per OTS item) + +Reviews OTS item requirements and verification evidence: + +- **Purpose**: Proves that the OTS item provides the required functionality +- **Title**: "Review that {OtsName} Provides Required Functionality" +- **Scope**: OTS items have no in-house design or source; review covers requirements and + verification evidence only +- **File Path Patterns**: + - OTS requirements: `docs/reqstream/ots/{ots-name}.yaml` + - OTS verification: `docs/verification/ots/{ots-name}.md` + - Tests (if applicable): `test/{OtsSoftwareTests}/...` (cased per language) + **Note**: File path patterns use `{ext}` as a placeholder for language-specific extensions (`.cs`, `.cpp`/`.hpp`, `.py`, etc.). Adapt to your repository's languages. @@ -184,6 +209,7 @@ Before submitting ReviewMark configuration, verify: - [ ] Architecture review-sets include system verification design alongside system design - [ ] Subsystem review-sets include subsystem verification design - [ ] Unit review-sets include unit verification design +- [ ] OTS review-sets include OTS requirements and verification evidence - [ ] Each review-set focuses on a single compliance question (single focus principle) - [ ] File patterns use correct glob syntax and match intended files - [ ] Review-set file counts remain manageable (context management principle) diff --git a/.github/standards/software-items.md b/.github/standards/software-items.md index 4e5c90e..6be029f 100644 --- a/.github/standards/software-items.md +++ b/.github/standards/software-items.md @@ -81,6 +81,14 @@ Choose the appropriate category based on scope and testability: consumes it - Tested through integration tests proving required functionality works - Examples: System.Text.Json, Entity Framework, third-party APIs +- **Artifact locations** (OTS items have no design documentation): + - Requirements: `docs/reqstream/ots/{ots-name}.yaml` + - Verification: `docs/verification/ots/{ots-name}.md` + - These folders sit parallel to system folders (not inside any system folder) +- System design documentation records which OTS items each system depends on +- **OTS test project**: If no other verification evidence is available (e.g., vendor test results, + published compliance reports), a dedicated test project (`OtsSoftwareTests` / `ots_software_tests`, + cased per language) holds OTS integration tests - one test file per OTS item requiring tests. # Software Item Artifact Model diff --git a/.github/standards/technical-documentation.md b/.github/standards/technical-documentation.md index 7ff5b5a..2ac29f4 100644 --- a/.github/standards/technical-documentation.md +++ b/.github/standards/technical-documentation.md @@ -84,6 +84,23 @@ elsewhere causes duplicate sections in the compiled PDF. List documents in logical reading order in Pandoc configuration because readers need coherent information flow from general to specific topics. +## Heading Depth Rule (MANDATORY) + +A file's top-level heading depth must equal its folder depth under the document +collection root - this ensures Pandoc can concatenate all files in `definition.yaml` +order and produce a coherent outline with no heading-shift configuration: + +| Folder depth | Top heading | +| --- | --- | +| 0 - collection root | `#` | +| 1 - one subfolder deep | `##` | +| 2 - two subfolders deep | `###` | +| N - N subfolders deep | `#` × (N+1) | + +Internal sections use the next heading level down (e.g. a `##` file uses `###` +for *Overview*, *Interfaces*, etc.). Deeply nested files have fewer heading levels +available - keep internal structure flat to avoid excessive nesting. + # Writing Guidelines Write technical documentation for clarity and compliance verification: diff --git a/.github/standards/verification-documentation.md b/.github/standards/verification-documentation.md index f6f407f..8eea3b7 100644 --- a/.github/standards/verification-documentation.md +++ b/.github/standards/verification-documentation.md @@ -23,18 +23,25 @@ Organize under `docs/verification/` mirroring the software item hierarchy: ```text docs/verification/ -├── introduction.md # Verification overview -├── {system-name}/ # System-level verification folder (one per system) -│ ├── {system-name}.md # System-level verification design -│ ├── {subsystem-name}/ # Subsystem (kebab-case); may nest recursively -│ │ ├── {subsystem-name}.md # Subsystem verification design -│ │ ├── {child-subsystem}/ # Child subsystem (same structure as parent) -│ │ └── {unit-name}.md # Unit-level verification design documents -│ └── {unit-name}.md # Top-level unit verification documents (if not in subsystem) -└── ots/ # OTS items (one verification file per OTS item) - └── {ots-name}.md # Verification evidence for each OTS item +├── introduction.md # Document overview - heading depth # +├── {system-name}.md # System-level verification - heading depth # +├── {system-name}/ # System folder (one per system) +│ ├── {subsystem-name}.md # Subsystem verification - heading depth ## +│ ├── {subsystem-name}/ # Subsystem folder (kebab-case); may nest recursively +│ │ ├── {child-subsystem}.md # Child subsystem verification - heading depth ### +│ │ ├── {child-subsystem}/ # Child subsystem folder (same structure as parent) +│ │ └── {unit-name}.md # Unit verification - heading depth ### +│ └── {unit-name}.md # System-level unit verification - heading depth ## +├── ots.md # OTS section overview - heading depth # (MANDATORY if OTS items exist) +└── ots/ # OTS items - parallel to system folders (not inside them) + └── {ots-name}.md # OTS item verification evidence - heading depth ## ``` +Each scope's overview file lives in its **parent** folder, not inside the scope's own +subfolder - this keeps artifact locations consistent with design and requirements trees +so any item's files are deterministically locatable, and aligns heading depth with folder +depth for correct PDF structure (see Heading Depth Rule in `technical-documentation.md`). + ## introduction.md (MANDATORY) Follow the standard `introduction.md` format from `technical-documentation.md`. Scope @@ -45,16 +52,16 @@ artifact to all related files: ```text In-house items have parallel artifacts in: -- Requirements: `docs/reqstream/{system}/.../{item}.yaml` (kebab-case) -- Design: `docs/design/{system}/.../{item}.md` (kebab-case) -- Verification: `docs/verification/{system}/.../{item}.md` (kebab-case) -- Source: `src/{System}/.../{Item}.{ext}` (cased per language) -- Tests: `test/{System}.Tests/.../{Item}Tests.{ext}` (cased per language) +- Requirements: `docs/reqstream/{system-name}.yaml`, `docs/reqstream/{system-name}/.../{item}.yaml` +- Design: `docs/design/{system-name}.md`, `docs/design/{system-name}/.../{item}.md` +- Verification: `docs/verification/{system-name}.md`, `docs/verification/{system-name}/.../{item}.md` +- Source: `src/{SystemName}/.../{Item}.{ext}` (cased per language) +- Tests: `test/{SystemName}.Tests/.../{Item}Tests.{ext}` (cased per language) -OTS items have parallel artifacts in: -- Requirements: `docs/reqstream/ots/{ots-name}.yaml` (kebab-case) -- Verification: `docs/verification/ots/{ots-name}.md` (kebab-case) -- Tests: `test/{OtsName}.Tests/...` (cased per language, if required) +OTS items (no design documentation) have artifacts parallel to system folders: +- Requirements: `docs/reqstream/ots/{ots-name}.yaml` +- Verification: `docs/verification/ots/{ots-name}.md` +- Tests (if required): `test/{OtsSoftwareTests}/...` (cased per language - see `software-items.md`) Review-sets: defined in `.reviewmark.yaml` ``` @@ -64,7 +71,8 @@ a `## References` section in `introduction.md` only - do not add one to any othe ## System Verification Design (MANDATORY) -For each system, create a kebab-case folder and `{system-name}.md` covering: +For each system, create `{system-name}.md` at `docs/verification/` root and a +`{system-name}/` folder for subsystems. Cover: - System verification strategy and overall test approach - Test environments and configuration required @@ -75,7 +83,8 @@ For each system, create a kebab-case folder and `{system-name}.md` covering: ## Subsystem Verification Design (MANDATORY) -For each subsystem, create a kebab-case folder and `{subsystem-name}.md` covering: +For each subsystem, place `{subsystem-name}.md` in the parent (system or subsystem) +folder and create a `{subsystem-name}/` folder for its units. Cover: - Subsystem verification strategy and integration test approach - Dependencies that must be mocked or stubbed at the subsystem boundary @@ -84,7 +93,7 @@ For each subsystem, create a kebab-case folder and `{subsystem-name}.md` coverin ## Unit Verification Design (MANDATORY) -For each unit, create `{unit-name}.md` covering: +Place `{unit-name}.md` in the parent (system or subsystem) folder. Cover: - Verification approach for each unit requirement - Named test scenarios including boundary conditions, error paths, and normal-operation cases @@ -93,6 +102,10 @@ For each unit, create `{unit-name}.md` covering: ## OTS Verification Evidence (when OTS items are used) +Create `docs/verification/ots.md` at the collection root with a `#` top-level heading. This +file introduces the OTS verification approach and ensures OTS items compile as a top-level +section in the PDF rather than as subsystems of the last in-house system. + For each OTS item, create `docs/verification/ots/{ots-name}.md` covering: - The OTS item's required functionality (reference `docs/reqstream/ots/{ots-name}.yaml`) @@ -121,8 +134,11 @@ Before submitting verification documentation, verify: - [ ] System verification documents cover end-to-end and integration scenarios - [ ] Subsystem verification documents identify mocked boundaries and integration scenarios - [ ] Unit verification documents identify individual scenarios including boundary and error paths -- [ ] Subsystem documentation folders use kebab-case names mirroring the source subsystem structure +- [ ] Files organized under `docs/verification/` following the folder structure pattern above +- [ ] Each file's top-level heading depth matches its folder depth per the Heading Depth Rule +- [ ] All documentation folders use kebab-case names mirroring source code structure - [ ] All documents follow technical documentation formatting standards - [ ] Content is current with requirements and test implementation - [ ] Every OTS item has `docs/verification/ots/{ots-name}.md` with requirement coverage +- [ ] `docs/verification/ots.md` exists with a `#` heading when OTS items are present - [ ] Documents are integrated into ReviewMark review-sets for formal review diff --git a/.reviewmark.yaml b/.reviewmark.yaml index 43e5206..e08e87c 100644 --- a/.reviewmark.yaml +++ b/.reviewmark.yaml @@ -32,18 +32,18 @@ reviews: paths: - "README.md" # project readme - "docs/user_guide/**/*.md" # user guide - - "docs/reqstream/file-assert/file-assert.yaml" # system requirements + - "docs/reqstream/file-assert.yaml" # system requirements - "docs/design/introduction.md" # design introduction - - "docs/design/file-assert/file-assert.md" # system design + - "docs/design/file-assert.md" # system design # FileAssert-Architecture Review (one per system) - id: FileAssert-Architecture title: Review that FileAssert Architecture Satisfies Requirements paths: - - "docs/reqstream/file-assert/file-assert.yaml" # system requirements + - "docs/reqstream/file-assert.yaml" # system requirements - "docs/design/introduction.md" # design introduction - - "docs/design/file-assert/file-assert.md" # system design - - "docs/verification/file-assert/file-assert.md" # system verification + - "docs/design/file-assert.md" # system design + - "docs/verification/file-assert.md" # system verification - "test/**/IntegrationTests.cs" # integration tests - "test/**/AssemblyInfo.cs" # test infrastructure - "test/**/Runner.cs" # test infrastructure @@ -52,12 +52,15 @@ reviews: - id: FileAssert-Design title: Review that FileAssert Design is Consistent and Complete paths: - - "docs/reqstream/file-assert/file-assert.yaml" # system requirements + - "docs/reqstream/file-assert.yaml" # system requirements - "docs/reqstream/file-assert/platform-requirements.yaml" # platform requirements - "docs/design/introduction.md" # design introduction + - "docs/design/file-assert.md" # system design overview - "docs/design/file-assert/**/*.md" # all system design documents - "docs/verification/introduction.md" # verification introduction + - "docs/verification/file-assert.md" # system verification overview - "docs/verification/file-assert/**/*.md" # all verification documents + - "docs/verification/ots.md" # OTS verification overview # FileAssert-AllRequirements Review (one per system) - id: FileAssert-AllRequirements @@ -70,45 +73,45 @@ reviews: - id: FileAssert-Cli title: Review that FileAssert Cli Satisfies Subsystem Requirements paths: - - "docs/reqstream/file-assert/cli/cli.yaml" # subsystem requirements - - "docs/design/file-assert/cli/cli.md" # subsystem design - - "docs/verification/file-assert/cli/cli.md" # subsystem verification + - "docs/reqstream/file-assert/cli.yaml" # subsystem requirements + - "docs/design/file-assert/cli.md" # subsystem design + - "docs/verification/file-assert/cli.md" # subsystem verification - "test/**/Cli/CliTests.cs" # subsystem tests # FileAssert-Configuration Review (one per subsystem) - id: FileAssert-Configuration title: Review that FileAssert Configuration Satisfies Subsystem Requirements paths: - - "docs/reqstream/file-assert/configuration/configuration.yaml" # subsystem requirements - - "docs/design/file-assert/configuration/configuration.md" # subsystem design - - "docs/verification/file-assert/configuration/configuration.md" # subsystem verification + - "docs/reqstream/file-assert/configuration.yaml" # subsystem requirements + - "docs/design/file-assert/configuration.md" # subsystem design + - "docs/verification/file-assert/configuration.md" # subsystem verification - "test/**/Configuration/ConfigurationTests.cs" # subsystem tests # FileAssert-Modeling Review (one per subsystem) - id: FileAssert-Modeling title: Review that FileAssert Modeling Satisfies Subsystem Requirements paths: - - "docs/reqstream/file-assert/modeling/modeling.yaml" # subsystem requirements - - "docs/design/file-assert/modeling/modeling.md" # subsystem design - - "docs/verification/file-assert/modeling/modeling.md" # subsystem verification + - "docs/reqstream/file-assert/modeling.yaml" # subsystem requirements + - "docs/design/file-assert/modeling.md" # subsystem design + - "docs/verification/file-assert/modeling.md" # subsystem verification - "test/**/Modeling/ModelingTests.cs" # subsystem tests # FileAssert-Utilities Review (one per subsystem) - id: FileAssert-Utilities title: Review that FileAssert Utilities Satisfies Subsystem Requirements paths: - - "docs/reqstream/file-assert/utilities/utilities.yaml" # subsystem requirements - - "docs/design/file-assert/utilities/utilities.md" # subsystem design - - "docs/verification/file-assert/utilities/utilities.md" # subsystem verification + - "docs/reqstream/file-assert/utilities.yaml" # subsystem requirements + - "docs/design/file-assert/utilities.md" # subsystem design + - "docs/verification/file-assert/utilities.md" # subsystem verification - "test/**/Utilities/UtilitiesTests.cs" # subsystem tests # FileAssert-SelfTest Review (one per subsystem) - id: FileAssert-SelfTest title: Review that FileAssert SelfTest Satisfies Subsystem Requirements paths: - - "docs/reqstream/file-assert/selftest/selftest.yaml" # subsystem requirements - - "docs/design/file-assert/selftest/selftest.md" # subsystem design - - "docs/verification/file-assert/selftest/selftest.md" # subsystem verification + - "docs/reqstream/file-assert/selftest.yaml" # subsystem requirements + - "docs/design/file-assert/selftest.md" # subsystem design + - "docs/verification/file-assert/selftest.md" # subsystem verification - "test/**/SelfTest/SelfTestTests.cs" # subsystem tests # FileAssert-Cli-Context Review (one per unit) diff --git a/AGENTS.md b/AGENTS.md index f0f4b59..c83827c 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -100,7 +100,7 @@ Result semantics for orchestrator decision-making: # Formatting (After Making Changes) After making changes, run the auto-fix pass. This applies all available fixers -silently and **always exits 0** — agents do not need to respond to its output. +silently and **always exits 0** - agents do not need to respond to its output. ```pwsh pwsh ./fix.ps1 @@ -108,7 +108,7 @@ pwsh ./fix.ps1 This automatically handles: `dotnet format`, markdown formatting, and YAML formatting. Full lint compliance is a **pre-PR responsibility**, not an agent -responsibility — invoke the lint-fix agent once before submitting a pull request. +responsibility - invoke the lint-fix agent once before submitting a pull request. ## CI Quality Tools @@ -118,7 +118,7 @@ reqstream, versionmark, and reviewmark. # Scope Discipline (ALL Agents Must Follow) - **No generated file access**: Files inside any `generated/` folder are build - outputs — do not read, lint, or modify them + outputs - do not read, lint, or modify them - **Minimum necessary changes**: Only modify files directly required by the task - **No speculative refactoring**: Do not refactor code adjacent to the change unless the task explicitly requests it diff --git a/docs/design/definition.yaml b/docs/design/definition.yaml index bd1dff0..6510a04 100644 --- a/docs/design/definition.yaml +++ b/docs/design/definition.yaml @@ -5,14 +5,14 @@ resource-path: input-files: - docs/design/title.txt - docs/design/introduction.md - - docs/design/file-assert/file-assert.md + - docs/design/file-assert.md - docs/design/file-assert/program.md - - docs/design/file-assert/cli/cli.md + - docs/design/file-assert/cli.md - docs/design/file-assert/cli/context.md - - docs/design/file-assert/configuration/configuration.md + - docs/design/file-assert/configuration.md - docs/design/file-assert/configuration/file-assert-config.md - docs/design/file-assert/configuration/file-assert-data.md - - docs/design/file-assert/modeling/modeling.md + - docs/design/file-assert/modeling.md - docs/design/file-assert/modeling/file-assert-test.md - docs/design/file-assert/modeling/file-assert-file.md - docs/design/file-assert/modeling/file-assert-rule.md @@ -22,9 +22,9 @@ input-files: - docs/design/file-assert/modeling/file-assert-html-assert.md - docs/design/file-assert/modeling/file-assert-yaml-assert.md - docs/design/file-assert/modeling/file-assert-json-assert.md - - docs/design/file-assert/utilities/utilities.md + - docs/design/file-assert/utilities.md - docs/design/file-assert/utilities/path-helpers.md - - docs/design/file-assert/selftest/selftest.md + - docs/design/file-assert/selftest.md - docs/design/file-assert/selftest/validation.md - docs/design/file-assert/ots-dependencies.md template: template.html diff --git a/docs/design/file-assert/file-assert.md b/docs/design/file-assert.md similarity index 100% rename from docs/design/file-assert/file-assert.md rename to docs/design/file-assert.md diff --git a/docs/design/file-assert/cli/cli.md b/docs/design/file-assert/cli.md similarity index 93% rename from docs/design/file-assert/cli/cli.md rename to docs/design/file-assert/cli.md index 6ac78c6..bb99cc6 100644 --- a/docs/design/file-assert/cli/cli.md +++ b/docs/design/file-assert/cli.md @@ -1,18 +1,18 @@ -# Cli Subsystem Design +## Cli Subsystem Design -## Overview +### Overview The Cli subsystem is responsible for translating the raw command-line argument array into a structured, immutable context object that the rest of the tool uses for output, configuration, and execution decisions. -## Subsystem Contents +### Subsystem Contents | Unit | File | Responsibility | | :-------- | :------------ | :-------------------------------------------------------- | | `Context` | `Context.cs` | Parses arguments and owns all I/O operations. | -## Subsystem Responsibilities +### Subsystem Responsibilities - Parse all supported flags (`--version`/`-v`, `--help`/`-h`/`-?`, `--silent`, `--validate`, `--log`, `--results`/`--result`, `--config`, `--depth`) and positional filter arguments. @@ -21,7 +21,7 @@ and execution decisions. - Write output to stdout and the log file; write errors to stderr and the log file. - Expose an exit code that reflects whether any errors have been reported. -## Interactions with Other Subsystems +### Interactions with Other Subsystems | Consumer | Usage | | :---------------- | :------------------------------------------------------------------- | @@ -30,7 +30,7 @@ and execution decisions. | Modeling | Receives a `Context` to write error messages for assertion failures. | | SelfTest | Receives a `Context` to write validation results and errors. | -## Design Decisions +### Design Decisions - **Immutable context object**: Properties are set once via `private init` accessors, preventing accidental mutation after the context is created. diff --git a/docs/design/file-assert/cli/context.md b/docs/design/file-assert/cli/context.md index 407d6b0..ec5c417 100644 --- a/docs/design/file-assert/cli/context.md +++ b/docs/design/file-assert/cli/context.md @@ -1,14 +1,14 @@ -# Context Design +### Context Design -## Overview +#### Overview `Context` is the command-line argument parser and I/O owner for FileAssert. It translates the raw `string[]` argument array into named properties, manages the optional log file stream, and provides a unified interface for writing output and errors throughout the tool's execution. -## Class Structure +#### Class Structure -### Properties +##### Properties | Property | Type | Description | | :--------------------- | :---------------------- | :------------------------------------------------------------ | @@ -24,7 +24,7 @@ provides a unified interface for writing output and errors throughout the tool's | `ExitCode` | `int` | Returns `1` if any errors have been reported; otherwise `0`. | | `ErrorCount` | `int` | Monotonically increasing count of `WriteError` calls. | -### Factory Method +##### Factory Method ```csharp public static Context Create(string[] args) @@ -33,7 +33,7 @@ public static Context Create(string[] args) Delegates argument parsing to the private `ArgumentParser` nested class. Opens a log file if `--log` was specified. Returns the fully initialized `Context` instance. -### Output Methods +##### Output Methods ```csharp public void WriteLine(string message) @@ -44,7 +44,7 @@ public void WriteError(string message) `WriteError` sets the internal error flag, writes to stderr in red (unless silent), and writes to the log file. -### Argument Parsing +##### Argument Parsing The private nested class `ArgumentParser` processes each argument in order: @@ -55,7 +55,7 @@ The private nested class `ArgumentParser` processes each argument in order: - Unknown flag arguments (starting with `-`) throw `ArgumentException`. - All other arguments are accumulated in the `Filters` list. -## Design Decisions +#### Design Decisions - **Sealed with IDisposable**: The class is sealed to prevent inheritance of internal state, and implements `IDisposable` to ensure the log file stream is always closed. diff --git a/docs/design/file-assert/configuration/configuration.md b/docs/design/file-assert/configuration.md similarity index 92% rename from docs/design/file-assert/configuration/configuration.md rename to docs/design/file-assert/configuration.md index 9ee36cc..949df45 100644 --- a/docs/design/file-assert/configuration/configuration.md +++ b/docs/design/file-assert/configuration.md @@ -1,20 +1,20 @@ -# Configuration Subsystem Design +## Configuration Subsystem Design -## Overview +### Overview The Configuration subsystem is responsible for reading the YAML test-suite configuration file and constructing the domain object hierarchy that drives test execution. It owns the data transfer objects used during deserialization and the top-level configuration class that loads and runs the tests. -## Subsystem Contents +### Subsystem Contents | Unit | File | Responsibility | | :----------------- | :--------------------- | :---------------------------------------------------------- | | `FileAssertConfig` | `FileAssertConfig.cs` | Loads the YAML file and runs the filtered test suite. | | `FileAssertData` | `FileAssertData.cs` | Data transfer objects for YAML deserialization. | -## Subsystem Responsibilities +### Subsystem Responsibilities - Read and deserialize a YAML configuration file using YamlDotNet. - Tolerate unknown YAML properties for forward compatibility. @@ -23,7 +23,7 @@ and runs the tests. - Resolve the base directory for glob patterns from the configuration file path. - Filter tests by name or tag before execution. -## Interactions with Other Subsystems +### Interactions with Other Subsystems | Dependency | Usage | | :---------- | :-------------------------------------------------------------------------- | @@ -31,7 +31,7 @@ and runs the tests. | Modeling | Delegates test construction to `FileAssertTest.Create` and execution to | | | `FileAssertTest.Run`. | -## YAML Configuration Format +### YAML Configuration Format The top-level YAML structure is: @@ -47,7 +47,7 @@ tests: - contains: "Copyright" ``` -## Design Decisions +### Design Decisions - **Separation of data and domain objects**: The `FileAssertData` classes are pure data holders with no logic. The Modeling subsystem owns the domain objects built from them. diff --git a/docs/design/file-assert/configuration/file-assert-config.md b/docs/design/file-assert/configuration/file-assert-config.md index f45e930..3af15ca 100644 --- a/docs/design/file-assert/configuration/file-assert-config.md +++ b/docs/design/file-assert/configuration/file-assert-config.md @@ -1,21 +1,21 @@ -# FileAssertConfig Design +### FileAssertConfig Design -## Overview +#### Overview The `FileAssertConfig` class is the top-level entry point for the FileAssert tool's main execution path. It loads a YAML configuration file, builds the full hierarchy of tests, files, and rules, and drives test execution with optional name or tag filtering. -## Class Structure +#### Class Structure -### Properties +##### Properties | Property | Type | Description | | :------- | :------------------------------ | :--------------------------------------- | | `Tests` | `IReadOnlyList` | Tests defined in the configuration file. | -### Factory Method +##### Factory Method ```csharp internal static FileAssertConfig ReadFromFile(string path) @@ -35,7 +35,7 @@ The factory: 5. Stores the config file path internally so the base directory can be resolved at run time. -### Execution Method +##### Execution Method ```csharp internal void Run(Context context, IEnumerable filters) @@ -60,7 +60,7 @@ Execution proceeds as follows: 5. When results serialization is active, the results file is written in TRX format (`.trx` extension) or JUnit XML format (`.xml` extension) after all tests complete. -### Results Serialization +##### Results Serialization When `context.ResultsFile` is non-null, `Run` collects one `TestResult` per executed test (tests skipped by the filter are not recorded) and calls `WriteResultsFile` after @@ -68,7 +68,7 @@ the test loop. `WriteResultsFile` serializes using `TrxSerializer.Serialize` or `JUnitSerializer.Serialize` from `DemaConsulting.TestResults.IO`, selecting the format from the file extension. -## YAML Configuration Format +#### YAML Configuration Format The top-level YAML structure is: @@ -85,7 +85,7 @@ tests: - contains: "Copyright" ``` -## Integration with Program +#### Integration with Program `Program.RunToolLogic` loads the configuration from the path stored in `context.ConfigFile` (defaulting to `.fileassert.yaml`) and passes @@ -93,7 +93,7 @@ tests: the tool prints usage guidance rather than an error. When an explicitly specified file is absent, the tool reports an error and exits with a non-zero code. -## Design Decisions +#### Design Decisions - **Static factory with stored path**: Storing the configuration file path in the object avoids threading the path through every method signature while still diff --git a/docs/design/file-assert/configuration/file-assert-data.md b/docs/design/file-assert/configuration/file-assert-data.md index 8a342bc..a9b530e 100644 --- a/docs/design/file-assert/configuration/file-assert-data.md +++ b/docs/design/file-assert/configuration/file-assert-data.md @@ -1,15 +1,15 @@ -# FileAssertData Design +### FileAssertData Design -## Overview +#### Overview `FileAssertData` is the set of YAML data transfer objects (DTOs) used by YamlDotNet to deserialize the FileAssert configuration file. Each class maps directly to a YAML structure and is intentionally free of business logic. Domain objects are constructed from these DTOs by the Modeling subsystem. -## Class Structure +#### Class Structure -### FileAssertRuleData +##### FileAssertRuleData Represents a single content validation rule within a file assertion. @@ -22,7 +22,7 @@ Represents a single content validation rule within a file assertion. Exactly one property shall be set per rule. The `FileAssertRule.Create` factory enforces this. -### FileAssertFileData +##### FileAssertFileData Represents a file pattern assertion within a test. @@ -41,7 +41,7 @@ Represents a file pattern assertion within a test. | `Yaml` | `yaml` | `List?`| YAML node count assertions using dot-notation. | | `Json` | `json` | `List?`| JSON node count assertions using dot-notation. | -### FileAssertTestData +##### FileAssertTestData Represents a named test within the configuration. @@ -51,7 +51,7 @@ Represents a named test within the configuration. | `Tags` | `tags` | `List?` | Tags used for command-line filter selection. | | `Files` | `files` | `List?` | File assertions belonging to this test. | -### FileAssertConfigData +##### FileAssertConfigData Represents the top-level configuration document. @@ -59,7 +59,7 @@ Represents the top-level configuration document. | :------- | :--------- | :-------------------------- | :---------------------------------------- | | `Tests` | `tests` | `List?` | Tests defined in this configuration file. | -### FileAssertPdfMetadataRuleData +##### FileAssertPdfMetadataRuleData Represents a single PDF metadata field assertion. @@ -69,7 +69,7 @@ Represents a single PDF metadata field assertion. | `Contains` | `contains` | `string?` | Metadata value must contain this substring. | | `Matches` | `matches` | `string?` | Metadata value must match this regular expression. | -### FileAssertPdfPagesData +##### FileAssertPdfPagesData Represents PDF page count constraints. @@ -78,7 +78,7 @@ Represents PDF page count constraints. | `Min` | `min` | `int?` | Minimum number of pages. | | `Max` | `max` | `int?` | Maximum number of pages. | -### FileAssertPdfData +##### FileAssertPdfData Represents the `pdf:` assertion block for a file entry. @@ -88,7 +88,7 @@ Represents the `pdf:` assertion block for a file entry. | `Pages` | `pages` | `FileAssertPdfPagesData?` | Page count constraints. | | `Text` | `text` | `List?` | Body text assertions (contains/matches). | -### FileAssertQueryData +##### FileAssertQueryData Represents a single structured-document query assertion, shared by XML, HTML, YAML, and JSON assertion blocks. @@ -100,7 +100,7 @@ assertion blocks. | `Min` | `min` | `int?` | Minimum number of matched nodes. | | `Max` | `max` | `int?` | Maximum number of matched nodes. | -## Design Decisions +#### Design Decisions - **Nullable reference type properties**: All properties are nullable to correctly represent absent YAML keys without throwing during deserialization. diff --git a/docs/design/file-assert/modeling/modeling.md b/docs/design/file-assert/modeling.md similarity index 96% rename from docs/design/file-assert/modeling/modeling.md rename to docs/design/file-assert/modeling.md index 25c3efe..d79cde1 100644 --- a/docs/design/file-assert/modeling/modeling.md +++ b/docs/design/file-assert/modeling.md @@ -1,12 +1,12 @@ -# Modeling Subsystem Design +## Modeling Subsystem Design -## Overview +### Overview The Modeling subsystem contains the domain objects that represent a FileAssert test suite at runtime. It transforms the data transfer objects produced by the Configuration subsystem into executable domain objects and drives the assertion logic. -## Subsystem Contents +### Subsystem Contents | Unit | File | Responsibility | | :---------------------- | :-------------------------- | :----------------------------------------------------- | @@ -20,7 +20,7 @@ executable domain objects and drives the assertion logic. | `FileAssertYamlAssert` | `FileAssertYamlAssert.cs` | Parses YAML; applies dot-notation path assertions. | | `FileAssertJsonAssert` | `FileAssertJsonAssert.cs` | Parses JSON; applies dot-notation path assertions. | -## Subsystem Responsibilities +### Subsystem Responsibilities - Construct domain objects from Configuration DTOs via static factory methods. - Validate required fields (test name, file pattern, rule type) during construction. @@ -32,7 +32,7 @@ executable domain objects and drives the assertion logic. - Apply structured-document query assertions (XPath or dot-notation) to parsed document nodes. - Report assertion failures via the `Context` from the Cli subsystem. -## Object Hierarchy +### Object Hierarchy ```text FileAssertTest @@ -50,14 +50,14 @@ FileAssertTest └── FileAssertJsonAssert? (zero or one) ``` -## Interactions with Other Subsystems +### Interactions with Other Subsystems | Dependency | Usage | | :------------ | :------------------------------------------------------- | | Cli | Receives `Context` to report assertion failures. | | Configuration | Accepts DTO types for test, file, and rule construction. | -## Design Decisions +### Design Decisions - **Factory methods over constructors**: Each domain class provides an `internal static Create` method that validates the DTO and constructs the domain object, keeping constructors private. diff --git a/docs/design/file-assert/modeling/file-assert-file.md b/docs/design/file-assert/modeling/file-assert-file.md index 03dd01d..f0cd58d 100644 --- a/docs/design/file-assert/modeling/file-assert-file.md +++ b/docs/design/file-assert/modeling/file-assert-file.md @@ -1,14 +1,14 @@ -# FileAssertFile Design +### FileAssertFile Design -## Overview +#### Overview The `FileAssertFile` class locates files on disk using a glob pattern, enforces optional minimum and maximum count constraints, and delegates per-file assertions to file-type-specific assert units. -## Class Structure +#### Class Structure -### Properties +##### Properties | Property | Type | Description | | :----------- | :------------------------------- | :------------------------------------------------ | @@ -25,7 +25,7 @@ file-type-specific assert units. | `YamlAssert` | `FileAssertYamlAssert?` | YAML node assertions (null if not declared). | | `JsonAssert` | `FileAssertJsonAssert?` | JSON node assertions (null if not declared). | -### Factory Method +##### Factory Method ```csharp internal static FileAssertFile Create(FileAssertFileData data) @@ -35,7 +35,7 @@ The factory validates that `Pattern` is not null or whitespace before constructi the instance. Each file-type assert is created from the corresponding data block when that block is present. -### Execution Method +##### Execution Method ```csharp internal void Run(Context context, string basePath) @@ -78,7 +78,7 @@ Execution proceeds in five phases: reports an immediate error if parsing fails, otherwise applies dot-notation path count assertions. -### Count Constraint Error Messages +##### Count Constraint Error Messages ```text Pattern '' matched file(s), but expected at least @@ -86,14 +86,14 @@ Pattern '' matched file(s), but expected at most Pattern '' matched file(s), but expected exactly ``` -### Size Constraint Error Messages +##### Size Constraint Error Messages ```text File '' is byte(s), which is less than the minimum bytes File '' is byte(s), which exceeds the maximum bytes ``` -## YAML Configuration +#### YAML Configuration ```yaml files: @@ -109,7 +109,7 @@ files: All properties except `pattern` are optional. -## Design Decisions +#### Design Decisions - **Glob via FileSystemGlobbing**: The `Microsoft.Extensions.FileSystemGlobbing` library is already a project dependency and provides cross-platform glob support diff --git a/docs/design/file-assert/modeling/file-assert-html-assert.md b/docs/design/file-assert/modeling/file-assert-html-assert.md index a2aa938..bda9c1d 100644 --- a/docs/design/file-assert/modeling/file-assert-html-assert.md +++ b/docs/design/file-assert/modeling/file-assert-html-assert.md @@ -1,19 +1,19 @@ -# FileAssertHtmlAssert Design +### FileAssertHtmlAssert Design -## Overview +#### Overview The `FileAssertHtmlAssert` class attempts to parse a matched file as an HTML document using `HtmlAgilityPack`. If parsing produces critical errors, an error is reported and no further assertions are evaluated. Otherwise it evaluates each XPath query against the document and applies min, max, and exact count constraints to the number of matching nodes. -## Class Structure +#### Class Structure -### FileAssertHtmlAssert +##### FileAssertHtmlAssert The main class coordinating XPath-based node count assertions for an HTML file. -#### FileAssertHtmlAssert Properties +###### FileAssertHtmlAssert Properties | Property | Type | Description | | :-------- | :----------------------------------- | :---------------------- | @@ -28,13 +28,13 @@ Each `FileAssertHtmlQuery` entry holds: | `Min` | `int?` | Minimum number of matched nodes. | | `Max` | `int?` | Maximum number of matched nodes. | -#### FileAssertHtmlAssert Factory +###### FileAssertHtmlAssert Factory ```csharp internal static FileAssertHtmlAssert Create(IEnumerable data) ``` -#### FileAssertHtmlAssert Run +###### FileAssertHtmlAssert Run ```csharp internal void Run(Context context, string fileName) @@ -49,13 +49,13 @@ Execution proceeds in the following steps: `HtmlDocument.DocumentNode.SelectNodes(xpathQuery)`, counts the result, and applies `Count`, `Min`, and `Max` constraints against the match count. -#### FileAssertHtmlAssert Parse Error Message +###### FileAssertHtmlAssert Parse Error Message ```text File '' could not be parsed as an HTML document ``` -#### FileAssertHtmlAssert Query Error Messages +###### FileAssertHtmlAssert Query Error Messages ```text File '' query '' returned result(s) which is below the minimum of @@ -63,7 +63,7 @@ File '' query '' returned result(s) which exceeds the maxim File '' query '' returned result(s) but expected exactly ``` -## YAML Configuration +#### YAML Configuration ```yaml files: @@ -77,7 +77,7 @@ files: min: 1 ``` -## Design Decisions +#### Design Decisions - **HtmlAgilityPack chosen**: HtmlAgilityPack is the de-facto standard for lenient HTML parsing in .NET. It handles malformed HTML gracefully, making it appropriate for diff --git a/docs/design/file-assert/modeling/file-assert-json-assert.md b/docs/design/file-assert/modeling/file-assert-json-assert.md index a66f9aa..958f5e9 100644 --- a/docs/design/file-assert/modeling/file-assert-json-assert.md +++ b/docs/design/file-assert/modeling/file-assert-json-assert.md @@ -1,6 +1,6 @@ -# FileAssertJsonAssert Design +### FileAssertJsonAssert Design -## Overview +#### Overview The `FileAssertJsonAssert` class attempts to parse a matched file as a JSON document using `System.Text.Json.JsonDocument.Parse`. If parsing fails, an error is reported and no further @@ -8,13 +8,13 @@ assertions are evaluated. Otherwise it evaluates each dot-notation path against element tree and applies min, max, and exact count constraints to the number of matching elements. -## Class Structure +#### Class Structure -### FileAssertJsonAssert +##### FileAssertJsonAssert The main class coordinating dot-notation path assertions for a JSON file. -#### FileAssertJsonAssert Properties +###### FileAssertJsonAssert Properties | Property | Type | Description | | :-------- | :----------------------------------- | :---------------------------------- | @@ -29,13 +29,13 @@ Each `FileAssertJsonQuery` entry holds: | `Min` | `int?` | Minimum number of matched nodes. | | `Max` | `int?` | Maximum number of matched nodes. | -#### FileAssertJsonAssert Factory +###### FileAssertJsonAssert Factory ```csharp internal static FileAssertJsonAssert Create(IEnumerable data) ``` -#### FileAssertJsonAssert Run +###### FileAssertJsonAssert Run ```csharp internal void Run(Context context, string fileName) @@ -49,13 +49,13 @@ Execution proceeds in the following steps: segments, counts the matched properties or array elements, and applies `Count`, `Min`, and `Max` constraints against the match count. -#### FileAssertJsonAssert Parse Error Message +###### FileAssertJsonAssert Parse Error Message ```text File '' could not be parsed as a JSON document ``` -#### FileAssertJsonAssert Query Error Messages +###### FileAssertJsonAssert Query Error Messages ```text File '' query '' returned result(s) which is below the minimum of @@ -63,7 +63,7 @@ File '' query '' returned result(s) which exceeds the maxim File '' query '' returned result(s) but expected exactly ``` -## YAML Configuration +#### YAML Configuration ```yaml files: @@ -77,7 +77,7 @@ files: count: 1 ``` -## Design Decisions +#### Design Decisions - **No additional dependencies**: `System.Text.Json` is part of the .NET BCL, so JSON assertions require no additional NuGet packages. diff --git a/docs/design/file-assert/modeling/file-assert-pdf-assert.md b/docs/design/file-assert/modeling/file-assert-pdf-assert.md index 19d02f3..ca2b314 100644 --- a/docs/design/file-assert/modeling/file-assert-pdf-assert.md +++ b/docs/design/file-assert/modeling/file-assert-pdf-assert.md @@ -1,18 +1,18 @@ -# FileAssertPdfAssert Design +### FileAssertPdfAssert Design -## Overview +#### Overview The `FileAssertPdfAssert` class attempts to parse a matched file as a PDF document using PdfPig. If parsing fails, an error is reported and no further assertions are evaluated. Otherwise it applies metadata field assertions, page count constraints, and body text rules. -## Class Structure +#### Class Structure -### PdfMetadataRule +##### PdfMetadataRule An inner modeling class that applies a single PDF metadata field assertion. -#### PdfMetadataRule Properties +###### PdfMetadataRule Properties | Property | Type | Description | | :--------- | :-------- | :------------------------------------------------- | @@ -20,13 +20,13 @@ An inner modeling class that applies a single PDF metadata field assertion. | `Contains` | `string?` | Metadata value must contain this substring. | | `Matches` | `string?` | Metadata value must match this regular expression. | -#### PdfMetadataRule Factory +###### PdfMetadataRule Factory ```csharp internal static PdfMetadataRule FromData(FileAssertPdfMetadataRuleData data) ``` -#### PdfMetadataRule Apply +###### PdfMetadataRule Apply ```csharp internal void Apply(Context context, string fileName, string? fieldValue) @@ -34,31 +34,31 @@ internal void Apply(Context context, string fileName, string? fieldValue) Checks `Contains` substring presence (ordinal) and `Matches` regex against `fieldValue`. -#### PdfMetadataRule Error Messages +###### PdfMetadataRule Error Messages ```text File '' PDF metadata '' does not contain '' File '' PDF metadata '' does not match '' ``` -### PdfPages +##### PdfPages An inner modeling class that enforces page count constraints. -#### PdfPages Properties +###### PdfPages Properties | Property | Type | Description | | :------- | :----- | :----------------------- | | `Min` | `int?` | Minimum number of pages. | | `Max` | `int?` | Maximum number of pages. | -#### PdfPages Factory +###### PdfPages Factory ```csharp internal static PdfPages FromData(FileAssertPdfPagesData data) ``` -#### PdfPages Apply +###### PdfPages Apply ```csharp internal void Apply(Context context, string fileName, int n) @@ -66,18 +66,18 @@ internal void Apply(Context context, string fileName, int n) Reports an error if `n < Min` or `n > Max`. -#### PdfPages Error Messages +###### PdfPages Error Messages ```text File '' PDF has page(s) which is below the minimum of File '' PDF has page(s) which exceeds the maximum of ``` -### FileAssertPdfAssert +##### FileAssertPdfAssert The main class coordinating metadata, page count, and body text assertions for a PDF file. -#### FileAssertPdfAssert Properties +###### FileAssertPdfAssert Properties | Field | Type | Description | | :---------- | :-------------------------------- | :--------------------------------------------- | @@ -85,7 +85,7 @@ The main class coordinating metadata, page count, and body text assertions for a | `_pages` | `PdfPages?` | Page count constraints (null if not declared). | | `_text` | `IReadOnlyList` | Body text rules. | -#### FileAssertPdfAssert Factory +###### FileAssertPdfAssert Factory ```csharp internal static FileAssertPdfAssert Create(FileAssertPdfData data) @@ -93,7 +93,7 @@ internal static FileAssertPdfAssert Create(FileAssertPdfData data) Creates metadata rules, page constraints, and text rules from the DTO. -#### FileAssertPdfAssert Run +###### FileAssertPdfAssert Run ```csharp internal void Run(Context context, string fileName) @@ -108,13 +108,13 @@ Execution proceeds in the following steps: 5. If `Text` rules are defined, extracts page text via PdfPig, concatenates, and applies each rule. -#### FileAssertPdfAssert Parse Error Message +###### FileAssertPdfAssert Parse Error Message ```text File '' could not be parsed as a PDF document ``` -#### FileAssertPdfAssert GetMetadataField +###### FileAssertPdfAssert GetMetadataField ```csharp private static string? GetMetadataField(PdfDocument document, string field) @@ -136,7 +136,7 @@ Recognized field names: Any other field name returns `null`. -## YAML Configuration +#### YAML Configuration ```yaml files: @@ -155,7 +155,7 @@ files: - does-not-contain: "DRAFT" ``` -## Design Decisions +#### Design Decisions - **Immediate failure on parse error**: Attempting to apply metadata, page, or text assertions against a file that is not a valid PDF would produce meaningless partial diff --git a/docs/design/file-assert/modeling/file-assert-rule.md b/docs/design/file-assert/modeling/file-assert-rule.md index 265f4eb..4155847 100644 --- a/docs/design/file-assert/modeling/file-assert-rule.md +++ b/docs/design/file-assert/modeling/file-assert-rule.md @@ -1,21 +1,21 @@ -# FileAssertRule Design +### FileAssertRule Design -## Overview +#### Overview The `FileAssertRule` class hierarchy provides the content validation rules used by `FileAssertTextAssert` to assert the textual content of matched files. Rules are created from YAML configuration data using a factory method and are applied to file content during test execution. -## Class Structure +#### Class Structure -### FileAssertRule (Abstract Base Class) +##### FileAssertRule (Abstract Base Class) `FileAssertRule` is an abstract class that defines the common interface for all content validation rules. It provides a static factory method that selects the correct concrete implementation based on the deserialized YAML data. -### Factory Method +##### Factory Method ```csharp internal static FileAssertRule Create(FileAssertRuleData data) @@ -27,7 +27,7 @@ property determines the concrete type returned. If no property is set the factor throws `InvalidOperationException` with a descriptive message listing all four supported rule types. -### Abstract Method +##### Abstract Method ```csharp internal abstract void Apply(Context context, string fileName, string content) @@ -37,56 +37,56 @@ Each derived class implements `Apply` to perform its specific check against `content`. When the check fails the rule calls `context.WriteError` to record the failure; no exception is thrown, allowing all rules to be evaluated independently. -### FileAssertContainsRule +##### FileAssertContainsRule Checks whether the file content contains a required substring using an ordinal (byte-exact) string comparison. This is appropriate for license header checks, copyright notices, and other exact-text requirements. -#### ContainsRule Error Message Format +###### ContainsRule Error Message Format ```text File '' does not contain expected text '' ``` -### FileAssertDoesNotContainRule +##### FileAssertDoesNotContainRule Checks whether the file content does NOT contain a forbidden substring using an ordinal (byte-exact) string comparison. This is appropriate for asserting that sensitive strings such as hard-coded passwords or debug flags are absent. -#### DoesNotContainRule Error Message Format +###### DoesNotContainRule Error Message Format ```text File '' contains forbidden text '' ``` -### FileAssertMatchesRule +##### FileAssertMatchesRule Checks whether the file content matches a regular expression. The regex is compiled at construction time with a ten-second evaluation timeout to guard against catastrophic backtracking on adversarial or malformed content. -#### MatchesRule Error Message Format +###### MatchesRule Error Message Format ```text File '' does not match pattern '' ``` -### FileAssertDoesNotMatchRule +##### FileAssertDoesNotMatchRule Checks whether the file content does NOT match a forbidden regular expression. The regex is compiled at construction time with a ten-second evaluation timeout. This is appropriate for asserting that log files contain no fatal errors or that source files contain no debug-only patterns. -#### DoesNotMatchRule Error Message Format +###### DoesNotMatchRule Error Message Format ```text File '' matches forbidden pattern '' ``` -## YAML Configuration +#### YAML Configuration Rules are declared under the `text` key of a file entry. Each rule item specifies exactly one of the supported rule types: @@ -102,7 +102,7 @@ text: The `FileAssertRuleData` data transfer object is deserialized by YamlDotNet and passed to `FileAssertRule.Create` to produce the concrete rule instance. -## Design Decisions +#### Design Decisions - **Abstract base class over interface**: The base class provides the factory method alongside the abstract `Apply` method, keeping rule creation and diff --git a/docs/design/file-assert/modeling/file-assert-test.md b/docs/design/file-assert/modeling/file-assert-test.md index 2802e1d..596df3b 100644 --- a/docs/design/file-assert/modeling/file-assert-test.md +++ b/docs/design/file-assert/modeling/file-assert-test.md @@ -1,15 +1,15 @@ -# FileAssertTest Design +### FileAssertTest Design -## Overview +#### Overview The `FileAssertTest` class represents a named, tagged test within a FileAssert configuration. It groups a collection of `FileAssertFile` assertions and supports filter-based selection so that users can run targeted subsets of the test suite from the command line. -## Class Structure +#### Class Structure -### Properties +##### Properties | Property | Type | Description | | :------- | :------------------------------ | :----------------------------------------- | @@ -17,7 +17,7 @@ from the command line. | `Tags` | `IReadOnlyList` | Tags used for filter-based test selection. | | `Files` | `IReadOnlyList` | File assertions belonging to this test. | -### Factory Method +##### Factory Method ```csharp internal static FileAssertTest Create(FileAssertTestData data) @@ -27,7 +27,7 @@ The factory validates that `Name` is not null or whitespace. An empty or null `Tags` or `Files` list is treated as an empty collection rather than an error. Passing a null `data` argument throws `ArgumentNullException`. -### Filter Method +##### Filter Method ```csharp internal bool MatchesFilter(IEnumerable filters) @@ -39,7 +39,7 @@ Returns `true` when: - Any filter string matches `Name` using `OrdinalIgnoreCase` comparison, or - Any filter string matches any element of `Tags` using `OrdinalIgnoreCase` comparison. -### Execution Method +##### Execution Method ```csharp internal void Run(Context context, string basePath) @@ -50,7 +50,7 @@ by individual file assertions accumulate in the context and do not stop subseque assertions from running. Passing a null `context` or null `basePath` throws `ArgumentNullException`. -## YAML Configuration +#### YAML Configuration ```yaml tests: @@ -65,7 +65,7 @@ tests: - contains: "Copyright (c) DEMA Consulting" ``` -## Design Decisions +#### Design Decisions - **Non-empty name required**: A name is required so that errors and run logs identify which test failed without ambiguity. diff --git a/docs/design/file-assert/modeling/file-assert-text-assert.md b/docs/design/file-assert/modeling/file-assert-text-assert.md index 7464d9c..1745502 100644 --- a/docs/design/file-assert/modeling/file-assert-text-assert.md +++ b/docs/design/file-assert/modeling/file-assert-text-assert.md @@ -1,6 +1,6 @@ -# FileAssertTextAssert Design +### FileAssertTextAssert Design -## Overview +#### Overview The `FileAssertTextAssert` class applies a collection of `FileAssertRule` instances to the text content of a matched file. It is created from a list of `FileAssertRuleData` DTOs and @@ -8,15 +8,15 @@ delegates rule application to `FileAssertRule.Apply`. Wrapping text rules in a d unit keeps `FileAssertFile` free of rule-application logic and makes the text assertion pattern consistent with all other file-type assert units. -## Class Structure +#### Class Structure -### Properties +##### Properties | Property | Type | Description | | :------- | :------------------------------ | :-------------------------------------- | | `Rules` | `IReadOnlyList` | Content rules applied to the file text. | -### Factory Method +##### Factory Method ```csharp internal static FileAssertTextAssert Create(IEnumerable data) @@ -33,7 +33,7 @@ Creates a `FileAssertRule` for each entry in the data list via `FileAssertRule.C | Returns | A new `FileAssertTextAssert` instance. | | `ArgumentNullException` | Thrown when `data` is null. | -### Run Method +##### Run Method ```csharp internal void Run(Context context, string fileName) @@ -49,7 +49,7 @@ Execution proceeds in the following steps: and returns immediately. 3. Applies each configured rule to the file content. -#### Run Error Message +###### Run Error Message ```text File '' could not be read as text @@ -60,7 +60,7 @@ File '' could not be read as text | `context` | `Context` | Reporting sink used to record errors. | | `fileName` | `string` | Full path to the file to validate. | -## YAML Configuration +#### YAML Configuration Text rules are declared under the `text:` key of a file entry: @@ -74,7 +74,7 @@ files: - does-not-contain-regex: "FATAL|ERROR" ``` -## Design Decisions +#### Design Decisions - **Dedicated unit for text rules**: Wrapping text rules in `FileAssertTextAssert` keeps `FileAssertFile` free of rule-application logic and makes the text assertion pattern diff --git a/docs/design/file-assert/modeling/file-assert-xml-assert.md b/docs/design/file-assert/modeling/file-assert-xml-assert.md index 83eb536..cac4afc 100644 --- a/docs/design/file-assert/modeling/file-assert-xml-assert.md +++ b/docs/design/file-assert/modeling/file-assert-xml-assert.md @@ -1,19 +1,19 @@ -# FileAssertXmlAssert Design +### FileAssertXmlAssert Design -## Overview +#### Overview The `FileAssertXmlAssert` class attempts to parse a matched file as an XML document using `System.Xml.Linq` (`XDocument.Load`). If parsing fails, an error is reported and no further assertions are evaluated. Otherwise it evaluates each XPath query against the document and applies min, max, and exact count constraints to the number of matching nodes. -## Class Structure +#### Class Structure -### FileAssertXmlAssert +##### FileAssertXmlAssert The main class coordinating XPath-based node count assertions for an XML file. -#### FileAssertXmlAssert Properties +###### FileAssertXmlAssert Properties | Property | Type | Description | | :-------- | :---------------------------------- | :---------------------- | @@ -28,13 +28,13 @@ Each `FileAssertXmlQuery` entry holds: | `Min` | `int?` | Minimum number of matched nodes. | | `Max` | `int?` | Maximum number of matched nodes. | -#### FileAssertXmlAssert Factory +###### FileAssertXmlAssert Factory ```csharp internal static FileAssertXmlAssert Create(IEnumerable data) ``` -#### FileAssertXmlAssert Run +###### FileAssertXmlAssert Run ```csharp internal void Run(Context context, string fileName) @@ -48,13 +48,13 @@ Execution proceeds in the following steps: `System.Xml.XPath` extension methods, counts the matching nodes, and applies `Count`, `Min`, and `Max` constraints against the match count. -#### FileAssertXmlAssert Parse Error Message +###### FileAssertXmlAssert Parse Error Message ```text File '' could not be parsed as an XML document ``` -#### FileAssertXmlAssert Query Error Messages +###### FileAssertXmlAssert Query Error Messages ```text File '' query '' returned result(s) which is below the minimum of @@ -62,7 +62,7 @@ File '' query '' returned result(s) which exceeds the maxim File '' query '' returned result(s) but expected exactly ``` -## YAML Configuration +#### YAML Configuration ```yaml files: @@ -74,7 +74,7 @@ files: count: 1 ``` -## Design Decisions +#### Design Decisions - **No additional dependencies**: `System.Xml.Linq` and `System.Xml.XPath` are part of the .NET BCL, so XML assertions require no additional NuGet packages. diff --git a/docs/design/file-assert/modeling/file-assert-yaml-assert.md b/docs/design/file-assert/modeling/file-assert-yaml-assert.md index c47989b..50e1be5 100644 --- a/docs/design/file-assert/modeling/file-assert-yaml-assert.md +++ b/docs/design/file-assert/modeling/file-assert-yaml-assert.md @@ -1,19 +1,19 @@ -# FileAssertYamlAssert Design +### FileAssertYamlAssert Design -## Overview +#### Overview The `FileAssertYamlAssert` class attempts to parse a matched file as a YAML document using `YamlDotNet`. If parsing fails, an error is reported and no further assertions are evaluated. Otherwise it evaluates each dot-notation path against the YAML document tree and applies min, max, and exact count constraints to the number of matching nodes. -## Class Structure +#### Class Structure -### FileAssertYamlAssert +##### FileAssertYamlAssert The main class coordinating dot-notation path assertions for a YAML file. -#### FileAssertYamlAssert Properties +###### FileAssertYamlAssert Properties | Property | Type | Description | | :-------- | :----------------------------------- | :---------------------------------- | @@ -28,13 +28,13 @@ Each `FileAssertYamlQuery` entry holds: | `Min` | `int?` | Minimum number of matched nodes. | | `Max` | `int?` | Maximum number of matched nodes. | -#### FileAssertYamlAssert Factory +###### FileAssertYamlAssert Factory ```csharp internal static FileAssertYamlAssert Create(IEnumerable data) ``` -#### FileAssertYamlAssert Run +###### FileAssertYamlAssert Run ```csharp internal void Run(Context context, string fileName) @@ -48,13 +48,13 @@ Execution proceeds in the following steps: path segments, counts the matched nodes, and applies `Count`, `Min`, and `Max` constraints against the match count. -#### FileAssertYamlAssert Parse Error Message +###### FileAssertYamlAssert Parse Error Message ```text File '' could not be parsed as a YAML document ``` -#### FileAssertYamlAssert Query Error Messages +###### FileAssertYamlAssert Query Error Messages ```text File '' query '' returned result(s) which is below the minimum of @@ -62,7 +62,7 @@ File '' query '' returned result(s) which exceeds the maxim File '' query '' returned result(s) but expected exactly ``` -## YAML Configuration +#### YAML Configuration ```yaml files: @@ -76,7 +76,7 @@ files: count: 3 ``` -## Design Decisions +#### Design Decisions - **YamlDotNet reuse**: YamlDotNet is already a project dependency for configuration deserialization. Reusing it for YAML assertions avoids adding a new library. diff --git a/docs/design/file-assert/ots-dependencies.md b/docs/design/file-assert/ots-dependencies.md index 78d7b02..2509b9b 100644 --- a/docs/design/file-assert/ots-dependencies.md +++ b/docs/design/file-assert/ots-dependencies.md @@ -1,14 +1,14 @@ -# OTS Dependencies Design +## OTS Dependencies Design -## Overview +### Overview FileAssert relies on several off-the-shelf (OTS) tools and libraries that are integrated into the build, quality, and traceability pipeline. This document describes each OTS dependency, its purpose, and how its correct operation is verified. -## OTS Tools +### OTS Tools -### ReqStream +#### ReqStream | Attribute | Value | | :----------- | :----------------------------------------------------------------- | @@ -20,7 +20,7 @@ ReqStream reads requirements from `docs/reqstream/**/*.yaml` and cross-reference against TRX test result files. It enforces that every requirement listed is traceable to a passing test, providing continuous compliance evidence for formal reviews. -### ReviewMark +#### ReviewMark | Attribute | Value | | :----------- | :------------------------------------------------------------------ | @@ -32,7 +32,7 @@ ReviewMark reads review records from the repository and validates that every fil included in a review-set has a recorded review. This provides a continuous audit trail for compliance with formal code review requirements. -### SonarMark +#### SonarMark | Attribute | Value | | :----------- | :--------------------------------------------------------- | @@ -44,7 +44,7 @@ SonarMark queries the SonarCloud API and surfaces the quality gate result as a b step. Failures in code quality metrics (coverage, duplications, maintainability) are caught before merging. -### SarifMark +#### SarifMark | Attribute | Value | | :----------- | :--------------------------------------------------------------- | @@ -56,7 +56,7 @@ SarifMark processes the SARIF files produced by CodeQL and generates a Markdown summary report. Any open high-severity alerts cause the build to fail, enforcing zero-tolerance for unaddressed security findings. -### BuildMark +#### BuildMark | Attribute | Value | | :----------- | :-------------------------------------------------------------------------- | @@ -68,7 +68,7 @@ BuildMark interrogates installed tool versions and writes a version manifest to build output. This ensures that the exact tool versions used to produce a release are permanently recorded and reproducible. -### VersionMark +#### VersionMark | Attribute | Value | | :----------- | :------------------------------------------------------------------ | @@ -80,7 +80,7 @@ VersionMark reads the version from a central configuration file and propagates i all artifacts produced by the build. This eliminates manual version updates and ensures consistency between the NuGet package version, assembly version, and release tag. -### xUnit +#### xUnit | Attribute | Value | | :----------- | :----------------------------------------------------------------------------------- | diff --git a/docs/design/file-assert/program.md b/docs/design/file-assert/program.md index 22c16c9..8f10e16 100644 --- a/docs/design/file-assert/program.md +++ b/docs/design/file-assert/program.md @@ -1,15 +1,15 @@ -# Program Design +## Program Design -## Overview +### Overview `Program` is the entry point for the FileAssert tool. It owns the `Main` method, constructs a `Context` from command-line arguments, dispatches to the appropriate handler based on context flags, and returns the final exit code. It also exposes a `Version` property used by both the version display path and the self-validation header. -## Class Structure +### Class Structure -### Version Property +#### Version Property ```csharp public static string Version { get; } @@ -18,7 +18,7 @@ public static string Version { get; } Reads the informational version from the executing assembly's `AssemblyInformationalVersionAttribute`. Falls back to the assembly version, then to `"0.0.0"`. -### Main Method +#### Main Method ```csharp private static int Main(string[] args) @@ -29,7 +29,7 @@ and `InvalidOperationException` to print expected error messages and return exit Unexpected exceptions are re-thrown after printing the message so that the runtime generates an event-log entry. -### Run Method +#### Run Method ```csharp public static void Run(Context context) @@ -44,7 +44,7 @@ Inspects context flags in the following priority order: | 3 | `context.Validate` | Print banner; delegate to `Validation.Run`. | | 4 | Default | Print banner; delegate to `RunToolLogic`. | -### RunToolLogic Method +#### RunToolLogic Method ```csharp private static void RunToolLogic(Context context) @@ -57,7 +57,7 @@ without setting an error. When an explicitly specified file is absent, it calls `FileAssertConfig.ReadFromFile` and then passes `context.Filters` (the positional name-or-tag arguments) to `config.Run` so that only matching tests are executed. -## Interactions with Other Units +### Interactions with Other Units | Dependency | Usage | | :------------------ | :------------------------------------------------------------ | @@ -65,7 +65,7 @@ arguments) to `config.Run` so that only matching tests are executed. | `Validation` | Invoked by `Run` when `--validate` is set. | | `FileAssertConfig` | Loaded from file and executed by `RunToolLogic`. | -## Design Decisions +### Design Decisions - **Public `Run` method**: `Run` is `public` so that unit tests and the self-validation tests can invoke it directly without starting a new process. diff --git a/docs/design/file-assert/selftest/selftest.md b/docs/design/file-assert/selftest.md similarity index 92% rename from docs/design/file-assert/selftest/selftest.md rename to docs/design/file-assert/selftest.md index bad81cb..d2cdc5d 100644 --- a/docs/design/file-assert/selftest/selftest.md +++ b/docs/design/file-assert/selftest.md @@ -1,25 +1,25 @@ -# SelfTest Subsystem Design +## SelfTest Subsystem Design -## Overview +### Overview The SelfTest subsystem provides built-in self-validation functionality that verifies the core behavior of the tool at run time. It is invoked via the `--validate` command-line flag and produces structured test results that can be written to a TRX or JUnit XML file. -## Subsystem Contents +### Subsystem Contents | Unit | File | Responsibility | | :----------- | :-------------- | :------------------------------------------------------- | | `Validation` | `Validation.cs` | Runs built-in self-validation tests and reports results. | -## Subsystem Responsibilities +### Subsystem Responsibilities - Execute a set of built-in test cases that exercise core tool functionality. - Collect and summarize test outcomes (passed, failed). - Optionally serialize results to TRX or JUnit XML format. - Report a system information header before running tests. -## Interactions with Other Subsystems +### Interactions with Other Subsystems | Dependency | Usage | | :---------- | :----------------------------------------------------------------- | @@ -28,7 +28,7 @@ produces structured test results that can be written to a TRX or JUnit XML file. | Program | References `Program.Version` for the system information header. | | | Calls `Program.Run` and `Context.Create` to exercise the tool. | -## Design Decisions +### Design Decisions - **Self-contained tests**: Each built-in test creates its own `Context` with a temporary log file, runs `Program.Run`, and inspects the output. No external test framework is required at diff --git a/docs/design/file-assert/selftest/validation.md b/docs/design/file-assert/selftest/validation.md index d3c892d..52bbd4e 100644 --- a/docs/design/file-assert/selftest/validation.md +++ b/docs/design/file-assert/selftest/validation.md @@ -1,15 +1,15 @@ -# Validation Design +### Validation Design -## Overview +#### Overview `Validation` is a static class that implements the self-validation test runner for FileAssert. It runs a series of built-in tests that exercise the tool's core functionality, prints a structured report to the context output, and optionally writes results to a TRX or JUnit XML file. -## Class Structure +#### Class Structure -### Run Method +##### Run Method ```csharp public static void Run(Context context) @@ -24,7 +24,7 @@ Entry point for self-validation. Executes the following steps: 4. Prints a pass/fail summary. 5. Writes the results file if `context.ResultsFile` is set. -### Built-in Tests +##### Built-in Tests | Test Name | Description | | :-------------------------- | :----------------------------------------------------------------------------------- | @@ -50,7 +50,7 @@ Each test body: 4. Calls `Program.Run` and checks the exit code and/or output files. 5. Returns `null` on success or an error message string on failure. -### RunValidationTest Helper +##### RunValidationTest Helper ```csharp private static void RunValidationTest( @@ -64,7 +64,7 @@ Central dispatcher for all built-in tests. Executes `testBody`, maps its return a pass/fail outcome, logs the result to the context, handles unhandled exceptions, and adds the `TestResult` to the collection. -### Results Serialization +##### Results Serialization ```csharp private static void WriteResultsFile(Context context, TestResults testResults) @@ -77,13 +77,13 @@ Writes the collected results to the file specified by `context.ResultsFile`: - Other extensions → error written to context. - Any I/O or other exception is caught and an error message is written to context. -### TemporaryDirectory Helper +##### TemporaryDirectory Helper A private nested `IDisposable` class that creates a unique temporary directory on construction and deletes it recursively on disposal. Uses `PathHelpers.SafePathCombine` to build the directory path under `Path.GetTempPath()`. -## Design Decisions +#### Design Decisions - **`RunValidationTest` dispatcher**: All built-in tests share a single helper that owns the try/catch, pass/fail recording, logging, and result finalization. Each test body only needs to diff --git a/docs/design/file-assert/utilities/utilities.md b/docs/design/file-assert/utilities.md similarity index 89% rename from docs/design/file-assert/utilities/utilities.md rename to docs/design/file-assert/utilities.md index 9f2f7e1..de370a8 100644 --- a/docs/design/file-assert/utilities/utilities.md +++ b/docs/design/file-assert/utilities.md @@ -1,29 +1,29 @@ -# Utilities Subsystem Design +## Utilities Subsystem Design -## Overview +### Overview The Utilities subsystem provides shared helper functionality used by other subsystems. It contains security-sensitive or otherwise reusable operations that do not belong to any specific domain subsystem. -## Subsystem Contents +### Subsystem Contents | Unit | File | Responsibility | | :------------ | :--------------- | :------------------------------------------------------------ | | `PathHelpers` | `PathHelpers.cs` | Safe path-combination utility with path-traversal protection. | -## Subsystem Responsibilities +### Subsystem Responsibilities - Provide path utilities that safely combine paths while preventing path-traversal attacks. - Reject relative paths containing `..` or absolute paths when a relative path is expected. -## Interactions with Other Subsystems +### Interactions with Other Subsystems | Consumer | Usage | | :-------- | :----------------------------------------------------------------------- | | SelfTest | Uses `PathHelpers.SafePathCombine` when creating temporary log files. | -## Design Decisions +### Design Decisions - **Static class**: `PathHelpers` is a static utility class with no instance state, suitable for use anywhere in the codebase without injection. diff --git a/docs/design/file-assert/utilities/path-helpers.md b/docs/design/file-assert/utilities/path-helpers.md index 9430473..2796d4a 100644 --- a/docs/design/file-assert/utilities/path-helpers.md +++ b/docs/design/file-assert/utilities/path-helpers.md @@ -1,6 +1,6 @@ -# PathHelpers Design +### PathHelpers Design -## Overview +#### Overview `PathHelpers` is a static utility class that provides a safe path-combination method. It protects callers against path-traversal attacks by verifying the resolved combined path stays @@ -8,9 +8,9 @@ within the base directory. Note that `Path.GetFullPath` normalizes `.`/`..` segm not resolve symlinks or reparse points, so this check guards against string-level traversal only. -## Class Structure +#### Class Structure -### SafePathCombine Method +##### SafePathCombine Method ```csharp internal static string SafePathCombine(string basePath, string relativePath) @@ -30,7 +30,7 @@ the base directory. or `Path.AltDirectorySeparatorChar`, or is itself rooted (absolute), which would indicate the combined path escapes the base directory. -## Design Decisions +#### Design Decisions - **`Path.GetRelativePath` for containment check**: Using `GetRelativePath` to verify containment handles root paths (e.g. `/`, `C:\`), platform case-sensitivity, and diff --git a/docs/design/introduction.md b/docs/design/introduction.md index c45a64a..aa40b70 100644 --- a/docs/design/introduction.md +++ b/docs/design/introduction.md @@ -113,6 +113,23 @@ Throughout this document: methods/algorithms, and interactions with other units. - Text tables are used in preference to diagrams, which may not render in all PDF viewers. +## Companion Artifact Structure + +Each in-house software item has corresponding artifacts in parallel directory trees: + +- Requirements: `docs/reqstream/{system-name}.yaml`, `docs/reqstream/{system-name}/.../{item}.yaml` +- Design docs: `docs/design/{system-name}.md`, `docs/design/{system-name}/.../{item}.md` +- Verification: `docs/verification/{system-name}.md`, `docs/verification/{system-name}/.../{item}.md` +- Source code: `src/{SystemName}/.../{Item}.cs` (PascalCase for C#) +- Tests: `test/{SystemName}.Tests/.../{Item}Tests.cs` (PascalCase for C#) + +OTS items have no design documentation; their artifacts sit parallel to system folders: + +- Requirements: `docs/reqstream/ots/{ots-name}.yaml` +- Verification: `docs/verification/ots/{ots-name}.md` + +Review-sets: defined in `.reviewmark.yaml` + ## References - [FileAssert User Guide][guide] diff --git a/docs/reqstream/file-assert/file-assert.yaml b/docs/reqstream/file-assert.yaml similarity index 100% rename from docs/reqstream/file-assert/file-assert.yaml rename to docs/reqstream/file-assert.yaml diff --git a/docs/reqstream/file-assert/cli/cli.yaml b/docs/reqstream/file-assert/cli.yaml similarity index 100% rename from docs/reqstream/file-assert/cli/cli.yaml rename to docs/reqstream/file-assert/cli.yaml diff --git a/docs/reqstream/file-assert/configuration/configuration.yaml b/docs/reqstream/file-assert/configuration.yaml similarity index 100% rename from docs/reqstream/file-assert/configuration/configuration.yaml rename to docs/reqstream/file-assert/configuration.yaml diff --git a/docs/reqstream/file-assert/modeling/modeling.yaml b/docs/reqstream/file-assert/modeling.yaml similarity index 100% rename from docs/reqstream/file-assert/modeling/modeling.yaml rename to docs/reqstream/file-assert/modeling.yaml diff --git a/docs/reqstream/file-assert/selftest/selftest.yaml b/docs/reqstream/file-assert/selftest.yaml similarity index 100% rename from docs/reqstream/file-assert/selftest/selftest.yaml rename to docs/reqstream/file-assert/selftest.yaml diff --git a/docs/reqstream/file-assert/utilities/utilities.yaml b/docs/reqstream/file-assert/utilities.yaml similarity index 100% rename from docs/reqstream/file-assert/utilities/utilities.yaml rename to docs/reqstream/file-assert/utilities.yaml diff --git a/docs/verification/definition.yaml b/docs/verification/definition.yaml index 2f2e26e..1095c2f 100644 --- a/docs/verification/definition.yaml +++ b/docs/verification/definition.yaml @@ -1,26 +1,19 @@ --- resource-path: - docs/verification - - docs/verification/file-assert - - docs/verification/file-assert/cli - - docs/verification/file-assert/configuration - - docs/verification/file-assert/modeling - - docs/verification/file-assert/utilities - - docs/verification/file-assert/selftest - - docs/verification/ots - docs/template input-files: - docs/verification/title.txt - docs/verification/introduction.md - - docs/verification/file-assert/file-assert.md + - docs/verification/file-assert.md - docs/verification/file-assert/program.md - - docs/verification/file-assert/cli/cli.md + - docs/verification/file-assert/cli.md - docs/verification/file-assert/cli/context.md - - docs/verification/file-assert/configuration/configuration.md + - docs/verification/file-assert/configuration.md - docs/verification/file-assert/configuration/file-assert-config.md - docs/verification/file-assert/configuration/file-assert-data.md - - docs/verification/file-assert/modeling/modeling.md + - docs/verification/file-assert/modeling.md - docs/verification/file-assert/modeling/file-assert-test.md - docs/verification/file-assert/modeling/file-assert-file.md - docs/verification/file-assert/modeling/file-assert-rule.md @@ -30,10 +23,11 @@ input-files: - docs/verification/file-assert/modeling/file-assert-html-assert.md - docs/verification/file-assert/modeling/file-assert-yaml-assert.md - docs/verification/file-assert/modeling/file-assert-json-assert.md - - docs/verification/file-assert/utilities/utilities.md + - docs/verification/file-assert/utilities.md - docs/verification/file-assert/utilities/path-helpers.md - - docs/verification/file-assert/selftest/selftest.md + - docs/verification/file-assert/selftest.md - docs/verification/file-assert/selftest/validation.md + - docs/verification/ots.md - docs/verification/ots/buildmark.md - docs/verification/ots/fileassert.md - docs/verification/ots/pandoc.md diff --git a/docs/verification/file-assert/file-assert.md b/docs/verification/file-assert.md similarity index 100% rename from docs/verification/file-assert/file-assert.md rename to docs/verification/file-assert.md diff --git a/docs/verification/file-assert/cli/cli.md b/docs/verification/file-assert/cli.md similarity index 84% rename from docs/verification/file-assert/cli/cli.md rename to docs/verification/file-assert/cli.md index 77b6424..346a761 100644 --- a/docs/verification/file-assert/cli/cli.md +++ b/docs/verification/file-assert/cli.md @@ -1,17 +1,17 @@ -# Cli Subsystem Verification +## Cli Subsystem Verification This document describes the subsystem-level verification design for the `Cli` subsystem. It defines the integration test approach, subsystem boundary, mocking strategy, and test scenarios that together verify the `Cli` subsystem requirements. -## Verification Approach +### Verification Approach The `Cli` subsystem boundary at `Program` is verified by integration tests defined in `CliTests.cs`. Each test exercises `Context.Create` and `Program.Run` together, treating the pair as the observable subsystem interface. Tests pass controlled argument arrays and assert on captured console output, file system side-effects, and exit codes. -## Dependencies and Mocking Strategy +### Dependencies and Mocking Strategy At the subsystem boundary, `Validation` (part of the `SelfTest` subsystem) is the only external collaborator that `Program` calls. In scenarios that exercise the `--validate` path, `Validation` @@ -21,50 +21,50 @@ not reach `Validation` at all. No mocking is applied at this level; all collaborators within and directly adjacent to the subsystem use their real implementations. -## Integration Test Scenarios +### Integration Test Scenarios The following integration test scenarios are defined in `CliTests.cs`. -### Cli_CreateContext_ParsesSilentValidateAndLogFlags +#### Cli_CreateContext_ParsesSilentValidateAndLogFlags **Scenario**: Arguments containing `--silent`, `--validate`, and `--log ` flags are passed through `Context.Create`. **Expected**: All three flags are correctly parsed; exit code is 0. -### Cli_CreateContext_ParsesVersionHelpConfigResultsFlags +#### Cli_CreateContext_ParsesVersionHelpConfigResultsFlags **Scenario**: Arguments containing `--version`, `--help`, `--config `, and `--results ` flags are passed through `Context.Create`. **Expected**: All four flags are correctly parsed; exit code is 0. -### Cli_CreateContext_WithFilters_ParsesPositionalArguments +#### Cli_CreateContext_WithFilters_ParsesPositionalArguments **Scenario**: Positional arguments (test filters) are passed through `Context.Create`. **Expected**: The filters list contains the expected values; exit code is 0. -### Cli_CreateContext_UnknownArgument_ThrowsArgumentException +#### Cli_CreateContext_UnknownArgument_ThrowsArgumentException **Scenario**: An unrecognized argument is passed through `Context.Create`. **Expected**: An `ArgumentException` is thrown. -### Cli_WriteError_ChangesExitCodeToOne +#### Cli_WriteError_ChangesExitCodeToOne **Scenario**: `Context.WriteError` is called with an error message. **Expected**: `ExitCode` becomes 1 after the call. -### Cli_OutputPipeline_WritesMessagesToLogFile +#### Cli_OutputPipeline_WritesMessagesToLogFile **Scenario**: A context with both `--silent` and `--log ` flags is created; `Context.WriteLine` is called with a message. **Expected**: The message appears in the log file; exit code is 0. -## Requirements Coverage +### Requirements Coverage - **Argument parsing**: Cli_CreateContext_ParsesSilentValidateAndLogFlags, Cli_CreateContext_ParsesVersionHelpConfigResultsFlags, diff --git a/docs/verification/file-assert/cli/context.md b/docs/verification/file-assert/cli/context.md index 0d5c3f6..bfe137d 100644 --- a/docs/verification/file-assert/cli/context.md +++ b/docs/verification/file-assert/cli/context.md @@ -1,9 +1,9 @@ -# Context Verification +### Context Verification This document describes the unit-level verification design for the `Context` unit. It defines the test scenarios, dependency usage, and requirement coverage for `Cli/Context.cs`. -## Verification Approach +#### Verification Approach `Context` is verified with unit tests defined in `ContextTests.cs` and `ContextNewPropertiesTests.cs`. Because `Context` depends only on .NET base class library types @@ -11,14 +11,14 @@ test scenarios, dependency usage, and requirement coverage for `Cli/Context.cs`. `Context.Create` with controlled argument arrays, inspect the resulting properties and exit codes, and verify output written to captured streams. -## Dependencies +#### Dependencies `Context` has no dependencies on other tool units. All dependencies are real .NET BCL types; no mocking is needed at this level. -## Test Scenarios +#### Test Scenarios -### Context_Create_NoArguments_ReturnsDefaultContext +##### Context_Create_NoArguments_ReturnsDefaultContext **Scenario**: `Context.Create` is called with an empty argument array. @@ -26,7 +26,7 @@ no mocking is needed at this level. **Requirement coverage**: Default context creation requirement. -### Context_Create_VersionFlag_SetsVersionTrue +##### Context_Create_VersionFlag_SetsVersionTrue **Scenario**: `Context.Create` is called with `["--version"]`. @@ -34,7 +34,7 @@ no mocking is needed at this level. **Requirement coverage**: Version flag parsing requirement. -### Context_Create_ShortVersionFlag_SetsVersionTrue +##### Context_Create_ShortVersionFlag_SetsVersionTrue **Scenario**: `Context.Create` is called with `["-v"]`. @@ -42,7 +42,7 @@ no mocking is needed at this level. **Requirement coverage**: Short version flag parsing requirement. -### Context_Create_HelpFlag_SetsHelpTrue +##### Context_Create_HelpFlag_SetsHelpTrue **Scenario**: `Context.Create` is called with `["--help"]`. @@ -50,7 +50,7 @@ no mocking is needed at this level. **Requirement coverage**: Help flag (long form) parsing requirement. -### Context_Create_ShortHelpFlag_H_SetsHelpTrue +##### Context_Create_ShortHelpFlag_H_SetsHelpTrue **Scenario**: `Context.Create` is called with `["-h"]`. @@ -58,7 +58,7 @@ no mocking is needed at this level. **Requirement coverage**: Help flag (-h) parsing requirement. -### Context_Create_ShortHelpFlag_Question_SetsHelpTrue +##### Context_Create_ShortHelpFlag_Question_SetsHelpTrue **Scenario**: `Context.Create` is called with `["-?"]`. @@ -66,7 +66,7 @@ no mocking is needed at this level. **Requirement coverage**: Help flag (-?) parsing requirement. -### Context_Create_SilentFlag_SetsSilentTrue +##### Context_Create_SilentFlag_SetsSilentTrue **Scenario**: `Context.Create` is called with `["--silent"]`. @@ -74,7 +74,7 @@ no mocking is needed at this level. **Requirement coverage**: Silent flag parsing requirement. -### Context_Create_ValidateFlag_SetsValidateTrue +##### Context_Create_ValidateFlag_SetsValidateTrue **Scenario**: `Context.Create` is called with `["--validate"]`. @@ -82,7 +82,7 @@ no mocking is needed at this level. **Requirement coverage**: Validate flag parsing requirement. -### Context_Create_ResultsFlag_SetsResultsFile +##### Context_Create_ResultsFlag_SetsResultsFile **Scenario**: `Context.Create` is called with `["--results", "output.trx"]`. @@ -90,7 +90,7 @@ no mocking is needed at this level. **Requirement coverage**: Results file path parsing requirement. -### Context_Create_ResultAliasFlag_SetsResultsFile +##### Context_Create_ResultAliasFlag_SetsResultsFile **Scenario**: `Context.Create` is called with `["--result", "output.trx"]` (legacy alias). @@ -98,7 +98,7 @@ no mocking is needed at this level. **Requirement coverage**: Results alias flag parsing requirement. -### Context_Create_LogFlag_OpensLogFile +##### Context_Create_LogFlag_OpensLogFile **Scenario**: `Context.Create` is called with `["--log", ".log"]`; `WriteLine` is then called with a test message. @@ -107,7 +107,7 @@ with a test message. **Requirement coverage**: Log file opening and writing requirement. -### Context_Create_UnknownArgument_ThrowsArgumentException +##### Context_Create_UnknownArgument_ThrowsArgumentException **Scenario**: `Context.Create` is called with an unrecognized argument (e.g., `["--unknown"]`). @@ -115,7 +115,7 @@ with a test message. **Requirement coverage**: Unknown argument rejection requirement. -### Context_Create_LogFlag_WithoutValue_ThrowsArgumentException +##### Context_Create_LogFlag_WithoutValue_ThrowsArgumentException **Scenario**: `Context.Create` is called with `["--log"]` (value missing). @@ -123,7 +123,7 @@ with a test message. **Requirement coverage**: Log flag missing-value validation requirement. -### Context_Create_ResultsFlag_WithoutValue_ThrowsArgumentException +##### Context_Create_ResultsFlag_WithoutValue_ThrowsArgumentException **Scenario**: `Context.Create` is called with `["--results"]` (value missing). @@ -131,7 +131,7 @@ with a test message. **Requirement coverage**: Results flag missing-value validation requirement. -### Context_WriteLine_NotSilent_WritesToConsole +##### Context_WriteLine_NotSilent_WritesToConsole **Scenario**: A non-silent `Context` is created and `WriteLine` is called with a test message. @@ -139,7 +139,7 @@ with a test message. **Requirement coverage**: Normal output writing requirement. -### Context_WriteLine_Silent_DoesNotWriteToConsole +##### Context_WriteLine_Silent_DoesNotWriteToConsole **Scenario**: A silent `Context` (created with `["--silent"]`) calls `WriteLine`. @@ -147,7 +147,7 @@ with a test message. **Requirement coverage**: Silent mode suppression requirement. -### Context_WriteError_Silent_DoesNotWriteToConsole +##### Context_WriteError_Silent_DoesNotWriteToConsole **Scenario**: A silent `Context` calls `WriteError`. @@ -155,7 +155,7 @@ with a test message. **Requirement coverage**: Silent mode error suppression requirement. -### Context_WriteError_SetsErrorExitCode +##### Context_WriteError_SetsErrorExitCode **Scenario**: A `Context` calls `WriteError`. @@ -163,7 +163,7 @@ with a test message. **Requirement coverage**: Error exit code setting requirement. -### Context_WriteError_NotSilent_WritesToConsole +##### Context_WriteError_NotSilent_WritesToConsole **Scenario**: A non-silent `Context` calls `WriteError` with a test message. @@ -171,7 +171,7 @@ with a test message. **Requirement coverage**: Error output writing requirement. -### Context_WriteError_WritesToLogFile +##### Context_WriteError_WritesToLogFile **Scenario**: A `Context` created with `["--silent", "--log", ".log"]` calls `WriteError` with a test message. @@ -180,7 +180,7 @@ with a test message. **Requirement coverage**: Error log writing requirement. -### Context_ErrorCount_IncrementsOnEachWriteError +##### Context_ErrorCount_IncrementsOnEachWriteError **Scenario**: `WriteError` is called multiple times on the same `Context`. @@ -188,7 +188,7 @@ with a test message. **Requirement coverage**: Error count tracking requirement. -### Context_Create_DepthFlag_SetsDepth +##### Context_Create_DepthFlag_SetsDepth **Scenario**: `Context.Create` is called with `["--depth", "3"]`. @@ -196,7 +196,7 @@ with a test message. **Requirement coverage**: Depth flag parsing requirement. -### Context_Create_NoArguments_DepthDefaultsToOne +##### Context_Create_NoArguments_DepthDefaultsToOne **Scenario**: `Context.Create` is called with an empty argument array. @@ -204,7 +204,7 @@ with a test message. **Requirement coverage**: Default heading depth requirement. -### Context_Create_DepthFlag_WithoutValue_ThrowsArgumentException +##### Context_Create_DepthFlag_WithoutValue_ThrowsArgumentException **Scenario**: `Context.Create` is called with `["--depth"]` (value missing). @@ -212,7 +212,7 @@ with a test message. **Requirement coverage**: Depth flag missing-value validation requirement. -### Context_Create_DepthFlag_NonNumeric_ThrowsArgumentException +##### Context_Create_DepthFlag_NonNumeric_ThrowsArgumentException **Scenario**: `Context.Create` is called with `["--depth", "abc"]`. @@ -220,7 +220,7 @@ with a test message. **Requirement coverage**: Depth flag non-integer validation requirement. -### Context_Create_DepthFlag_Zero_ThrowsArgumentException +##### Context_Create_DepthFlag_Zero_ThrowsArgumentException **Scenario**: `Context.Create` is called with `["--depth", "0"]` (below minimum of 1). @@ -228,7 +228,7 @@ with a test message. **Requirement coverage**: Depth flag minimum-value validation requirement. -### Context_Create_DepthFlag_AboveSix_ThrowsArgumentException +##### Context_Create_DepthFlag_AboveSix_ThrowsArgumentException **Scenario**: `Context.Create` is called with `["--depth", "7"]` (above maximum of 6). @@ -236,7 +236,7 @@ with a test message. **Requirement coverage**: Depth flag maximum-value validation requirement. -### Context_Create_NoArguments_ConfigFileHasDefaultValue +##### Context_Create_NoArguments_ConfigFileHasDefaultValue **Scenario**: `Context.Create` is called with an empty argument array. @@ -244,7 +244,7 @@ with a test message. **Requirement coverage**: Default config file path requirement. -### Context_Create_NoArguments_FiltersIsEmpty +##### Context_Create_NoArguments_FiltersIsEmpty **Scenario**: `Context.Create` is called with an empty argument array. @@ -252,7 +252,7 @@ with a test message. **Requirement coverage**: Default filters requirement. -### Context_Create_ConfigFlag_SetsConfigFile +##### Context_Create_ConfigFlag_SetsConfigFile **Scenario**: `Context.Create` is called with `["--config", "my.yaml"]`. @@ -260,7 +260,7 @@ with a test message. **Requirement coverage**: Config file flag parsing requirement. -### Context_Create_PositionalArguments_AddedToFilters +##### Context_Create_PositionalArguments_AddedToFilters **Scenario**: `Context.Create` is called with positional arguments (e.g., `["TestA", "TestB"]`). @@ -268,7 +268,7 @@ with a test message. **Requirement coverage**: Test filter parsing requirement. -### Context_Create_MixedArguments_ParsesCorrectly +##### Context_Create_MixedArguments_ParsesCorrectly **Scenario**: `Context.Create` is called with a mix of flags and positional arguments. @@ -276,7 +276,7 @@ with a test message. **Requirement coverage**: Mixed argument parsing requirement. -### Context_Create_UnknownFlagWithDash_ThrowsArgumentException +##### Context_Create_UnknownFlagWithDash_ThrowsArgumentException **Scenario**: `Context.Create` is called with an unrecognized flag starting with `--`. @@ -284,7 +284,7 @@ with a test message. **Requirement coverage**: Unknown flag rejection requirement. -### Context_Create_ConfigFlag_WithoutValue_ThrowsArgumentException +##### Context_Create_ConfigFlag_WithoutValue_ThrowsArgumentException **Scenario**: `Context.Create` is called with `["--config"]` (value missing). @@ -292,7 +292,7 @@ with a test message. **Requirement coverage**: Config flag missing-value validation requirement. -## Requirements Coverage +#### Requirements Coverage | Requirement | Test Scenario | |--------------------------------|-----------------------------------------------------------------| diff --git a/docs/verification/file-assert/configuration/configuration.md b/docs/verification/file-assert/configuration.md similarity index 84% rename from docs/verification/file-assert/configuration/configuration.md rename to docs/verification/file-assert/configuration.md index 2b35b5b..6c40417 100644 --- a/docs/verification/file-assert/configuration/configuration.md +++ b/docs/verification/file-assert/configuration.md @@ -1,26 +1,26 @@ -# Configuration Subsystem Verification +## Configuration Subsystem Verification This document describes the subsystem-level verification design for the `Configuration` subsystem. It defines the integration test approach, subsystem boundary, mocking strategy, and test scenarios that together verify the `Configuration` subsystem requirements. -## Verification Approach +### Verification Approach The `Configuration` subsystem is verified by integration tests defined in `ConfigurationTests.cs`. Each test exercises the full loading and execution pipeline — reading a YAML file, constructing the test hierarchy, and running the resulting configuration — with a real `Context`. -## Dependencies and Mocking Strategy +### Dependencies and Mocking Strategy All collaborators at the subsystem boundary (`Context`, `FileAssertConfig`, `PathHelpers`) use their real implementations. Temporary directories are used for configuration files and test artifacts so that tests remain isolated and leave no permanent file-system side-effects. -## Integration Test Scenarios +### Integration Test Scenarios The following integration test scenarios are defined in `ConfigurationTests.cs`. -### Configuration_LoadYaml_BuildsCompleteTestHierarchy +#### Configuration_LoadYaml_BuildsCompleteTestHierarchy **Scenario**: A YAML configuration file with nested test, file, and rule entries is loaded using `FileAssertConfig.ReadFromFile`. @@ -28,21 +28,21 @@ The following integration test scenarios are defined in `ConfigurationTests.cs`. **Expected**: The complete object hierarchy (tests → files → rules) is correctly constructed with all properties populated. -### Configuration_RunWithFilter_ExecutesOnlyMatchingTests +#### Configuration_RunWithFilter_ExecutesOnlyMatchingTests **Scenario**: A configuration with two tests is loaded. Only one file exists; a filter naming one test is passed to `FileAssertConfig.Run`. **Expected**: Only the named test runs; exit code is 0. -### Configuration_RunWithTagFilter_ExecutesOnlyMatchingTests +#### Configuration_RunWithTagFilter_ExecutesOnlyMatchingTests **Scenario**: A configuration with two tests with different tags is loaded. Only one file exists; a filter naming one tag is passed to `FileAssertConfig.Run`. **Expected**: Only the test matching the tag runs; exit code is 0. -## Requirements Coverage +### Requirements Coverage - **YAML loading and hierarchy construction**: Configuration_LoadYaml_BuildsCompleteTestHierarchy - **Test name filtering**: Configuration_RunWithFilter_ExecutesOnlyMatchingTests diff --git a/docs/verification/file-assert/configuration/file-assert-config.md b/docs/verification/file-assert/configuration/file-assert-config.md index 8f81247..f15a49c 100644 --- a/docs/verification/file-assert/configuration/file-assert-config.md +++ b/docs/verification/file-assert/configuration/file-assert-config.md @@ -1,25 +1,25 @@ -# FileAssertConfig Verification +### FileAssertConfig Verification This document describes the unit-level verification design for the `FileAssertConfig` unit. It defines the test scenarios, dependency usage, and requirement coverage for `Configuration/FileAssertConfig.cs`. -## Verification Approach +#### Verification Approach `FileAssertConfig` is verified with unit tests defined in `FileAssertConfigTests.cs`. Tests supply YAML configuration files in temporary directories and assert on the resulting object state, exit codes, and results files. -## Dependencies +#### Dependencies | Dependency | Usage in Tests | |----------------|--------------------------------------------------------------| | `Context` | Used directly (not mocked) — created with controlled flags. | | `PathHelpers` | Used internally by `FileAssertConfig`; not mocked. | -## Test Scenarios +#### Test Scenarios -### FileAssertConfig_ReadFromFile_ValidFile_ReturnsConfig +##### FileAssertConfig_ReadFromFile_ValidFile_ReturnsConfig **Scenario**: `FileAssertConfig.ReadFromFile` is called with a valid YAML file path. @@ -27,7 +27,7 @@ codes, and results files. **Requirement coverage**: Configuration file reading requirement. -### FileAssertConfig_ReadFromFile_FileNotFound_ThrowsFileNotFoundException +##### FileAssertConfig_ReadFromFile_FileNotFound_ThrowsFileNotFoundException **Scenario**: `FileAssertConfig.ReadFromFile` is called with a path that does not exist. @@ -35,7 +35,7 @@ codes, and results files. **Boundary / error path**: Missing configuration file error path. -### FileAssertConfig_ReadFromFile_NullPath_ThrowsArgumentNullException +##### FileAssertConfig_ReadFromFile_NullPath_ThrowsArgumentNullException **Scenario**: `FileAssertConfig.ReadFromFile` is called with `null` as the path. @@ -43,7 +43,7 @@ codes, and results files. **Boundary / error path**: Null guard on the path parameter. -### FileAssertConfig_Run_WithNoFilter_RunsAllTests +##### FileAssertConfig_Run_WithNoFilter_RunsAllTests **Scenario**: `FileAssertConfig.Run` is called with an empty filter list. @@ -51,7 +51,7 @@ codes, and results files. **Requirement coverage**: Run-all-tests requirement. -### FileAssertConfig_Run_WithMatchingFilter_RunsMatchingTest +##### FileAssertConfig_Run_WithMatchingFilter_RunsMatchingTest **Scenario**: `FileAssertConfig.Run` is called with a filter that matches one test name. @@ -59,7 +59,7 @@ codes, and results files. **Requirement coverage**: Test name filtering requirement. -### FileAssertConfig_Run_WithNonMatchingFilter_SkipsTests +##### FileAssertConfig_Run_WithNonMatchingFilter_SkipsTests **Scenario**: `FileAssertConfig.Run` is called with a filter that matches no tests. @@ -67,7 +67,7 @@ codes, and results files. **Requirement coverage**: Non-matching filter skips all tests requirement. -### FileAssertConfig_Run_WithResultsFile_WritesTrxWithPassedOutcome +##### FileAssertConfig_Run_WithResultsFile_WritesTrxWithPassedOutcome **Scenario**: `FileAssertConfig.Run` is called with a context whose `ResultsFile` points to a temporary `.trx` path, and all assertions pass. @@ -76,7 +76,7 @@ temporary `.trx` path, and all assertions pass. **Requirement coverage**: TRX results output requirement. -### FileAssertConfig_Run_WithResultsFile_WritesJUnitWithFailedOutcome +##### FileAssertConfig_Run_WithResultsFile_WritesJUnitWithFailedOutcome **Scenario**: `FileAssertConfig.Run` is called with a context whose `ResultsFile` points to a temporary `.xml` path, and at least one assertion fails. @@ -85,7 +85,7 @@ temporary `.xml` path, and at least one assertion fails. **Requirement coverage**: JUnit results output requirement. -### FileAssertConfig_ReadFromFile_PdfAssertConfig_ParsesCorrectly +##### FileAssertConfig_ReadFromFile_PdfAssertConfig_ParsesCorrectly **Scenario**: `FileAssertConfig.ReadFromFile` is called with a YAML file that includes PDF assertion configuration (pages, metadata, text rules). @@ -94,7 +94,7 @@ assertion configuration (pages, metadata, text rules). **Requirement coverage**: PDF assertion configuration parsing requirement. -## Requirements Coverage +#### Requirements Coverage - **Configuration file reading**: FileAssertConfig_ReadFromFile_ValidFile_ReturnsConfig - **Missing file error path**: FileAssertConfig_ReadFromFile_FileNotFound_ThrowsFileNotFoundException diff --git a/docs/verification/file-assert/configuration/file-assert-data.md b/docs/verification/file-assert/configuration/file-assert-data.md index 90bfe39..cd86e21 100644 --- a/docs/verification/file-assert/configuration/file-assert-data.md +++ b/docs/verification/file-assert/configuration/file-assert-data.md @@ -1,26 +1,26 @@ -# FileAssertData Verification +### FileAssertData Verification This document describes the unit-level verification design for the `FileAssertData` unit. It defines the verification approach for `Configuration/FileAssertData.cs`. -## Verification Approach +#### Verification Approach `FileAssertData` consists of data-transfer objects used exclusively for YAML deserialization. They carry no logic and are exercised indirectly through `FileAssertConfig.ReadFromFile` in `FileAssertConfigTests.cs`. No dedicated test file exists; all coverage is inherited from the `FileAssertConfig` tests. -## Dependencies +#### Dependencies `FileAssertData` depends only on YamlDotNet deserialization annotations. No mocking is needed. -## Coverage +#### Coverage `FileAssertData` objects are verified indirectly by every `FileAssertConfig_ReadFromFile_*` test scenario in `FileAssertConfigTests.cs` that supplies YAML content. Correct population of all fields confirms the data-transfer objects are correctly annotated and deserialized. -## Requirements Coverage +#### Requirements Coverage All `FileAssertData` requirements are satisfied indirectly by the `FileAssertConfig` test scenarios. See [FileAssertConfig Verification](file-assert-config.md) for details. diff --git a/docs/verification/file-assert/modeling/modeling.md b/docs/verification/file-assert/modeling.md similarity index 83% rename from docs/verification/file-assert/modeling/modeling.md rename to docs/verification/file-assert/modeling.md index 83852e3..d68f31c 100644 --- a/docs/verification/file-assert/modeling/modeling.md +++ b/docs/verification/file-assert/modeling.md @@ -1,53 +1,53 @@ -# Modeling Subsystem Verification +## Modeling Subsystem Verification This document describes the subsystem-level verification design for the `Modeling` subsystem. It defines the integration test approach, subsystem boundary, mocking strategy, and test scenarios that together verify the `Modeling` subsystem requirements. -## Verification Approach +### Verification Approach The `Modeling` subsystem is verified by integration tests defined in `ModelingTests.cs`. Each test exercises the assertion execution pipeline — creating a `FileAssertTest`, resolving file patterns, evaluating constraints, and reporting results through a real `Context`. -## Dependencies and Mocking Strategy +### Dependencies and Mocking Strategy All collaborators at the subsystem boundary use their real implementations. Temporary directories are used for test files so that tests remain isolated. -## Integration Test Scenarios +### Integration Test Scenarios The following integration test scenarios are defined in `ModelingTests.cs`. -### Modeling_ExecuteChain_PassesWhenAllConstraintsMet +#### Modeling_ExecuteChain_PassesWhenAllConstraintsMet **Scenario**: A `FileAssertTest` is created with a configuration where all file pattern, count, and content constraints are satisfied by the test files in a temporary directory. **Expected**: No errors are written to the context; exit code is 0. -### Modeling_ExecuteChain_ReportsFailuresThroughContext +#### Modeling_ExecuteChain_ReportsFailuresThroughContext **Scenario**: A `FileAssertTest` is created with a configuration where at least one constraint is not satisfied. **Expected**: Errors are written to the context; exit code is non-zero. -### Modeling_FileTypeParsing_InvalidXml_ReportsParseError +#### Modeling_FileTypeParsing_InvalidXml_ReportsParseError **Scenario**: A `FileAssertFile` with an XML assertion is configured to evaluate a file that is not valid XML. **Expected**: An error is written to the context; exit code is non-zero. -### Modeling_QueryAssertions_XmlQueryMeetsCount_NoError +#### Modeling_QueryAssertions_XmlQueryMeetsCount_NoError **Scenario**: A `FileAssertFile` with an XML XPath assertion is configured and a valid XML file satisfying the query and count constraints is provided. **Expected**: No errors are written to the context; exit code is 0. -## Requirements Coverage +### Requirements Coverage - **Constraint evaluation**: Modeling_ExecuteChain_PassesWhenAllConstraintsMet, Modeling_ExecuteChain_ReportsFailuresThroughContext diff --git a/docs/verification/file-assert/modeling/file-assert-file.md b/docs/verification/file-assert/modeling/file-assert-file.md index a9f3d6d..b818e98 100644 --- a/docs/verification/file-assert/modeling/file-assert-file.md +++ b/docs/verification/file-assert/modeling/file-assert-file.md @@ -1,24 +1,24 @@ -# FileAssertFile Verification +### FileAssertFile Verification This document describes the unit-level verification design for the `FileAssertFile` unit. It defines the test scenarios, dependency usage, and requirement coverage for `Modeling/FileAssertFile.cs`. -## Verification Approach +#### Verification Approach `FileAssertFile` is verified with unit tests defined in `FileAssertFileTests.cs`. Tests create temporary directories with controlled file sets and assert on constraint evaluation and error reporting behavior. -## Dependencies +#### Dependencies | Dependency | Usage in Tests | |--------------|-------------------------------------------------------------| | `Context` | Used directly (not mocked) — created with controlled flags. | -## Test Scenarios +#### Test Scenarios -### FileAssertFile_Create_ValidData_CreatesFile +##### FileAssertFile_Create_ValidData_CreatesFile **Scenario**: `FileAssertFile.Create` is called with valid data containing a pattern. @@ -26,7 +26,7 @@ reporting behavior. **Requirement coverage**: File entry creation requirement. -### FileAssertFile_Create_NullData_ThrowsArgumentNullException +##### FileAssertFile_Create_NullData_ThrowsArgumentNullException **Scenario**: `FileAssertFile.Create` is called with `null` data. @@ -34,7 +34,7 @@ reporting behavior. **Boundary / error path**: Null data guard. -### FileAssertFile_Create_NullPattern_ThrowsInvalidOperationException +##### FileAssertFile_Create_NullPattern_ThrowsInvalidOperationException **Scenario**: `FileAssertFile.Create` is called with data whose `Pattern` is `null`. @@ -42,7 +42,7 @@ reporting behavior. **Boundary / error path**: Null pattern validation. -### FileAssertFile_Create_BlankPattern_ThrowsInvalidOperationException +##### FileAssertFile_Create_BlankPattern_ThrowsInvalidOperationException **Scenario**: `FileAssertFile.Create` is called with data whose `Pattern` is blank. @@ -50,82 +50,82 @@ reporting behavior. **Boundary / error path**: Blank pattern validation. -### FileAssertFile_Run_NoMatchingFiles_NoConstraints_NoError +##### FileAssertFile_Run_NoMatchingFiles_NoConstraints_NoError **Scenario**: `FileAssertFile.Run` is called with a pattern that matches no files and no count constraints are specified. **Expected**: No errors are written to the context; exit code is 0. -### FileAssertFile_Run_WithMatchingFiles_NoConstraints_NoError +##### FileAssertFile_Run_WithMatchingFiles_NoConstraints_NoError **Scenario**: `FileAssertFile.Run` is called with a pattern that matches one or more files and no constraints are specified. **Expected**: No errors are written to the context; exit code is 0. -### FileAssertFile_Run_TooFewFiles_WritesError +##### FileAssertFile_Run_TooFewFiles_WritesError **Scenario**: `FileAssertFile.Run` is called with a `min` constraint but fewer than the required files match the pattern. **Expected**: An error is written to the context; exit code is non-zero. -### FileAssertFile_Run_TooManyFiles_WritesError +##### FileAssertFile_Run_TooManyFiles_WritesError **Scenario**: `FileAssertFile.Run` is called with a `max` constraint but more files than allowed match the pattern. **Expected**: An error is written to the context; exit code is non-zero. -### FileAssertFile_Run_WithContentRule_ContentContainsValue_NoError +##### FileAssertFile_Run_WithContentRule_ContentContainsValue_NoError **Scenario**: `FileAssertFile.Run` is called with a `contains` text rule; the matching file contains the expected text. **Expected**: No errors are written to the context; exit code is 0. -### FileAssertFile_Run_WithContentRule_ContentMissingValue_WritesError +##### FileAssertFile_Run_WithContentRule_ContentMissingValue_WritesError **Scenario**: `FileAssertFile.Run` is called with a `contains` text rule; the matching file does not contain the expected text. **Expected**: An error is written to the context; exit code is non-zero. -### FileAssertFile_Run_WrongCount_WritesError +##### FileAssertFile_Run_WrongCount_WritesError **Scenario**: `FileAssertFile.Run` is called with an exact `count` constraint but the actual file count differs. **Expected**: An error is written to the context; exit code is non-zero. -### FileAssertFile_Run_TooSmall_WritesError +##### FileAssertFile_Run_TooSmall_WritesError **Scenario**: `FileAssertFile.Run` is called with a minimum file size constraint; the matching file is smaller than the minimum. **Expected**: An error is written to the context; exit code is non-zero. -### FileAssertFile_Run_TooLarge_WritesError +##### FileAssertFile_Run_TooLarge_WritesError **Scenario**: `FileAssertFile.Run` is called with a maximum file size constraint; the matching file is larger than the maximum. **Expected**: An error is written to the context; exit code is non-zero. -### FileAssertFile_Run_MultipleFiles_MultipleViolateSizeConstraints_WritesErrorForEachViolation +##### FileAssertFile_Run_MultipleFiles_MultipleViolateSizeConstraints_WritesErrorForEachViolation **Scenario**: Multiple files match the pattern; more than one violates the size constraints. **Expected**: A separate error is written for each violation; exit code is non-zero. -### FileAssertFile_Run_MultipleFiles_MultipleFailContentRule_WritesErrorForEachViolation +##### FileAssertFile_Run_MultipleFiles_MultipleFailContentRule_WritesErrorForEachViolation **Scenario**: Multiple files match the pattern; more than one fails a content rule. **Expected**: A separate error is written for each violation; exit code is non-zero. -## Requirements Coverage +#### Requirements Coverage - **File entry creation**: FileAssertFile_Create_ValidData_CreatesFile - **Null/blank pattern guards**: FileAssertFile_Create_NullData_ThrowsArgumentNullException, diff --git a/docs/verification/file-assert/modeling/file-assert-html-assert.md b/docs/verification/file-assert/modeling/file-assert-html-assert.md index bcbca5d..0c9b480 100644 --- a/docs/verification/file-assert/modeling/file-assert-html-assert.md +++ b/docs/verification/file-assert/modeling/file-assert-html-assert.md @@ -1,24 +1,24 @@ -# FileAssertHtmlAssert Verification +### FileAssertHtmlAssert Verification This document describes the unit-level verification design for the `FileAssertHtmlAssert` unit. It defines the test scenarios, dependency usage, and requirement coverage for `Modeling/FileAssertHtmlAssert.cs`. -## Verification Approach +#### Verification Approach `FileAssertHtmlAssert` is verified with unit tests defined in `FileAssertHtmlAssertTests.cs`. Tests create temporary HTML files with controlled content and assert on XPath query results, count constraints, and text matching. -## Dependencies +#### Dependencies | Dependency | Usage in Tests | |------------|-------------------------------------------------------------| | `Context` | Used directly (not mocked) — created with controlled flags. | -## Test Scenarios +#### Test Scenarios -### FileAssertHtmlAssert_Create_ValidData_CreatesHtmlAssert +##### FileAssertHtmlAssert_Create_ValidData_CreatesHtmlAssert **Scenario**: `FileAssertHtmlAssert.Create` is called with valid data. @@ -26,7 +26,7 @@ constraints, and text matching. **Requirement coverage**: HTML assert creation requirement. -### FileAssertHtmlAssert_Create_NullData_ThrowsArgumentNullException +##### FileAssertHtmlAssert_Create_NullData_ThrowsArgumentNullException **Scenario**: `FileAssertHtmlAssert.Create` is called with `null` data. @@ -34,7 +34,7 @@ constraints, and text matching. **Boundary / error path**: Null data guard. -### FileAssertHtmlAssert_Run_ExactCount_Matches_NoError +##### FileAssertHtmlAssert_Run_ExactCount_Matches_NoError **Scenario**: `FileAssertHtmlAssert.Run` is called with an exact count assertion and the XPath query returns exactly the expected number of elements. @@ -43,7 +43,7 @@ query returns exactly the expected number of elements. **Requirement coverage**: Exact count match requirement. -### FileAssertHtmlAssert_Run_ExactCount_Mismatch_WritesError +##### FileAssertHtmlAssert_Run_ExactCount_Mismatch_WritesError **Scenario**: `FileAssertHtmlAssert.Run` is called with an exact count assertion and the XPath query returns a different number of elements. @@ -52,7 +52,7 @@ query returns a different number of elements. **Requirement coverage**: Exact count mismatch requirement. -### FileAssertHtmlAssert_Run_MinMaxCount_WithinBounds_NoError +##### FileAssertHtmlAssert_Run_MinMaxCount_WithinBounds_NoError **Scenario**: `FileAssertHtmlAssert.Run` is called with min/max count constraints and the XPath query result count is within bounds. @@ -61,7 +61,7 @@ query result count is within bounds. **Requirement coverage**: Min/max count constraint pass requirement. -### FileAssertHtmlAssert_Run_NonExistentFile_WritesError +##### FileAssertHtmlAssert_Run_NonExistentFile_WritesError **Scenario**: `FileAssertHtmlAssert.Run` is called with a path that does not exist. @@ -69,7 +69,7 @@ query result count is within bounds. **Boundary / error path**: Missing file error path. -### FileAssertHtmlAssert_Run_InvalidXPathQuery_WritesError +##### FileAssertHtmlAssert_Run_InvalidXPathQuery_WritesError **Scenario**: `FileAssertHtmlAssert.Run` is called with a malformed XPath query string. @@ -77,7 +77,7 @@ query result count is within bounds. **Boundary / error path**: Invalid XPath query error path. -### FileAssertHtmlAssert_Run_XPathExactTextMatch_Matches_NoError +##### FileAssertHtmlAssert_Run_XPathExactTextMatch_Matches_NoError **Scenario**: `FileAssertHtmlAssert.Run` is called with an exact-text assertion and the XPath result matches exactly. @@ -86,7 +86,7 @@ result matches exactly. **Requirement coverage**: XPath exact text match pass requirement. -### FileAssertHtmlAssert_Run_XPathExactTextMatch_NoMatch_WritesError +##### FileAssertHtmlAssert_Run_XPathExactTextMatch_NoMatch_WritesError **Scenario**: `FileAssertHtmlAssert.Run` is called with an exact-text assertion but the XPath result does not match. @@ -95,7 +95,7 @@ result does not match. **Requirement coverage**: XPath exact text match fail requirement. -### FileAssertHtmlAssert_Run_XPathContainsText_Matches_NoError +##### FileAssertHtmlAssert_Run_XPathContainsText_Matches_NoError **Scenario**: `FileAssertHtmlAssert.Run` is called with a `contains` text assertion and the XPath result contains the expected value. @@ -104,7 +104,7 @@ result contains the expected value. **Requirement coverage**: XPath contains text pass requirement. -### FileAssertHtmlAssert_Run_XPathContainsText_NoMatch_WritesError +##### FileAssertHtmlAssert_Run_XPathContainsText_NoMatch_WritesError **Scenario**: `FileAssertHtmlAssert.Run` is called with a `contains` text assertion but the XPath result does not contain the expected value. @@ -113,7 +113,7 @@ result does not contain the expected value. **Requirement coverage**: XPath contains text fail requirement. -## Requirements Coverage +#### Requirements Coverage - **HTML assert creation**: FileAssertHtmlAssert_Create_ValidData_CreatesHtmlAssert - **Null guard**: FileAssertHtmlAssert_Create_NullData_ThrowsArgumentNullException diff --git a/docs/verification/file-assert/modeling/file-assert-json-assert.md b/docs/verification/file-assert/modeling/file-assert-json-assert.md index 9b4d5ed..4132098 100644 --- a/docs/verification/file-assert/modeling/file-assert-json-assert.md +++ b/docs/verification/file-assert/modeling/file-assert-json-assert.md @@ -1,24 +1,24 @@ -# FileAssertJsonAssert Verification +### FileAssertJsonAssert Verification This document describes the unit-level verification design for the `FileAssertJsonAssert` unit. It defines the test scenarios, dependency usage, and requirement coverage for `Modeling/FileAssertJsonAssert.cs`. -## Verification Approach +#### Verification Approach `FileAssertJsonAssert` is verified with unit tests defined in `FileAssertJsonAssertTests.cs`. Tests create temporary JSON files with controlled content and assert on path query results and count constraints. -## Dependencies +#### Dependencies | Dependency | Usage in Tests | |------------|-------------------------------------------------------------| | `Context` | Used directly (not mocked) — created with controlled flags. | -## Test Scenarios +#### Test Scenarios -### FileAssertJsonAssert_Create_ValidData_CreatesJsonAssert +##### FileAssertJsonAssert_Create_ValidData_CreatesJsonAssert **Scenario**: `FileAssertJsonAssert.Create` is called with valid data. @@ -26,7 +26,7 @@ constraints. **Requirement coverage**: JSON assert creation requirement. -### FileAssertJsonAssert_Create_NullData_ThrowsArgumentNullException +##### FileAssertJsonAssert_Create_NullData_ThrowsArgumentNullException **Scenario**: `FileAssertJsonAssert.Create` is called with `null` data. @@ -34,7 +34,7 @@ constraints. **Boundary / error path**: Null data guard. -### FileAssertJsonAssert_Create_EmptyQuery_ThrowsInvalidOperationException +##### FileAssertJsonAssert_Create_EmptyQuery_ThrowsInvalidOperationException **Scenario**: `FileAssertJsonAssert.Create` is called with data whose query is empty. @@ -42,7 +42,7 @@ constraints. **Boundary / error path**: Empty query validation. -### FileAssertJsonAssert_Create_TrailingDotQuery_ThrowsInvalidOperationException +##### FileAssertJsonAssert_Create_TrailingDotQuery_ThrowsInvalidOperationException **Scenario**: `FileAssertJsonAssert.Create` is called with a query that ends with a dot. @@ -50,7 +50,7 @@ constraints. **Boundary / error path**: Malformed query validation. -### FileAssertJsonAssert_Create_LeadingDotQuery_ThrowsInvalidOperationException +##### FileAssertJsonAssert_Create_LeadingDotQuery_ThrowsInvalidOperationException **Scenario**: `FileAssertJsonAssert.Create` is called with a query that starts with a dot. @@ -58,7 +58,7 @@ constraints. **Boundary / error path**: Malformed query validation. -### FileAssertJsonAssert_Create_ConsecutiveDotsQuery_ThrowsInvalidOperationException +##### FileAssertJsonAssert_Create_ConsecutiveDotsQuery_ThrowsInvalidOperationException **Scenario**: `FileAssertJsonAssert.Create` is called with a query containing consecutive dots. @@ -66,7 +66,7 @@ constraints. **Boundary / error path**: Malformed query validation. -### FileAssertJsonAssert_Run_InvalidFile_WritesError +##### FileAssertJsonAssert_Run_InvalidFile_WritesError **Scenario**: `FileAssertJsonAssert.Run` is called with a path that is not valid JSON. @@ -74,7 +74,7 @@ constraints. **Boundary / error path**: Invalid JSON file error path. -### FileAssertJsonAssert_Run_ArrayCount_Matches_NoError +##### FileAssertJsonAssert_Run_ArrayCount_Matches_NoError **Scenario**: `FileAssertJsonAssert.Run` is called with an exact count assertion and the path query returns a JSON array with exactly the expected number of elements. @@ -83,7 +83,7 @@ query returns a JSON array with exactly the expected number of elements. **Requirement coverage**: Array count match requirement. -### FileAssertJsonAssert_Run_ArrayCount_Mismatch_WritesError +##### FileAssertJsonAssert_Run_ArrayCount_Mismatch_WritesError **Scenario**: `FileAssertJsonAssert.Run` is called with an exact count assertion and the path query returns a different number of elements. @@ -92,7 +92,7 @@ query returns a different number of elements. **Requirement coverage**: Array count mismatch requirement. -### FileAssertJsonAssert_Run_MinMaxCount_WithinBounds_NoError +##### FileAssertJsonAssert_Run_MinMaxCount_WithinBounds_NoError **Scenario**: `FileAssertJsonAssert.Run` is called with min/max count constraints and the result count is within bounds. @@ -101,7 +101,7 @@ count is within bounds. **Requirement coverage**: Min/max count constraint pass requirement. -### FileAssertJsonAssert_Run_ScalarValue_CountsAsOne_NoError +##### FileAssertJsonAssert_Run_ScalarValue_CountsAsOne_NoError **Scenario**: `FileAssertJsonAssert.Run` is called on a path that resolves to a scalar JSON value; a count of 1 is asserted. @@ -110,7 +110,7 @@ a count of 1 is asserted. **Requirement coverage**: Scalar value counts as one requirement. -### FileAssertJsonAssert_Run_MinCount_BelowMinimum_WritesError +##### FileAssertJsonAssert_Run_MinCount_BelowMinimum_WritesError **Scenario**: `FileAssertJsonAssert.Run` is called with a minimum count constraint that is not satisfied. @@ -119,7 +119,7 @@ satisfied. **Requirement coverage**: Minimum count constraint requirement. -### FileAssertJsonAssert_Run_MaxCount_ExceedsMaximum_WritesError +##### FileAssertJsonAssert_Run_MaxCount_ExceedsMaximum_WritesError **Scenario**: `FileAssertJsonAssert.Run` is called with a maximum count constraint that is exceeded. @@ -128,7 +128,7 @@ exceeded. **Requirement coverage**: Maximum count constraint requirement. -## Requirements Coverage +#### Requirements Coverage - **JSON assert creation**: FileAssertJsonAssert_Create_ValidData_CreatesJsonAssert - **Null guard**: FileAssertJsonAssert_Create_NullData_ThrowsArgumentNullException diff --git a/docs/verification/file-assert/modeling/file-assert-pdf-assert.md b/docs/verification/file-assert/modeling/file-assert-pdf-assert.md index e356aa2..3abc879 100644 --- a/docs/verification/file-assert/modeling/file-assert-pdf-assert.md +++ b/docs/verification/file-assert/modeling/file-assert-pdf-assert.md @@ -1,24 +1,24 @@ -# FileAssertPdfAssert Verification +### FileAssertPdfAssert Verification This document describes the unit-level verification design for the `FileAssertPdfAssert` unit. It defines the test scenarios, dependency usage, and requirement coverage for `Modeling/FileAssertPdfAssert.cs`. -## Verification Approach +#### Verification Approach `FileAssertPdfAssert` is verified with unit tests defined in `FileAssertPdfAssertTests.cs`. Tests use PDF files in test fixtures and assert on page-count constraints, metadata field assertions, and text content assertions. -## Dependencies +#### Dependencies | Dependency | Usage in Tests | |------------|-------------------------------------------------------------| | `Context` | Used directly (not mocked) — created with controlled flags. | -## Test Scenarios +#### Test Scenarios -### FileAssertPdfAssert_Create_ValidData_CreatesPdfAssert +##### FileAssertPdfAssert_Create_ValidData_CreatesPdfAssert **Scenario**: `FileAssertPdfAssert.Create` is called with valid data. @@ -26,7 +26,7 @@ and text content assertions. **Requirement coverage**: PDF assert creation requirement. -### FileAssertPdfAssert_Create_NullData_ThrowsArgumentNullException +##### FileAssertPdfAssert_Create_NullData_ThrowsArgumentNullException **Scenario**: `FileAssertPdfAssert.Create` is called with `null` data. @@ -34,7 +34,7 @@ and text content assertions. **Boundary / error path**: Null data guard. -### FileAssertPdfAssert_Run_InvalidFile_WritesError +##### FileAssertPdfAssert_Run_InvalidFile_WritesError **Scenario**: `FileAssertPdfAssert.Run` is called with a path that is not a valid PDF file. @@ -42,7 +42,7 @@ and text content assertions. **Boundary / error path**: Invalid PDF file error path. -### FileAssertPdfAssert_Run_ValidPdf_PageCountSatisfied_NoError +##### FileAssertPdfAssert_Run_ValidPdf_PageCountSatisfied_NoError **Scenario**: `FileAssertPdfAssert.Run` is called on a valid PDF that meets the page count constraints. @@ -51,7 +51,7 @@ constraints. **Requirement coverage**: Page count constraint pass requirement. -### FileAssertPdfAssert_Run_ValidPdf_TooFewPages_WritesError +##### FileAssertPdfAssert_Run_ValidPdf_TooFewPages_WritesError **Scenario**: `FileAssertPdfAssert.Run` is called on a valid PDF with fewer pages than the minimum. @@ -59,7 +59,7 @@ constraints. **Requirement coverage**: Minimum page count constraint requirement. -### FileAssertPdfAssert_Run_ValidPdf_TooManyPages_WritesError +##### FileAssertPdfAssert_Run_ValidPdf_TooManyPages_WritesError **Scenario**: `FileAssertPdfAssert.Run` is called on a valid PDF with more pages than the maximum. @@ -67,7 +67,7 @@ constraints. **Requirement coverage**: Maximum page count constraint requirement. -### FileAssertPdfAssert_Run_MetadataContainsRule_FieldMissing_WritesError +##### FileAssertPdfAssert_Run_MetadataContainsRule_FieldMissing_WritesError **Scenario**: `FileAssertPdfAssert.Run` is called with a metadata `contains` rule on a field that does not exist in the PDF metadata. @@ -76,7 +76,7 @@ does not exist in the PDF metadata. **Requirement coverage**: Metadata field missing error requirement. -### FileAssertPdfAssert_Run_MetadataContainsRule_TitleMatches_NoError +##### FileAssertPdfAssert_Run_MetadataContainsRule_TitleMatches_NoError **Scenario**: `FileAssertPdfAssert.Run` is called with a metadata `contains` rule on the Title field, and the Title contains the expected value. @@ -85,7 +85,7 @@ field, and the Title contains the expected value. **Requirement coverage**: Metadata title match requirement. -### FileAssertPdfAssert_Run_MetadataContainsRule_AuthorField_NoError +##### FileAssertPdfAssert_Run_MetadataContainsRule_AuthorField_NoError **Scenario**: `FileAssertPdfAssert.Run` is called with a metadata `contains` rule on the Author field, and the Author contains the expected value. @@ -94,7 +94,7 @@ field, and the Author contains the expected value. **Requirement coverage**: Metadata author match requirement. -### FileAssertPdfAssert_Run_MetadataMatchesRule_Matches_NoError +##### FileAssertPdfAssert_Run_MetadataMatchesRule_Matches_NoError **Scenario**: `FileAssertPdfAssert.Run` is called with a metadata `matches` regex rule that matches the field value. @@ -103,7 +103,7 @@ matches the field value. **Requirement coverage**: Metadata regex match pass requirement. -### FileAssertPdfAssert_Run_MetadataMatchesRule_NoMatch_WritesError +##### FileAssertPdfAssert_Run_MetadataMatchesRule_NoMatch_WritesError **Scenario**: `FileAssertPdfAssert.Run` is called with a metadata `matches` regex rule that does not match the field value. @@ -112,7 +112,7 @@ not match the field value. **Requirement coverage**: Metadata regex match fail requirement. -### FileAssertPdfAssert_Run_TextContainsRule_ContentPresent_NoError +##### FileAssertPdfAssert_Run_TextContainsRule_ContentPresent_NoError **Scenario**: `FileAssertPdfAssert.Run` is called with a text `contains` rule and the PDF text contains the expected value. @@ -121,7 +121,7 @@ contains the expected value. **Requirement coverage**: PDF text content assertion pass requirement. -### FileAssertPdfAssert_Run_TextRule_ContentMissing_WritesError +##### FileAssertPdfAssert_Run_TextRule_ContentMissing_WritesError **Scenario**: `FileAssertPdfAssert.Run` is called with a text rule and the PDF text does not satisfy the rule. @@ -130,7 +130,7 @@ satisfy the rule. **Requirement coverage**: PDF text content assertion fail requirement. -### FileAssertPdfAssert_Run_TextMatchesRule_PatternMatches_NoError +##### FileAssertPdfAssert_Run_TextMatchesRule_PatternMatches_NoError **Scenario**: `FileAssertPdfAssert.Run` is called with a text `matches` regex rule and the PDF text matches the pattern. @@ -139,7 +139,7 @@ text matches the pattern. **Requirement coverage**: PDF text regex match requirement. -## Requirements Coverage +#### Requirements Coverage - **PDF assert creation**: FileAssertPdfAssert_Create_ValidData_CreatesPdfAssert - **Null guard**: FileAssertPdfAssert_Create_NullData_ThrowsArgumentNullException diff --git a/docs/verification/file-assert/modeling/file-assert-rule.md b/docs/verification/file-assert/modeling/file-assert-rule.md index 8cf04eb..26d30f7 100644 --- a/docs/verification/file-assert/modeling/file-assert-rule.md +++ b/docs/verification/file-assert/modeling/file-assert-rule.md @@ -1,24 +1,24 @@ -# FileAssertRule Verification +### FileAssertRule Verification This document describes the unit-level verification design for the `FileAssertRule` unit. It defines the test scenarios, dependency usage, and requirement coverage for `Modeling/FileAssertRule.cs`. -## Verification Approach +#### Verification Approach `FileAssertRule` is verified with unit tests defined in `FileAssertRuleTests.cs`. Tests supply controlled rule data objects and string content, asserting on rule type creation, application results, and error reporting. -## Dependencies +#### Dependencies | Dependency | Usage in Tests | |------------|-------------------------------------------------------------| | `Context` | Used directly (not mocked) — created with controlled flags. | -## Test Scenarios +#### Test Scenarios -### FileAssertRule_Create_WithContains_ReturnsContainsRule +##### FileAssertRule_Create_WithContains_ReturnsContainsRule **Scenario**: `FileAssertRule.Create` is called with data specifying a `contains` rule. @@ -26,7 +26,7 @@ results, and error reporting. **Requirement coverage**: Contains rule creation requirement. -### FileAssertRule_Create_WithMatches_ReturnsMatchesRule +##### FileAssertRule_Create_WithMatches_ReturnsMatchesRule **Scenario**: `FileAssertRule.Create` is called with data specifying a `matches` regex rule. @@ -34,7 +34,7 @@ results, and error reporting. **Requirement coverage**: Regex matches rule creation requirement. -### FileAssertRule_Create_WithDoesNotContain_ReturnsDoesNotContainRule +##### FileAssertRule_Create_WithDoesNotContain_ReturnsDoesNotContainRule **Scenario**: `FileAssertRule.Create` is called with data specifying a `does-not-contain` rule. @@ -42,7 +42,7 @@ results, and error reporting. **Requirement coverage**: Does-not-contain rule creation requirement. -### FileAssertRule_Create_WithDoesNotContainRegex_ReturnsDoesNotMatchRule +##### FileAssertRule_Create_WithDoesNotContainRegex_ReturnsDoesNotMatchRule **Scenario**: `FileAssertRule.Create` is called with data specifying a `does-not-match` regex rule. @@ -50,7 +50,7 @@ results, and error reporting. **Requirement coverage**: Does-not-match rule creation requirement. -### FileAssertRule_Create_WithNoType_ThrowsInvalidOperationException +##### FileAssertRule_Create_WithNoType_ThrowsInvalidOperationException **Scenario**: `FileAssertRule.Create` is called with data that specifies no rule type. @@ -58,7 +58,7 @@ results, and error reporting. **Boundary / error path**: Unknown rule type validation. -### FileAssertRule_Create_WithNullData_ThrowsArgumentNullException +##### FileAssertRule_Create_WithNullData_ThrowsArgumentNullException **Scenario**: `FileAssertRule.Create` is called with `null` data. @@ -66,7 +66,7 @@ results, and error reporting. **Boundary / error path**: Null data guard. -### FileAssertContainsRule_Apply_ContentContainsValue_NoError +##### FileAssertContainsRule_Apply_ContentContainsValue_NoError **Scenario**: A `ContainsRule` is applied to content that contains the expected value. @@ -74,7 +74,7 @@ results, and error reporting. **Requirement coverage**: Contains rule pass requirement. -### FileAssertContainsRule_Apply_ContentMissingValue_WritesError +##### FileAssertContainsRule_Apply_ContentMissingValue_WritesError **Scenario**: A `ContainsRule` is applied to content that does not contain the expected value. @@ -82,7 +82,7 @@ results, and error reporting. **Requirement coverage**: Contains rule fail requirement. -### FileAssertMatchesRule_Apply_ContentMatchesPattern_NoError +##### FileAssertMatchesRule_Apply_ContentMatchesPattern_NoError **Scenario**: A `MatchesRule` is applied to content that matches the regex pattern. @@ -90,7 +90,7 @@ results, and error reporting. **Requirement coverage**: Regex match pass requirement. -### FileAssertMatchesRule_Apply_ContentDoesNotMatchPattern_WritesError +##### FileAssertMatchesRule_Apply_ContentDoesNotMatchPattern_WritesError **Scenario**: A `MatchesRule` is applied to content that does not match the regex pattern. @@ -98,7 +98,7 @@ results, and error reporting. **Requirement coverage**: Regex match fail requirement. -### FileAssertDoesNotContainRule_Apply_ContentContainsValue_WritesError +##### FileAssertDoesNotContainRule_Apply_ContentContainsValue_WritesError **Scenario**: A `DoesNotContainRule` is applied to content that contains the forbidden value. @@ -106,7 +106,7 @@ results, and error reporting. **Requirement coverage**: Does-not-contain fail requirement. -### FileAssertDoesNotContainRule_Apply_ContentMissingValue_NoError +##### FileAssertDoesNotContainRule_Apply_ContentMissingValue_NoError **Scenario**: A `DoesNotContainRule` is applied to content that does not contain the forbidden value. @@ -114,7 +114,7 @@ results, and error reporting. **Requirement coverage**: Does-not-contain pass requirement. -### FileAssertDoesNotMatchRule_Apply_ContentMatchesPattern_WritesError +##### FileAssertDoesNotMatchRule_Apply_ContentMatchesPattern_WritesError **Scenario**: A `DoesNotMatchRule` is applied to content that matches the forbidden regex pattern. @@ -122,7 +122,7 @@ results, and error reporting. **Requirement coverage**: Does-not-match fail requirement. -### FileAssertDoesNotMatchRule_Apply_ContentDoesNotMatchPattern_NoError +##### FileAssertDoesNotMatchRule_Apply_ContentDoesNotMatchPattern_NoError **Scenario**: A `DoesNotMatchRule` is applied to content that does not match the forbidden pattern. @@ -130,7 +130,7 @@ results, and error reporting. **Requirement coverage**: Does-not-match pass requirement. -## Requirements Coverage +#### Requirements Coverage - **Contains rule**: FileAssertRule_Create_WithContains_ReturnsContainsRule, FileAssertContainsRule_Apply_ContentContainsValue_NoError, diff --git a/docs/verification/file-assert/modeling/file-assert-test.md b/docs/verification/file-assert/modeling/file-assert-test.md index 7d06cc4..0ccaa06 100644 --- a/docs/verification/file-assert/modeling/file-assert-test.md +++ b/docs/verification/file-assert/modeling/file-assert-test.md @@ -1,25 +1,25 @@ -# FileAssertTest Verification +### FileAssertTest Verification This document describes the unit-level verification design for the `FileAssertTest` unit. It defines the test scenarios, dependency usage, and requirement coverage for `Modeling/FileAssertTest.cs`. -## Verification Approach +#### Verification Approach `FileAssertTest` is verified with unit tests defined in `FileAssertTestTests.cs`. Tests supply controlled `FileAssertTestData` instances and assert on filter matching behavior, creation validation, and execution delegation. -## Dependencies +#### Dependencies | Dependency | Usage in Tests | |-------------------|----------------------------------------------------------------------| | `Context` | Used directly (not mocked) — created with controlled flags. | | `FileAssertFile` | Used directly (not mocked) — called through `FileAssertTest.Run`. | -## Test Scenarios +#### Test Scenarios -### FileAssertTest_Create_ValidData_CreatesTest +##### FileAssertTest_Create_ValidData_CreatesTest **Scenario**: `FileAssertTest.Create` is called with valid data containing a name and files list. @@ -27,7 +27,7 @@ validation, and execution delegation. **Requirement coverage**: Test creation requirement. -### FileAssertTest_Create_NullData_ThrowsArgumentNullException +##### FileAssertTest_Create_NullData_ThrowsArgumentNullException **Scenario**: `FileAssertTest.Create` is called with `null` data. @@ -35,7 +35,7 @@ validation, and execution delegation. **Boundary / error path**: Null guard on data. -### FileAssertTest_Create_NullName_ThrowsInvalidOperationException +##### FileAssertTest_Create_NullName_ThrowsInvalidOperationException **Scenario**: `FileAssertTest.Create` is called with data whose `Name` property is `null`. @@ -43,7 +43,7 @@ validation, and execution delegation. **Boundary / error path**: Null name validation. -### FileAssertTest_Create_WhitespaceName_ThrowsInvalidOperationException +##### FileAssertTest_Create_WhitespaceName_ThrowsInvalidOperationException **Scenario**: `FileAssertTest.Create` is called with data whose `Name` property is whitespace. @@ -51,7 +51,7 @@ validation, and execution delegation. **Boundary / error path**: Whitespace name validation. -### FileAssertTest_MatchesFilter_EmptyFilters_ReturnsTrue +##### FileAssertTest_MatchesFilter_EmptyFilters_ReturnsTrue **Scenario**: `FileAssertTest.MatchesFilter` is called with an empty filter list. @@ -59,7 +59,7 @@ validation, and execution delegation. **Requirement coverage**: Empty filter match requirement. -### FileAssertTest_MatchesFilter_MatchingName_ReturnsTrue +##### FileAssertTest_MatchesFilter_MatchingName_ReturnsTrue **Scenario**: `FileAssertTest.MatchesFilter` is called with a filter list containing the test name. @@ -67,7 +67,7 @@ validation, and execution delegation. **Requirement coverage**: Name-based filter match requirement. -### FileAssertTest_MatchesFilter_MatchingTag_ReturnsTrue +##### FileAssertTest_MatchesFilter_MatchingTag_ReturnsTrue **Scenario**: `FileAssertTest.MatchesFilter` is called with a filter list containing one of the test's tags. @@ -76,7 +76,7 @@ test's tags. **Requirement coverage**: Tag-based filter match requirement. -### FileAssertTest_MatchesFilter_NonMatchingFilter_ReturnsFalse +##### FileAssertTest_MatchesFilter_NonMatchingFilter_ReturnsFalse **Scenario**: `FileAssertTest.MatchesFilter` is called with a filter list containing neither the test name nor any of its tags. @@ -85,7 +85,7 @@ test name nor any of its tags. **Requirement coverage**: Non-matching filter requirement. -### FileAssertTest_MatchesFilter_CaseInsensitiveName_ReturnsTrue +##### FileAssertTest_MatchesFilter_CaseInsensitiveName_ReturnsTrue **Scenario**: `FileAssertTest.MatchesFilter` is called with a filter that differs only in case from the test name. @@ -94,7 +94,7 @@ from the test name. **Requirement coverage**: Case-insensitive name matching requirement. -### FileAssertTest_MatchesFilter_CaseInsensitiveTag_ReturnsTrue +##### FileAssertTest_MatchesFilter_CaseInsensitiveTag_ReturnsTrue **Scenario**: `FileAssertTest.MatchesFilter` is called with a filter that differs only in case from a test tag. @@ -103,7 +103,7 @@ from a test tag. **Requirement coverage**: Case-insensitive tag matching requirement. -### FileAssertTest_Run_RunsAllFiles +##### FileAssertTest_Run_RunsAllFiles **Scenario**: `FileAssertTest.Run` is called on a test with multiple file entries. @@ -111,7 +111,7 @@ from a test tag. **Requirement coverage**: Run-all-files requirement. -### FileAssertTest_Run_NullContext_ThrowsArgumentNullException +##### FileAssertTest_Run_NullContext_ThrowsArgumentNullException **Scenario**: `FileAssertTest.Run` is called with a `null` context. @@ -119,7 +119,7 @@ from a test tag. **Boundary / error path**: Null context guard. -### FileAssertTest_Run_NullBasePath_ThrowsArgumentNullException +##### FileAssertTest_Run_NullBasePath_ThrowsArgumentNullException **Scenario**: `FileAssertTest.Run` is called with a `null` base path. @@ -127,7 +127,7 @@ from a test tag. **Boundary / error path**: Null base path guard. -## Requirements Coverage +#### Requirements Coverage - **Test creation**: FileAssertTest_Create_ValidData_CreatesTest - **Null data guard**: FileAssertTest_Create_NullData_ThrowsArgumentNullException diff --git a/docs/verification/file-assert/modeling/file-assert-text-assert.md b/docs/verification/file-assert/modeling/file-assert-text-assert.md index f88442d..9787941 100644 --- a/docs/verification/file-assert/modeling/file-assert-text-assert.md +++ b/docs/verification/file-assert/modeling/file-assert-text-assert.md @@ -1,24 +1,24 @@ -# FileAssertTextAssert Verification +### FileAssertTextAssert Verification This document describes the unit-level verification design for the `FileAssertTextAssert` unit. It defines the test scenarios, dependency usage, and requirement coverage for `Modeling/FileAssertTextAssert.cs`. -## Verification Approach +#### Verification Approach `FileAssertTextAssert` is verified with unit tests defined in `FileAssertTextAssertTests.cs`. Tests create temporary files with controlled content and assert on rule evaluation and error reporting. -## Dependencies +#### Dependencies | Dependency | Usage in Tests | |------------------|-------------------------------------------------------------| | `Context` | Used directly (not mocked) — created with controlled flags. | | `FileAssertRule` | Used directly (not mocked). | -## Test Scenarios +#### Test Scenarios -### FileAssertTextAssert_Create_ValidData_CreatesTextAssert +##### FileAssertTextAssert_Create_ValidData_CreatesTextAssert **Scenario**: `FileAssertTextAssert.Create` is called with valid data containing at least one rule. @@ -26,7 +26,7 @@ create temporary files with controlled content and assert on rule evaluation and **Requirement coverage**: Text assert creation requirement. -### FileAssertTextAssert_Create_NullData_ThrowsArgumentNullException +##### FileAssertTextAssert_Create_NullData_ThrowsArgumentNullException **Scenario**: `FileAssertTextAssert.Create` is called with `null` data. @@ -34,7 +34,7 @@ create temporary files with controlled content and assert on rule evaluation and **Boundary / error path**: Null data guard. -### FileAssertTextAssert_Run_FileContainsText_NoError +##### FileAssertTextAssert_Run_FileContainsText_NoError **Scenario**: `FileAssertTextAssert.Run` is called on a file whose content satisfies all rules. @@ -42,7 +42,7 @@ create temporary files with controlled content and assert on rule evaluation and **Requirement coverage**: Text assertion pass requirement. -### FileAssertTextAssert_Run_FileMissingText_WritesError +##### FileAssertTextAssert_Run_FileMissingText_WritesError **Scenario**: `FileAssertTextAssert.Run` is called on a file whose content does not satisfy a `contains` rule. @@ -51,7 +51,7 @@ create temporary files with controlled content and assert on rule evaluation and **Requirement coverage**: Text assertion fail requirement. -### FileAssertTextAssert_Run_NonExistentFile_WritesError +##### FileAssertTextAssert_Run_NonExistentFile_WritesError **Scenario**: `FileAssertTextAssert.Run` is called with a path that does not exist. @@ -59,7 +59,7 @@ create temporary files with controlled content and assert on rule evaluation and **Boundary / error path**: Missing file error path. -### FileAssertTextAssert_Run_MultipleRulesMultipleViolations_WritesMultipleErrors +##### FileAssertTextAssert_Run_MultipleRulesMultipleViolations_WritesMultipleErrors **Scenario**: `FileAssertTextAssert.Run` is called on a file that violates multiple rules. @@ -67,7 +67,7 @@ create temporary files with controlled content and assert on rule evaluation and **Requirement coverage**: Multiple-rule violation reporting requirement. -## Requirements Coverage +#### Requirements Coverage - **Text assert creation**: FileAssertTextAssert_Create_ValidData_CreatesTextAssert - **Null guard**: FileAssertTextAssert_Create_NullData_ThrowsArgumentNullException diff --git a/docs/verification/file-assert/modeling/file-assert-xml-assert.md b/docs/verification/file-assert/modeling/file-assert-xml-assert.md index 47093d5..ad5ccb9 100644 --- a/docs/verification/file-assert/modeling/file-assert-xml-assert.md +++ b/docs/verification/file-assert/modeling/file-assert-xml-assert.md @@ -1,24 +1,24 @@ -# FileAssertXmlAssert Verification +### FileAssertXmlAssert Verification This document describes the unit-level verification design for the `FileAssertXmlAssert` unit. It defines the test scenarios, dependency usage, and requirement coverage for `Modeling/FileAssertXmlAssert.cs`. -## Verification Approach +#### Verification Approach `FileAssertXmlAssert` is verified with unit tests defined in `FileAssertXmlAssertTests.cs`. Tests create temporary XML files with controlled content and assert on XPath query results, count constraints, and text matching. -## Dependencies +#### Dependencies | Dependency | Usage in Tests | |------------|-------------------------------------------------------------| | `Context` | Used directly (not mocked) — created with controlled flags. | -## Test Scenarios +#### Test Scenarios -### FileAssertXmlAssert_Create_ValidData_CreatesXmlAssert +##### FileAssertXmlAssert_Create_ValidData_CreatesXmlAssert **Scenario**: `FileAssertXmlAssert.Create` is called with valid data. @@ -26,7 +26,7 @@ constraints, and text matching. **Requirement coverage**: XML assert creation requirement. -### FileAssertXmlAssert_Create_NullData_ThrowsArgumentNullException +##### FileAssertXmlAssert_Create_NullData_ThrowsArgumentNullException **Scenario**: `FileAssertXmlAssert.Create` is called with `null` data. @@ -34,7 +34,7 @@ constraints, and text matching. **Boundary / error path**: Null data guard. -### FileAssertXmlAssert_Run_InvalidFile_WritesError +##### FileAssertXmlAssert_Run_InvalidFile_WritesError **Scenario**: `FileAssertXmlAssert.Run` is called with a path that is not valid XML. @@ -42,7 +42,7 @@ constraints, and text matching. **Boundary / error path**: Invalid XML file error path. -### FileAssertXmlAssert_Run_ExactCount_Matches_NoError +##### FileAssertXmlAssert_Run_ExactCount_Matches_NoError **Scenario**: `FileAssertXmlAssert.Run` is called with an exact count assertion and the XPath query returns exactly the expected number of nodes. @@ -51,7 +51,7 @@ query returns exactly the expected number of nodes. **Requirement coverage**: Exact count match requirement. -### FileAssertXmlAssert_Run_ExactCount_Mismatch_WritesError +##### FileAssertXmlAssert_Run_ExactCount_Mismatch_WritesError **Scenario**: `FileAssertXmlAssert.Run` is called with an exact count assertion and the XPath query returns a different number of nodes. @@ -60,7 +60,7 @@ query returns a different number of nodes. **Requirement coverage**: Exact count mismatch requirement. -### FileAssertXmlAssert_Run_MinMaxCount_WithinBounds_NoError +##### FileAssertXmlAssert_Run_MinMaxCount_WithinBounds_NoError **Scenario**: `FileAssertXmlAssert.Run` is called with min/max count constraints and the XPath query result count is within bounds. @@ -69,7 +69,7 @@ query result count is within bounds. **Requirement coverage**: Min/max count constraint pass requirement. -### FileAssertXmlAssert_Run_InvalidXPathQuery_WritesError +##### FileAssertXmlAssert_Run_InvalidXPathQuery_WritesError **Scenario**: `FileAssertXmlAssert.Run` is called with a malformed XPath query string. @@ -77,7 +77,7 @@ query result count is within bounds. **Boundary / error path**: Invalid XPath query error path. -### FileAssertXmlAssert_Run_XPathExactTextMatch_Matches_NoError +##### FileAssertXmlAssert_Run_XPathExactTextMatch_Matches_NoError **Scenario**: `FileAssertXmlAssert.Run` is called with an exact-text assertion and the first XPath result node matches exactly. @@ -86,7 +86,7 @@ XPath result node matches exactly. **Requirement coverage**: XPath exact text match pass requirement. -### FileAssertXmlAssert_Run_XPathExactTextMatch_NoMatch_WritesError +##### FileAssertXmlAssert_Run_XPathExactTextMatch_NoMatch_WritesError **Scenario**: `FileAssertXmlAssert.Run` is called with an exact-text assertion but the XPath result does not match. @@ -95,7 +95,7 @@ result does not match. **Requirement coverage**: XPath exact text match fail requirement. -### FileAssertXmlAssert_Run_XPathContainsText_Matches_NoError +##### FileAssertXmlAssert_Run_XPathContainsText_Matches_NoError **Scenario**: `FileAssertXmlAssert.Run` is called with a `contains` text assertion and the XPath result contains the expected value. @@ -104,7 +104,7 @@ result contains the expected value. **Requirement coverage**: XPath contains text pass requirement. -### FileAssertXmlAssert_Run_XPathContainsText_NoMatch_WritesError +##### FileAssertXmlAssert_Run_XPathContainsText_NoMatch_WritesError **Scenario**: `FileAssertXmlAssert.Run` is called with a `contains` text assertion but the XPath result does not contain the expected value. @@ -113,7 +113,7 @@ result does not contain the expected value. **Requirement coverage**: XPath contains text fail requirement. -## Requirements Coverage +#### Requirements Coverage - **XML assert creation**: FileAssertXmlAssert_Create_ValidData_CreatesXmlAssert - **Null guard**: FileAssertXmlAssert_Create_NullData_ThrowsArgumentNullException diff --git a/docs/verification/file-assert/modeling/file-assert-yaml-assert.md b/docs/verification/file-assert/modeling/file-assert-yaml-assert.md index a9d6450..87a80d7 100644 --- a/docs/verification/file-assert/modeling/file-assert-yaml-assert.md +++ b/docs/verification/file-assert/modeling/file-assert-yaml-assert.md @@ -1,24 +1,24 @@ -# FileAssertYamlAssert Verification +### FileAssertYamlAssert Verification This document describes the unit-level verification design for the `FileAssertYamlAssert` unit. It defines the test scenarios, dependency usage, and requirement coverage for `Modeling/FileAssertYamlAssert.cs`. -## Verification Approach +#### Verification Approach `FileAssertYamlAssert` is verified with unit tests defined in `FileAssertYamlAssertTests.cs`. Tests create temporary YAML files with controlled content and assert on path query results and count constraints. -## Dependencies +#### Dependencies | Dependency | Usage in Tests | |------------|-------------------------------------------------------------| | `Context` | Used directly (not mocked) — created with controlled flags. | -## Test Scenarios +#### Test Scenarios -### FileAssertYamlAssert_Create_ValidData_CreatesYamlAssert +##### FileAssertYamlAssert_Create_ValidData_CreatesYamlAssert **Scenario**: `FileAssertYamlAssert.Create` is called with valid data. @@ -26,7 +26,7 @@ constraints. **Requirement coverage**: YAML assert creation requirement. -### FileAssertYamlAssert_Create_NullData_ThrowsArgumentNullException +##### FileAssertYamlAssert_Create_NullData_ThrowsArgumentNullException **Scenario**: `FileAssertYamlAssert.Create` is called with `null` data. @@ -34,7 +34,7 @@ constraints. **Boundary / error path**: Null data guard. -### FileAssertYamlAssert_Create_EmptyQuery_ThrowsInvalidOperationException +##### FileAssertYamlAssert_Create_EmptyQuery_ThrowsInvalidOperationException **Scenario**: `FileAssertYamlAssert.Create` is called with data whose query is empty. @@ -42,7 +42,7 @@ constraints. **Boundary / error path**: Empty query validation. -### FileAssertYamlAssert_Create_TrailingDotQuery_ThrowsInvalidOperationException +##### FileAssertYamlAssert_Create_TrailingDotQuery_ThrowsInvalidOperationException **Scenario**: `FileAssertYamlAssert.Create` is called with a query that ends with a dot. @@ -50,7 +50,7 @@ constraints. **Boundary / error path**: Malformed query validation. -### FileAssertYamlAssert_Create_LeadingDotQuery_ThrowsInvalidOperationException +##### FileAssertYamlAssert_Create_LeadingDotQuery_ThrowsInvalidOperationException **Scenario**: `FileAssertYamlAssert.Create` is called with a query that starts with a dot. @@ -58,7 +58,7 @@ constraints. **Boundary / error path**: Malformed query validation. -### FileAssertYamlAssert_Create_ConsecutiveDotsQuery_ThrowsInvalidOperationException +##### FileAssertYamlAssert_Create_ConsecutiveDotsQuery_ThrowsInvalidOperationException **Scenario**: `FileAssertYamlAssert.Create` is called with a query containing consecutive dots. @@ -66,7 +66,7 @@ constraints. **Boundary / error path**: Malformed query validation. -### FileAssertYamlAssert_Run_InvalidFile_WritesError +##### FileAssertYamlAssert_Run_InvalidFile_WritesError **Scenario**: `FileAssertYamlAssert.Run` is called with a path that is not valid YAML. @@ -74,7 +74,7 @@ constraints. **Boundary / error path**: Invalid YAML file error path. -### FileAssertYamlAssert_Run_SequenceCount_Matches_NoError +##### FileAssertYamlAssert_Run_SequenceCount_Matches_NoError **Scenario**: `FileAssertYamlAssert.Run` is called with an exact count assertion and the path query returns a sequence with exactly the expected number of items. @@ -83,7 +83,7 @@ query returns a sequence with exactly the expected number of items. **Requirement coverage**: Sequence count match requirement. -### FileAssertYamlAssert_Run_SequenceCount_Mismatch_WritesError +##### FileAssertYamlAssert_Run_SequenceCount_Mismatch_WritesError **Scenario**: `FileAssertYamlAssert.Run` is called with an exact count assertion and the path query returns a different count. @@ -92,7 +92,7 @@ query returns a different count. **Requirement coverage**: Sequence count mismatch requirement. -### FileAssertYamlAssert_Run_MinMaxCount_WithinBounds_NoError +##### FileAssertYamlAssert_Run_MinMaxCount_WithinBounds_NoError **Scenario**: `FileAssertYamlAssert.Run` is called with min/max count constraints and the result count is within bounds. @@ -101,7 +101,7 @@ count is within bounds. **Requirement coverage**: Min/max count constraint pass requirement. -### FileAssertYamlAssert_Run_ScalarValue_CountsAsOne_NoError +##### FileAssertYamlAssert_Run_ScalarValue_CountsAsOne_NoError **Scenario**: `FileAssertYamlAssert.Run` is called on a path that resolves to a scalar value; a count of 1 is asserted. @@ -110,7 +110,7 @@ a count of 1 is asserted. **Requirement coverage**: Scalar value counts as one requirement. -### FileAssertYamlAssert_Run_MinCount_BelowMinimum_WritesError +##### FileAssertYamlAssert_Run_MinCount_BelowMinimum_WritesError **Scenario**: `FileAssertYamlAssert.Run` is called with a minimum count constraint that is not satisfied. @@ -119,7 +119,7 @@ satisfied. **Requirement coverage**: Minimum count constraint requirement. -### FileAssertYamlAssert_Run_MaxCount_ExceedsMaximum_WritesError +##### FileAssertYamlAssert_Run_MaxCount_ExceedsMaximum_WritesError **Scenario**: `FileAssertYamlAssert.Run` is called with a maximum count constraint that is exceeded. @@ -128,7 +128,7 @@ exceeded. **Requirement coverage**: Maximum count constraint requirement. -## Requirements Coverage +#### Requirements Coverage - **YAML assert creation**: FileAssertYamlAssert_Create_ValidData_CreatesYamlAssert - **Null guard**: FileAssertYamlAssert_Create_NullData_ThrowsArgumentNullException diff --git a/docs/verification/file-assert/program.md b/docs/verification/file-assert/program.md index f75198a..064febc 100644 --- a/docs/verification/file-assert/program.md +++ b/docs/verification/file-assert/program.md @@ -1,16 +1,16 @@ -# Program Verification +## Program Verification This document describes the unit-level verification design for the `Program` unit. It defines the test scenarios, dependency usage, and requirement coverage for `Program.cs`. -## Verification Approach +### Verification Approach `Program` is verified with unit tests defined in `ProgramTests.cs`. Because `Program` directly instantiates `Context` from real arguments and calls `Validation.Run` when needed, no mocking is required. The tests pass controlled argument arrays and assert on captured console output and exit codes. -## Dependencies +### Dependencies | Dependency | Usage in Tests | |--------------|--------------------------------------------------------------------------| @@ -19,9 +19,9 @@ codes. No test doubles are introduced at the `Program` level; all collaborators execute their real logic. -## Test Scenarios +### Test Scenarios -### Program_Run_WithVersionFlag_DisplaysVersionOnly +#### Program_Run_WithVersionFlag_DisplaysVersionOnly **Scenario**: `Program.Run` is called with a context created from `["--version"]`. @@ -30,7 +30,7 @@ exit code is 0. **Requirement coverage**: Version display requirement. -### Program_Run_WithHelpFlag_DisplaysUsageInformation +#### Program_Run_WithHelpFlag_DisplaysUsageInformation **Scenario**: `Program.Run` is called with a context created from `["--help"]`. @@ -38,7 +38,7 @@ exit code is 0. **Requirement coverage**: Help display requirement. -### Program_Run_WithValidateFlag_RunsValidation +#### Program_Run_WithValidateFlag_RunsValidation **Scenario**: `Program.Run` is called with a context created from `["--validate"]`. @@ -46,7 +46,7 @@ exit code is 0. **Requirement coverage**: Self-validation requirement. -### Program_Run_NoArguments_DisplaysDefaultBehavior +#### Program_Run_NoArguments_DisplaysDefaultBehavior **Scenario**: `Program.Run` is called with a context created from an empty argument array. @@ -54,7 +54,7 @@ exit code is 0. **Requirement coverage**: Default behavior requirement. -### Program_Version_ReturnsNonEmptyString +#### Program_Version_ReturnsNonEmptyString **Scenario**: The `Program.Version` static property is read. @@ -62,7 +62,7 @@ exit code is 0. **Requirement coverage**: Version string availability requirement. -## Requirements Coverage +### Requirements Coverage - **Version display**: Program_Run_WithVersionFlag_DisplaysVersionOnly, Program_Version_ReturnsNonEmptyString diff --git a/docs/verification/file-assert/selftest/selftest.md b/docs/verification/file-assert/selftest.md similarity index 83% rename from docs/verification/file-assert/selftest/selftest.md rename to docs/verification/file-assert/selftest.md index 044bf6c..14349c8 100644 --- a/docs/verification/file-assert/selftest/selftest.md +++ b/docs/verification/file-assert/selftest.md @@ -1,39 +1,39 @@ -# SelfTest Subsystem Verification +## SelfTest Subsystem Verification This document describes the subsystem-level verification design for the `SelfTest` subsystem. It defines the integration test approach, subsystem boundary, mocking strategy, and test scenarios that together verify the `SelfTest` subsystem requirements. -## Verification Approach +### Verification Approach The `SelfTest` subsystem is verified by integration tests defined in `SelfTestTests.cs`. Each test exercises the `Validation.Run` method with a real `Context` to confirm that the subsystem produces correct output and result files across the supported result-format options. -## Dependencies and Mocking Strategy +### Dependencies and Mocking Strategy At the subsystem boundary, `Context` (from the `Cli` subsystem) and `PathHelpers` (from the `Utilities` subsystem) are used with their real implementations. No mocking is applied. Temporary directories are used for result file output so that tests remain isolated. -## Integration Test Scenarios +### Integration Test Scenarios The following integration test scenarios are defined in `SelfTestTests.cs`. -### SelfTest_Run_ExecutesBuiltInTestsAndProducesSummary +#### SelfTest_Run_ExecutesBuiltInTestsAndProducesSummary **Scenario**: `Validation.Run` is called with a real context. **Expected**: Validation completes without error; exit code is 0; output contains a summary including "Total Tests:". -### SelfTest_Run_WhenInvoked_PrintsSystemInfoHeader +#### SelfTest_Run_WhenInvoked_PrintsSystemInfoHeader **Scenario**: `Validation.Run` is called with a real context. **Expected**: Output contains a system information header. -### SelfTest_Run_WithResultsFile_WritesTrxResultsFile +#### SelfTest_Run_WithResultsFile_WritesTrxResultsFile **Scenario**: `Validation.Run` is called with a context whose `ResultsFile` points to a temporary `.trx` path. @@ -41,7 +41,7 @@ including "Total Tests:". **Expected**: A TRX file is created at the specified path; the file contains a `