Skip to content

Commit 9c44754

Browse files
authored
feat: Enhance Nova CLI testing, workflow functionality, and documentation (#252)
* #247 feat: Enhance Nova CLI Testing and Workflow Functionality - Added tests for Invoke-NovaCliTestRouteCommand to ensure proper routing of test commands. - Improved Get-NovaPesterRunPath to return matching recursive test files based on BuildRecursiveFolders setting. - Updated Get-NovaPesterTestResultPath to allow custom result file names. - Refactored Get-NovaTestWorkflowContext to support new test workflow configurations and parameters. - Introduced new tests for Invoke-NovaTest to validate command options and workflow invocation. - Enhanced Invoke-NovaReleaseWorkflow to track unit and integration test calls separately. - Removed deprecated NewNovaTestDynamicParameterDictionary tests. - Updated scaffolding tests to reflect changes in suggested next steps for workflows. - Refined dynamic parameter handling in Nova testing functions to improve clarity and maintainability. * #247 feat: Add -OverrideWarning parameter to Invoke-NovaTest and related updates for coverage configuration * #247 feat: Refactor testing and validation instructions for Nova-managed projects - Update reviewer and test engineer agents to specify `Invoke-NovaTest` for unit validation and `Test-NovaBuild` for build-validation integration. - Revise documentation to clarify public command unit tests and integration tests structure under `tests/public/<Command>.Tests.ps1` and `tests/public/<Command>.Integration.Tests.ps1`. - Enhance instructions for handling destructive or environment-coupled commands with a preference for safe `-WhatIf` integration coverage. - Adjust various prompts and guidelines to reflect the new testing structure and validation processes. - Ensure consistency across all documentation regarding the use of `Invoke-NovaTest` and `Test-NovaBuild`. * #247 feat: Add integration tests for Nova commands with WhatIf support
1 parent 4daf546 commit 9c44754

104 files changed

Lines changed: 1751 additions & 474 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/agents/powershell-developer.agent.md

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,9 @@ Implement PowerShell command and helper changes in the NovaModuleTools style.
4747
- Preserve existing command names, warning semantics, and output shape.
4848
- Keep new or heavily changed source functions aligned with `.github/instructions/code-quality-matrix.instructions.md`: short, single-purpose, low-duplication, and split by clear responsibility unless the scope explicitly justifies otherwise.
4949
- Prefer `./scripts/build/Invoke-ScriptAnalyzerCI.ps1` and `./run.ps1` for normal analyzer loops; use direct `Invoke-ScriptAnalyzer` only for focused local checks that reuse the repository-approved settings.
50-
- Validate Nova-managed project tests through `Test-NovaBuild`; do not call `Invoke-Pester` directly.
50+
- Validate Nova-managed project tests through `Invoke-NovaTest` for unit validation and `Test-NovaBuild` for build-validation integration validation; do not call `Invoke-Pester` directly.
51+
- For public commands, keep unit coverage in `tests/public/<Command>.Tests.ps1` and keep per-command integration ownership in `tests/public/<Command>.Integration.Tests.ps1` when built-module behavior itself needs validation.
52+
- For destructive or environment-coupled public commands, prefer safe `-WhatIf` integration coverage when that still proves `ShouldProcess`, routing, and output behavior.
5153
- When help files change, keep `docs/NovaModuleTools/en-US/*.md` valid for `Import-MarkdownCommandHelp`: build and import the dist module first (`Import-Module ./dist/NovaModuleTools/NovaModuleTools.psd1 -Force`), then use `New-MarkdownCommandHelp` for new files, `Update-MarkdownCommandHelp` after command-surface changes, and `Test-MarkdownCommandHelp` before handoff. Generating help without the module imported causes `external help file` to default to the command name instead of the module name, producing per-command XML files that the manifest cannot find. A new public `src/public/*.ps1` file is not done until its matching help file exists.
5254

5355
## Definition of done
@@ -56,7 +58,8 @@ Implement PowerShell command and helper changes in the NovaModuleTools style.
5658
- Build output still comes from Nova-generated `dist/` files, not hand-authored module files in `src/`.
5759
- Public/private file ownership still follows the one externally called function per file rule, with private helpers kept as sibling top-level functions instead of nested function declarations.
5860
- Every new public entry point has its matching help file.
59-
- Project test validation ran through `Test-NovaBuild`.
61+
- Project test validation ran through `Invoke-NovaTest` for unit coverage and `Test-NovaBuild` for build-validation integration coverage.
62+
- Public-command integration coverage stays owned by `tests/public/<Command>.Integration.Tests.ps1` when built-module behavior needs validation.
6063
- Any ScriptAnalyzer findings reported by `run.ps1` or `Invoke-ScriptAnalyzerCI.ps1` are resolved.
6164
- Every changed or generated text file has been checked and ends with exactly one trailing newline and no extra blank lines at the bottom.
6265
- Docs/changelog review is complete.

.github/agents/reviewer.agent.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,9 @@ Review changes for correctness, maintainability, test coverage, workflow safety,
2727
- Review changed `src/**/*.ps1` against `.github/instructions/code-quality-matrix.instructions.md` and `tests/**/*.ps1` against `.github/instructions/testing-policy.instructions.md`; flag new or heavily changed code that ignores those maintainability rules without a clear, explicit reason.
2828
- Flag public files that do not keep exactly one top-level function, and flag private files that group multiple externally called functions instead of limiting extra functions to related same-file top-level support helpers. Also flag file/function name mismatches for public commands or externally called private helpers, and flag nested function declarations inside PowerShell functions.
2929
- Flag broad catch-all test files when focused source-mirrored tests would make ownership clearer.
30-
- Flag Nova-managed validation that bypasses `Test-NovaBuild` with direct `Invoke-Pester`.
30+
- Flag public-command changes that skip `tests/public/<Command>.Tests.ps1` or the owning `tests/public/<Command>.Integration.Tests.ps1` without a clear cross-cutting justification.
31+
- Flag destructive or environment-coupled public-command integrations that should have used safe `-WhatIf` coverage but did not.
32+
- Flag Nova-managed validation that bypasses `Invoke-NovaTest` or `Test-NovaBuild` with direct `Invoke-Pester`.
3133
- Flag any PSScriptAnalyzer rule excludes or suppressions; the code should be fixed instead.
3234
- Flag unresolved ScriptAnalyzer findings from `run.ps1` or `Invoke-ScriptAnalyzerCI.ps1`; they should be fixed instead of deferred.
3335
- Flag every changed or generated text file if they do not exactly have one trailing newline with no extra blank lines at the bottom.

.github/agents/test-engineer.agent.md

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -40,22 +40,24 @@ Improve or maintain the repository's Pester coverage, coverage-gate behavior, an
4040

4141
## Constraints
4242

43-
- Prefer the smallest `Test-NovaBuild` scope the project already supports, then the full repo quality loop.
43+
- Prefer the smallest `Invoke-NovaTest` scope for unit behavior, then `Test-NovaBuild` for build-validation integration coverage, then the full repo quality loop.
4444
- Keep test files maintainable; passing tests are not enough if Code Health degrades.
4545
- Reuse existing fixture and support patterns before adding new ones.
4646
- Do not group unrelated source files into one broad test file when mirrored `tests/public`, `tests/private`, or `tests/classes` ownership is possible.
47+
- For public commands, keep unit coverage in `tests/public/<Command>.Tests.ps1` and per-command integration ownership in `tests/public/<Command>.Integration.Tests.ps1` when built-module behavior needs coverage.
48+
- For destructive or environment-coupled public commands, prefer safe `-WhatIf` integration coverage when that still proves the command wiring and `ShouldProcess` behavior.
4749
- Do not introduce PowerShell 7.x-only test syntax or APIs into a project that targets `5.1` unless compatibility coverage is explicitly part of the scope.
4850
- If CodeScene flags a regression, refactor the tests or helpers instead of suppressing the finding.
4951
- Keep new or heavily changed tests focused, isolated, and easy to scan; split setup or assertion helpers when a test stops being readable.
5052
- Use `./scripts/build/Invoke-ScriptAnalyzerCI.ps1` as the normal analyzer entrypoint for changed test/helpers, and only fall back to direct `Invoke-ScriptAnalyzer` for focused local investigation with the repository-approved settings.
51-
- Use `Test-NovaBuild` as the test entrypoint for Nova-managed projects; do not validate with direct `Invoke-Pester`.
53+
- Use `Invoke-NovaTest` as the unit-test entrypoint and `Test-NovaBuild` as the build-validation integration-test entrypoint for Nova-managed projects; do not validate with direct `Invoke-Pester`.
5254

5355
## Definition of done
5456

5557
- The changed behavior is covered.
5658
- Each new or changed `src/**/*.ps1` file has a matching source-mirrored test, or the cross-cutting owner test is named explicitly.
5759
- The touched tests are readable and low-duplication.
58-
- Validation uses `Test-NovaBuild` for project test execution.
60+
- Validation uses `Invoke-NovaTest` for unit execution and `Test-NovaBuild` for build-validation integration execution.
5961
- Validation and CodeScene implications are addressed.
6062
- The pre-commit CodeScene safeguard is clean before the work is treated as commit-ready when local CodeScene tooling is available.
6163

.github/copilot-instructions.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ For new or not-yet-scoped work, use the `architect` agent with `.github/prompts/
2121

2222
- `src/public/` — public PowerShell commands; one top-level function per file, file name matches function name
2323
- `src/private/` — domain-grouped helpers (`build/`, `cli/`, `package/`, `quality/`, `release/`, `scaffold/`, `shared/`, `update/`); one externally called helper per file
24-
- `tests/` — Pester tests and shared test-support scripts
24+
- `tests/` — Pester tests and shared test-support scripts; public command unit tests live under `tests/public/<Command>.Tests.ps1` and per-command build-validation integration tests live under `tests/public/<Command>.Integration.Tests.ps1`
2525
- `scripts/build/` — local analyzer and build helpers
2626
- `scripts/build/ci/` — CI coverage, CodeScene, and artifact helpers
2727
- `.github/workflows/` — GitHub Actions CI, analyzer, dependency review, publish automation

.github/instructions/code-quality-matrix.instructions.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ This file tells Agentic Copilot how to shape source code from the start. Test-sp
111111
- How to apply in PowerShell:
112112
- Add or update a source-mirrored `tests/<area>/<Name>.Tests.ps1` file for every changed `src/**/*.ps1` file.
113113
- Cover both the happy path and the meaningful unhappy, invalid, and boundary cases that the change introduces.
114-
- Use `Test-NovaBuild` as the authoritative test entrypoint in Nova-managed projects. Do not call `Invoke-Pester` directly.
114+
- Use `Invoke-NovaTest` as the unit-test entrypoint and `Test-NovaBuild` as the build-validation integration-test entrypoint in Nova-managed projects. Do not call `Invoke-Pester` directly.
115115
- Isolate collaborators with mocks/stubs when verifying side effects or branching. Keep tests order-independent.
116116
- See `.github/instructions/testing-policy.instructions.md` and the `pester-testing` skill for the full testing rules.
117117
- Common objection: "It is too small to test." If it is too small to test, it is too small to be a change worth landing.

.github/instructions/powershell-coding-standards.instructions.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ Use this file when changing `src/public/`, `src/private/`, or PowerShell build/r
3838
- Follow `.github/instructions/psscriptanalyzer.instructions.md` as the ScriptAnalyzer workflow source of truth. Use the repository analyzer wrapper for normal runs and reuse repository-approved settings when invoking `Invoke-ScriptAnalyzer` directly on a focused path.
3939
- When public command help changes, follow `.github/instructions/platyps-help.instructions.md` and use `New-MarkdownCommandHelp`, `Update-MarkdownCommandHelp`, and `Test-MarkdownCommandHelp` instead of hand-authoring the help structure.
4040
- Do not add PSScriptAnalyzer `ExcludeRule`, `ExcludeRules`, suppression attributes, or generated settings that hide analyzer findings. Fix the rule violation instead.
41-
- Keep local quality wrappers ordered as ScriptAnalyzer first, then `Invoke-NovaBuild`, then `Test-NovaBuild`.
41+
- Keep local quality wrappers ordered as ScriptAnalyzer first, then `Invoke-NovaBuild`, then `Invoke-NovaTest`, then `Test-NovaBuild`.
4242
- If `run.ps1` or `Invoke-ScriptAnalyzerCI.ps1` reports ScriptAnalyzer findings, fix them before treating the change as complete.
4343

4444
## Formatting rules

.github/instructions/repository-conventions.instructions.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ Canonical rule source for cross-cutting NovaModuleTools conventions that apply t
2929
Use the smallest validation set that proves the change, then run the repository quality loop before finishing code work:
3030

3131
- local quality loop: `pwsh -NoLogo -NoProfile -File ./run.ps1`
32-
- test validation: `Test-NovaBuild`
32+
- test validation: `Invoke-NovaTest` for unit-test validation, then `Test-NovaBuild` for build-validation integration coverage
3333
- analyzer only: `./scripts/build/Invoke-ScriptAnalyzerCI.ps1`
3434
- CI-parity coverage flow: `./scripts/build/ci/Invoke-NovaModuleToolsCI.ps1 -OutputDirectory ./artifacts`
3535

.github/instructions/testing-policy.instructions.md

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,14 @@ BeforeAll {
3030

3131
Legacy tests that still use `Import-Module $project.OutputModuleDir` + `InModuleScope` can still exist while maintainers finish migrations, but the mirrored pattern itself now supports enabled repository coverage gates. Generated project templates still ship `CodeCoverage.Enabled = false` until maintainers opt into the coverage gate for their own project.
3232

33+
## Integration tests may import `dist/`
34+
35+
- New mirrored unit tests should keep dot-sourcing `src/**/*.ps1` files directly.
36+
- Public command integration ownership lives in `tests/public/<Command>.Integration.Tests.ps1` when the purpose is validating built-module behavior, exported command shape, command wiring, or build-validation smoke coverage.
37+
- Cross-cutting `*.Integration.Tests.ps1` files may `Import-Module ./dist/<ModuleName>/<ModuleName>.psd1` when the behavior genuinely spans multiple source files.
38+
- For destructive or environment-coupled public commands, prefer safe `-WhatIf` integration coverage when that still proves `ShouldProcess`, routing, and output behavior.
39+
- Keep that `dist/` import limited to integration scenarios; do not use it as the default pattern for mirrored unit tests.
40+
3341
## Cross-cutting tests are still allowed
3442

3543
Use a cross-cutting test file (not a mirrored one) when the behavior under test truly spans multiple source files:
@@ -46,6 +54,7 @@ Cross-cutting files should be **named for the behavior** they validate (e.g., `A
4654
| Source file | Mirrored test file |
4755
|-----------------------------------|-------------------------------------------|
4856
| `src/public/<Name>.ps1` | `tests/public/<Name>.Tests.ps1` |
57+
| `src/public/<Name>.ps1` | `tests/public/<Name>.Integration.Tests.ps1` for built-module/public-command integration ownership |
4958
| `src/private/<domain>/<Name>.ps1` | `tests/private/<domain>/<Name>.Tests.ps1` |
5059
| `src/classes/<Name>.ps1` | `tests/classes/<Name>.Tests.ps1` |
5160

@@ -54,8 +63,10 @@ A non-blocking mirror status helper is available at `scripts/build/Get-TestMirro
5463
## Test expectations
5564

5665
- Behavior changes require Pester coverage.
57-
- Use `Test-NovaBuild` as the authoritative test entrypoint in Nova-managed projects. Do not validate with direct `Invoke-Pester`, because it can bypass Nova's build/import/StrictMode flow and disagree with what users see later.
58-
- Prefer the smallest `Test-NovaBuild` scope the project already supports before running the full quality loop.
66+
- `Invoke-NovaTest` is the unit-test entrypoint and `Test-NovaBuild` is the build-validation integration-test entrypoint in Nova-managed projects. Do not validate with direct `Invoke-Pester`, because it can bypass Nova's build/import/StrictMode flow and disagree with what users see later.
67+
- Prefer the smallest supported test scope first: `Invoke-NovaTest` for unit behavior, then `Test-NovaBuild` when the change needs built-module or integration validation, before running the full quality loop.
68+
- For public commands, keep unit coverage in `tests/public/<Command>.Tests.ps1` and keep per-command integration ownership in `tests/public/<Command>.Integration.Tests.ps1` when the built command behavior itself needs validation.
69+
- For destructive or environment-coupled public commands, prefer safe `-WhatIf` integration coverage when that still proves `ShouldProcess`, routing, and output semantics.
5970
- Keep test names explicit about the behavior being proven.
6071
- Reuse `*.TestSupport.ps1` helpers where possible.
6172
- For every new or changed `src/**/*.ps1` file, add or update the matching source-mirrored `.Tests.ps1` file.
@@ -71,6 +82,7 @@ A non-blocking mirror status helper is available at `scripts/build/Get-TestMirro
7182
## Repository test structure
7283

7384
- `tests/public/<Name>.Tests.ps1`, `tests/private/<domain>/<Name>.Tests.ps1`, `tests/classes/<Name>.Tests.ps1` - mirrored unit tests (preferred for new and migrated tests)
85+
- `tests/public/<Name>.Integration.Tests.ps1` - per-command build-validation integration tests for public commands
7486
- `tests/ArchitectureGuardrails.Tests.ps1` - layering and adapter boundaries
7587
- `tests/NovaCommandModel*.Tests.ps1` - public command, CLI, and workflow behavior (legacy bucket, being migrated)
7688
- `tests/*TestSupport.ps1`, `tests/TestHelpers/` - shared helpers, reusable fixtures, dot-source helpers
@@ -79,7 +91,8 @@ A non-blocking mirror status helper is available at `scripts/build/Get-TestMirro
7991
## Coverage and CodeScene
8092

8193
- CI coverage is generated by `./scripts/build/ci/Invoke-NovaModuleToolsCI.ps1`.
82-
- `Test-NovaBuild` runs once and produces a JaCoCo coverage report at `artifacts/coverage.xml`.
94+
- `Invoke-NovaTest` produces the repository JaCoCo coverage report at `artifacts/coverage.xml`.
95+
- `Test-NovaBuild` focuses on build-validation integration coverage and produces NUnit results without source coverage enforcement.
8396
- The JaCoCo artifact is reused by the CodeScene PR coverage gate and by the develop/manual CodeScene analysis flow.
8497
- The CodeScene analysis upload sends coverage twice: once for `line-coverage` and once for `branch-coverage`.
8598
- Coverage paths in `project.json` must point at `src/**/*.ps1`, not at the built `dist` psm1. Nova does not override `CodeCoverage.Path`.
@@ -99,6 +112,7 @@ A non-blocking mirror status helper is available at `scripts/build/Get-TestMirro
99112

100113
## Verification
101114

115+
- `Invoke-NovaTest`
102116
- `Test-NovaBuild`
103117
- `./scripts/build/Invoke-ScriptAnalyzerCI.ps1` when PowerShell code changed
104118
- `pwsh -NoLogo -NoProfile -File ./run.ps1` before completion

.github/prompts/implement-issue.prompt.md

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -27,13 +27,14 @@ Implement the issue in the NovaModuleTools repository using the repository-local
2727
12. Keep file/function ownership explicit: one externally called function per file, with private-file extras limited to related same-file top-level support helpers, keep the file name aligned to the entry function, and do not declare functions inside functions.
2828
13. Before handoff, review every changed or generated text file and normalize it to exactly one trailing newline with no extra blank lines at the bottom.
2929
14. Add or update the matching source-mirrored Pester file for every changed `src/**/*.ps1` file; if the behavior is genuinely cross-cutting, document which integration/guardrail test owns it and why a mirrored unit test is not practical.
30-
15. Validate Nova-managed project tests through `Test-NovaBuild`; do not call `Invoke-Pester` directly because it can bypass Nova's build/import/StrictMode flow.
31-
16. Add or update valid PlatyPS-compatible help under `docs/NovaModuleTools/en-US/` when public commands or public classes change. Use `New-MarkdownCommandHelp` for new help, `Update-MarkdownCommandHelp` after command-surface changes, and `Test-MarkdownCommandHelp` before handoff; do not replace command help with plain Markdown prose.
32-
17. For every new public entry point, create its matching help file immediately in the same change.
33-
18. Review `README.md`, `CONTRIBUTING.md`, `CHANGELOG.md`, `RELEASE_NOTE.md`, help docs, and `docs/*.html` as applicable.
34-
19. If a commit message is requested, derive it from `$GIT_BRANCH_NAME` and the implemented change using the repository's Conventional Commit rules.
35-
20. Run the relevant validation, then summarize what changed, why, and how it was verified.
36-
21. If that summary is returned as Markdown or copy-ready UI output, format it according to the `markdown-authoring` skill (`.github/skills/markdown-authoring/SKILL.md`).
30+
15. Validate Nova-managed project tests through `Invoke-NovaTest` for unit validation and `Test-NovaBuild` for build-validation integration validation; do not call `Invoke-Pester` directly because it can bypass Nova's build/import/StrictMode flow.
31+
16. For public commands, keep unit coverage in `tests/public/<Command>.Tests.ps1` and keep per-command integration ownership in `tests/public/<Command>.Integration.Tests.ps1` when built-module behavior itself needs validation. For destructive or environment-coupled public commands, prefer safe `-WhatIf` integration coverage when that still proves `ShouldProcess`, routing, and output behavior.
32+
17. Add or update valid PlatyPS-compatible help under `docs/NovaModuleTools/en-US/` when public commands or public classes change. Use `New-MarkdownCommandHelp` for new help, `Update-MarkdownCommandHelp` after command-surface changes, and `Test-MarkdownCommandHelp` before handoff; do not replace command help with plain Markdown prose.
33+
18. For every new public entry point, create its matching help file immediately in the same change.
34+
19. Review `README.md`, `CONTRIBUTING.md`, `CHANGELOG.md`, `RELEASE_NOTE.md`, help docs, and `docs/*.html` as applicable.
35+
20. If a commit message is requested, derive it from `$GIT_BRANCH_NAME` and the implemented change using the repository's Conventional Commit rules.
36+
21. Run the relevant validation, then summarize what changed, why, and how it was verified.
37+
22. If that summary is returned as Markdown or copy-ready UI output, format it according to the `markdown-authoring` skill (`.github/skills/markdown-authoring/SKILL.md`).
3738

3839
## Repository-specific reminders
3940

0 commit comments

Comments
 (0)