Skip to content

Ci/pester v5 coverage re-branching after history re-write - #2

Closed
scweeks wants to merge 74 commits into
mainfrom
ci/pester-v5-coverage
Closed

Ci/pester v5 coverage re-branching after history re-write#2
scweeks wants to merge 74 commits into
mainfrom
ci/pester-v5-coverage

Conversation

@scweeks

@scweeks scweeks commented Jul 22, 2026

Copy link
Copy Markdown
Owner

Description

Working to fix broken managed system detection

Related issues

  • Fixes # (issue number)

Checklist

  • I have read the CONTRIBUTING guide.
  • The code follows repository style and lint rules.
  • I have added documentation where applicable (README/CHANGELOG).
  • CI passes.

Testing and verification

Describe how this change was tested.

scweeks added 30 commits March 7, 2026 16:20
…effort step; docs: update changelog and PR template
… up into the different phases as much as possible and keeping functions that are used by all in NetClean.psm1.
scweeks added 24 commits July 21, 2026 07:21
Additional disclosures
Parameterize the Pester command-coverage floor and set CI overall coverage to 69 percent while retaining the 95 percent changed-file and long-term targets.

Document the measured 69.07 percent baseline, adapter and privacy verification behavior, conditional DNS/ARP evidence, restricted backup ACLs, and the associated changelog entries.
Pin the latest stable Pester release across CI, the coverage runner, and contributor documentation. Rebaseline the profiler-based overall coverage ratchet at 68 percent against the measured 68.43 percent result while retaining the 95 percent changed-file target.

Make the module integration container self-contained for Pester 6 discovery, reject test files as coverage sources, and make discovery or container failures fatal. Keep experimental parallel execution out of authoritative CI and coverage runs.

Validated 251 tests under PowerShell 7 and Windows PowerShell 5.1, an isolated 251-test parallel trial, 3,351 of 4,897 covered production commands, and a clean PSScriptAnalyzer 1.25.0 run across 23 targets.
Exercise real Registry-provider detection, native backup, protected cleanup, and independent post-state verification against synthetic Pester TestRegistry data.

Add a private validated registry-root seam, fix reg.exe export quoting for paths containing spaces, include System tests in CI, and ratchet production command coverage to 69%.
Add a Phase 4 verification failure matrix for registry and user artifacts, event logs, DNS and ARP caches, and physical-adapter discovery.

Preserve fail-soft registry discovery while allowing post-state verification to surface provider failures, and tolerate physical adapter objects without InterfaceIndex.

Raise and align the production-only coverage ratchet from 69% to 71% after reaching 71.29%, with tests excluded from measurement.
Exercise Security Center products, services, drivers, uninstall records, adapters, PnP devices, service registry evidence, file metadata, and registry correlations that define protected components.

Allow empty metadata paths to reach the existing fail-soft guard and add complex inventory tests for services, drivers, adapter GUIDs, registry keys, filters, categories, and confidence.

Raise and align the production-only coverage ratchet from 71% to 80% after reaching 80.17%, with tests excluded from measurement.
Add functional contracts for menus, confirmation, detect/protect/clean/verify summaries, previews, Preview routing, live backup creation, and mocked dry or live power actions.

Make launcher settings explicitly script-scoped, permit empty summary collections, and correct invalid yes/no feedback that used an unsupported Write-Verbose parameter.

Keep performance-tuning selection out of this slice and raise the production-only coverage ratchet from 80% to 85% after reaching 85.56%.
Exercise Phase 3 cleanup failure ledgers, Quad9/adapter error handling, and Phase 4 fail-closed verification paths.

Harden sparse evidence and empty-context handling under strict mode, and remove fully traced private compatibility wrappers with no repository or export consumers.

Raise the overall coverage ratchet from 85% to 90% after reaching 92.05% production command coverage with 363 passing tests on PowerShell 7 and Windows PowerShell 5.1; PSScriptAnalyzer reports zero findings.
Expand Pester 6 coverage across protection discovery, workflow orchestration, registry export validation, cleanup failure handling, and sparse verification ledgers.

Preserve vendor inference when file metadata is incomplete and normalize exported Wi-Fi profile basenames used by workflow verification.

Raise the overall CI coverage ratchet from 90 to 94 percent after measuring 95.09 percent production command coverage, while retaining the 95 percent changed-file target and excluding tests from coverage.

