# Testing Patterns **Analysis Date:** 2026-04-02 ## Test Framework **Status:** No automated testing framework detected **Infrastructure:** Not applicable - No test runner (Jest, Vitest, Pester) - No test configuration files - No test suite in codebase - No CI/CD pipeline test stage configured ## Testing Approach **Current Testing Model:** Manual testing via GUI **Test Methods:** - **GUI Testing:** All functionality tested through WinForms UI - Manual interaction with controls and dialogs - Visual verification of results in generated reports - Log output observation in RichTextBox - **Report Validation:** HTML and CSV exports manually reviewed for correctness - **API Integration:** Manual testing of PnP.PowerShell operations against live SharePoint tenant - **Regression Testing:** Ad-hoc manual verification of features after changes ## Code Organization for Testing **Testability Patterns:** Limited The monolithic single-file architecture (`Sharepoint_ToolBox.ps1` at 6408 lines) makes isolated unit testing challenging. Key observations: **Tight Coupling to UI:** - Core business logic embedded in event handlers - Heavy reliance on global `$script:` scope for state - Example: `Load-Profiles` reads from `Get-ProfilesFilePath`, which is file-system dependent - Site picker functionality (`Show-SitePicker`) spawns background runspace but depends on form being instantiated **Hard Dependencies:** - PnP.PowerShell module imported dynamically in background runspace blocks - File system access (profiles, templates, settings) not abstracted - SharePoint connection state implicit in PnP connection context **Areas with Better Isolation:** - Pure utility functions like `Format-Bytes`, `EscHtml` could be unit tested - Data transformation functions like `Merge-PermissionRows` accept input arrays and return structured output - HTML generation in `Export-PermissionsToHTML` and `Export-StorageToHTML` could be tested against expected markup ## Background Runspace Pattern **Async Execution Model:** Most long-running operations execute in separate PowerShell runspace to prevent UI blocking: ```powershell # 1. Create synchronized hashtable for communication $sync = [hashtable]::Synchronized(@{ Done = $false Error = $null Result = $null Queue = [System.Collections.Generic.Queue[object]]::new() }) # 2. Define background script block (has access to passed parameters only) $bgScript = { param($Url, $ClientId, $Sync) try { Import-Module PnP.PowerShell -ErrorAction Stop Connect-PnPOnline -Url $Url -Interactive -ClientId $ClientId # Perform work $Sync.Result = $data } catch { $Sync.Error = $_.Exception.Message } finally { $Sync.Done = $true } } # 3. Launch in runspace $rs = [System.Management.Automation.Runspaces.RunspaceFactory]::CreateRunspace() $rs.ApartmentState = "STA"; $rs.ThreadOptions = "ReuseThread"; $rs.Open() $ps = [System.Management.Automation.PowerShell]::Create() $ps.Runspace = $rs [void]$ps.AddScript($bgScript) [void]$ps.AddArgument($url) $hnd = $ps.BeginInvoke() # 4. Poll completion with timer $tmr = New-Object System.Windows.Forms.Timer $tmr.Interval = 300 $tmr.Add_Tick({ if ($sync.Done) { [void]$ps.EndInvoke($hnd) $rs.Close(); $rs.Dispose() # Update UI with $sync.Result } }) $tmr.Start() ``` **Used for:** - Site picker loading: `Show-SitePicker` (lines 212-471) - Template capture: Background job in template manager (lines 900+) - Site creation: Background job in bulk creation (lines 1134+) - Permission/storage export: Operations triggered from event handlers - File search: Background search execution ## Message Queue Pattern **For logging from background runspaces:** ```powershell # Background function enqueues messages function BgLog([string]$m, [string]$c="LightGreen") { $Sync.Queue.Enqueue([PSCustomObject]@{ Text=$m; Color=$c }) } # Main thread timer dequeues and displays $tmr.Add_Tick({ while ($sync.Queue.Count -gt 0) { $msg = $sync.Queue.Dequeue() _Tpl-Log -Box $textBox -Msg $msg.Text -Color $msg.Color } }) ``` **Rationale:** Avoids cross-thread UI access violations by queueing messages from worker thread. ## Common Testing Patterns in Code **Null/Existence Checks:** ```powershell # Before using objects if ($script:LogBox -and !$script:LogBox.IsDisposed) { ... } if ($data -and $data.Count -gt 0) { ... } if ([string]::IsNullOrWhiteSpace($value)) { return $false } ``` **Error Logging in Loops:** ```powershell # Catch errors in data processing, log, continue foreach ($item in $items) { try { # Process item } catch { BgLog " Skipped: $($_.Exception.Message)" "DarkGray" } } ``` **Validation Before Operations:** ```powershell function Validate-Inputs { if ([string]::IsNullOrWhiteSpace($script:txtClientId.Text)) { [System.Windows.Forms.MessageBox]::Show(...) return $false } return $true } # Called before starting long operations if (-not (Validate-Inputs)) { return } ``` ## Data Flow Testing Approach **For Feature Development:** 1. **Manual Test Cases** (observed pattern, not formalized): - Permissions Export: - Select site with multiple libraries - Choose CSV format - Verify CSV contains all libraries and permissions - Test HTML format in browser for interactivity - Storage Metrics: - Run with `PerLibrary` flag - Verify folder hierarchy is captured - Test recursive subsite inclusion - Validate byte calculations - Template Capture/Apply: - Capture from source site - Verify JSON structure - Create new site from template - Verify structure, permissions, settings applied - File Search: - Test regex patterns - Verify date filtering - Test large result sets (pagination) - Check CSV/HTML output 2. **Visual Verification:** - Log output reviewed in RichTextBox for progress - Generated HTML reports tested in multiple browsers - CSV files opened in Excel for format verification ## Fragility Points & Testing Considerations **PnP Connection Management:** - No connection pooling; each operation may create new connection - Interactive auth prompt appears per runspace - **Risk:** Auth failures not consistently handled - **Testing Need:** Mock PnP module or use test tenant **HTML Generation:** - String concatenation for large HTML documents (lines 1475+) - Inline CSS for styling - JavaScript for interactivity - **Risk:** Complex HTML fragments prone to markup errors - **Testing Need:** Validate HTML structure and JavaScript functionality **JSON Persistence:** - Profiles, templates, settings stored in JSON - ConvertTo-Json/-From-Json without depth specification can truncate - **Risk:** Nested objects may not round-trip correctly - **Testing Need:** Validate all object types persist/restore **Background Runspace Cleanup:** - Runspace and PowerShell objects must be disposed - Timer must be stopped and disposed - **Risk:** Resource leaks if exception occurs before cleanup - **Testing Need:** Verify cleanup in error paths ## Suggested Testing Improvements **Unit Testing:** 1. Extract pure functions (no UI/file system dependencies) - `Format-Bytes`, `EscHtml`, `Merge-PermissionRows` - HTML generation functions 2. Use Pester framework for PowerShell unit tests: ```powershell Describe "Format-Bytes" { It "Formats bytes to GB" { Format-Bytes (1GB * 2) | Should -Be "2 GB" } } ``` 3. Mock file system and PnP operations for integration tests **Integration Testing:** 1. Use test SharePoint tenant for functional testing 2. Automate report generation and validation 3. Script common user workflows **Regression Testing:** 1. Maintain test suite of sites with known structures 2. Generate reports, compare outputs 3. Run before major releases --- *Testing analysis: 2026-04-02*