257 lines
7.8 KiB
Markdown
257 lines
7.8 KiB
Markdown
# 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*
|