Validated 387 tests on PowerShell 7 and Windows PowerShell 5.1, the module manifest, and PSScriptAnalyzer 1.25.0 with zero findings across 24 targets.
Retry only transient PSScriptAnalyzer null-reference failures once while keeping repeated failures, other exceptions, and findings fatal. Add focused regression tests for the retry boundary.

Run the complete suite in a parallel Windows PowerShell 5.1 job and pin workflow actions to immutable Node.js 24 releases.

Temporarily remove performance tuning from the interactive menu while preserving explicit mode compatibility, and update tests and project documentation.
Treat Workplace registration as preserved user-level SSO unless independent domain, Entra join, enterprise join, or MDM evidence exists. Keep security, VPN, and virtual-adapter protection boundaries intact.

Document and test the narrow Explorer-history and network-event-log cleanup allowlists so identity, token, credential, BrokerPlugin, and account stores remain out of scope.

Capture netsh Wi-Fi profile output as UTF-8 and restore the caller encoding so non-ASCII SSID names render correctly across PowerShell hosts.
@scweeks
scweeks requested a review from Copilot July 22, 2026 19:01
@scweeks scweeks self-assigned this Jul 22, 2026
@scweeks scweeks closed this Jul 22, 2026

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR restructures NetClean’s test/CI toolchain around Pester 6 + PSScriptAnalyzer, adds extensive regression/unit/system/functional coverage (including managed-device detection and protection/backup behaviors), and updates project docs/workflows to match the newer phase-oriented module layout.

Changes:

  • Add a comprehensive Pester 6 test suite across Unit/Integration/Functional/System layers and introduce a dedicated coverage runner with enforced minimum coverage.
  • Replace the legacy single-module/test setup with phase-oriented implementation (notably Phase 2 protect/backup helpers) and updated analyzer runner behavior.
  • Update CI workflows, repo docs, and contribution guidance to codify the new quality gates (analyzer clean + coverage ratchet + compatibility job).

Reviewed changes

Copilot reviewed 34 out of 35 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
tests/Unit/NetClean.Safety.Unit.Tests.ps1 Adds safety regression coverage for protected registry boundaries and dry-run backup behavior.
tests/Unit/NetClean.Phase2.Unit.Tests.ps1 Adds unit coverage for Phase 2 protection/backup exports (Wi-Fi, registry, firewall, manifest).
tests/Unit/NetClean.Phase1.Unit.Tests.ps1 Adds extensive unit coverage for Phase 1 detection (evidence sources, inventory correlation, sanitizable artifacts).
tests/Unit/NetClean.Coverage.Unit.Tests.ps1 Adds tests asserting coverage runner and CI workflow gating/pinning behaviors.
tests/Unit/NetClean.Core.Unit.Tests.ps1 Adds unit coverage for core helpers (registry path conversions, GUID normalization, IO seams, native capture).
tests/Unit/NetClean.Analyzer.Unit.Tests.ps1 Adds unit coverage for analyzer runner retry/fail-closed behavior.
tests/System/NetClean.Registry.System.Tests.ps1 Adds isolated system-component registry tests using Pester’s TestRegistry drive.
tests/Run-NetClean-Coverage.ps1 Introduces a Pester 6 coverage runner with minimum coverage enforcement and test-path exclusion.
tests/Netclean.Tests.ps1 Removes legacy Pester v5-era monolithic tests.
tests/Invoke-NetCleanAnalyzer.ps1 Adds a fail-closed analyzer runner with targeted retry for transient NullReferenceException.
tests/Integration/NetClean.Script.Integration.Tests.ps1 Adds integration tests for dot-sourcing the launcher script and launcher function surface.
tests/Integration/NetClean.Module.Integration.Tests.ps1 Adds integration tests for manifest validity and expected exports/aliases.
tests/Functional/NetClean.Workflow.Functional.Tests.ps1 Adds functional workflow contract tests for modes, timings, summaries, and option pass-through.
tests/Functional/NetClean.Launcher.Functional.Tests.ps1 Adds functional tests for launcher UX, options, summaries, and post-run power actions.
README.md Updates user-facing documentation to the new modes/workflow model and CI/tooling expectations.
PSScriptAnalyzerSettings.psd1 Adjusts analyzer settings to work around specific PSScriptAnalyzer 1.25.0 issues.
Netclean.psm1 Removes legacy module implementation in favor of the new module layout.
Netclean.psd1 Updates module manifest metadata, exports, and repository/license metadata.
Modules/NetCleanPhase2.ps1 Adds Phase 2 protect/backup implementation (registry/network/Wi-Fi/firewall/manifest exports).
examples/run-netclean.ps1 Updates example runner defaults and output behavior to match NetClean paths/streams.
examples/restore-wifi-profiles.ps1 Updates Wi-Fi restore helper to match new backup paths and avoid Write-Host.
examples/register-scheduledtask.ps1 Updates scheduled task example output behavior to avoid Write-Host.
CONTRIBUTING.md Rewrites contribution guidance around red-green-refactor, coverage ratchet, and tabled perf-tuning.
CHANGELOG.md Expands changelog entries to reflect the new architecture, coverage gates, and behavioral guarantees.
.gitignore Adds ignores for generated test/coverage output and assistant artifacts.
.github/workflows/powershell-check.yml Removes the old CI workflow.
.github/workflows/ci.yml Adds a new CI workflow with analyzer + coverage job, WinPS 5.1 compatibility job, and PR coverage commenting.
.github/PULL_REQUEST_TEMPLATE.md Updates PR template to include security/CI checklist items.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

BeforeEach {
Mock New-DirectoryIfNotExist {}
Mock Set-NetCleanPrivateDirectoryAcl {}
Mock Invoke-RegExport { $FilePath }
Comment on lines +73 to +81
Mock Invoke-ExternalCommandSafe {
[pscustomobject]@{
Name = $Name
ExitCode = 0
Succeeded = $true
DryRun = $true
Error = $null
}
}
Comment thread Netclean.psd1
LicenseUri = 'https://opensource.org/licenses/MIT'
ProjectUri = 'https://github.com/example/NetworkCleaner'
ProjectUri = 'https://github.com/scweeks/netclean'
LicenseUri = 'https://github.com/scweeks/netclean/blob/ci/pester-v5-coverage/LICENSE'
Comment on lines +105 to +111
.OUTPUTS
Array of exported file paths.
#>
function Export-NetworkList {
[CmdletBinding()]
[OutputType([System.Object[]])]
param(
Comment on lines +446 to +450
if (-not $PSBoundParameters.ContainsKey('Inventory') -or $null -eq $Inventory) {
Write-NetCleanLog -Level INFO -Message 'No inventory provided, performing detection to gather current protection inventory.'
$Inventory = @(Get-ProtectionInventory)
Write-NetCleanLog -Level INFO -Message ("Detected {0} inventory entries for export." -f @($Inventory).Count)
}
scweeks added a commit that referenced this pull request Jul 24, 2026
…port test

The Windows PowerShell 5.1 job's "Ensure repo modules are preferred and
PSModulePath set (ps51)" step set $env:PSModulePath to include the
Save-Module cache path, but never persisted it to $env:GITHUB_ENV -
unlike the equivalent PS7 job step, which does. Each workflow step
runs in a fresh process, so that PSModulePath change was silently lost
before the next step ran, and Import-Module Pester -RequiredVersion
6.0.1 then failed with "no valid module file was found in any module
directory" because the process resolving the import had no idea the
cache path existed. Added the missing GITHUB_ENV persistence line,
mirroring the working PS7 pattern exactly.

NetClean.Coverage.Unit.Tests.ps1's "runs the complete suite under
Windows PowerShell 5.1 in CI" test regex-matched the literal text
'Install-Module Pester...RequiredVersion 6.0.1' in ci.yml, which broke
when the ps51 job's install step was switched to Save-Module +
explicit Import-Module for module-cache support. Updated the pattern
to accept either Install-Module or Save-Module and to also check for
the explicit Import-Module call, preserving the original intent
(Pester 6.0.1 is specifically requested) without being tied to which
of the two installation mechanisms is currently in use.

Export-WiFiProfile's "falls back to per-profile export when bulk
export creates no files" test mocked Get-ChildItem with a hardcoded
call-order counter (call #1 = bulk-before, #2 = bulk-after, etc.) -
implementation-coupled in exactly the way flagged in the ongoing
test-agnosticism audit, and it was flaky: passed consistently in
isolation and in a full-file run locally, but failed in CI. Replaced
it with a state-driven mock: a virtual exported-file list that grows
only when Invoke-ExternalCommandSafe "exports" a named profile, with
Get-ChildItem always returning that list's current state. This models
the real netsh-creates-a-file/Get-ChildItem-sees-it relationship
directly, so the test no longer depends on how many times or in what
order the production code happens to call Get-ChildItem.

Validated: 455/455 Pester tests passing on PowerShell 7.6 and Windows
PowerShell 5.1, PSScriptAnalyzer 1.25.0 clean, production coverage
95.50%.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants