Added unit tests

This commit is contained in:
simwai 2024-05-21 22:32:03 +02:00
parent 12b5376cb6
commit d124716196
2 changed files with 184 additions and 18 deletions

View File

@ -0,0 +1,151 @@
# Ensure the latest version of Pester is installed and imported
if (-not (Get-Module -ListAvailable -Name Pester | Where-Object { $_.Version -ge [version]"5.3.1" })) {
Install-Module -Name Pester -Force -Scope CurrentUser -SkipPublisherCheck
}
Import-Module -Name Pester -MinimumVersion 5.3.1
# Describe block to contain all tests and setup
Describe "Setup and Tests" {
BeforeAll {
# Construct the absolute path to setup.ps1
$setupScriptPath = Join-Path -Path (Get-Location) -ChildPath "setup.ps1"
# Check if the setup script exists
if (-Not (Test-Path -Path $setupScriptPath)) {
Write-Host "Error: setup.ps1 script not found at path: $setupScriptPath"
exit 1
}
# Load the script to test
. $setupScriptPath
}
Context "Write-Log Tests" -Tag "Unit" {
It "should write INFO level log" {
$logFilePath = Join-Path $env:TEMP "script_log.txt"
Remove-Item $logFilePath -ErrorAction SilentlyContinue
Write-Log -Message "Test Info Message" -Level "INFO"
$logContent = Get-Content $logFilePath
$logContent | Should -Contain "INFO: Test Info Message"
}
It "should write ERROR level log" {
$logFilePath = Join-Path $env:TEMP "script_log.txt"
Remove-Item $logFilePath -ErrorAction SilentlyContinue
Write-Log -Message "Test Error Message" -Level "ERROR"
$logContent = Get-Content $logFilePath
$logContent | Should -Contain "ERROR: Test Error Message"
}
}
Context "Get-UserSelection Tests" -Tag "Unit" {
It "should handle valid input correctly" {
Mock Read-Host { return "A,B,C" }
$options = @("Option1", "Option2", "Option3")
$indices = Get-UserSelection -prompt "Select options" -options $options -defaultChoice "A"
$indices | Should -Be @(0, 1, 2)
}
It "should return indices for selected options" {
Mock Read-Host { return "a,b" }
$options = @("Option1", "Option2", "Option3")
$indices = Get-UserSelection -prompt "Select options" -options $options
$indices | Should -Be @(0, 1)
}
It "should return default choice if no input" {
Mock Read-Host { return "" }
$options = @("Option1", "Option2", "Option3")
$indices = Get-UserSelection -prompt "Select options" -options $options -defaultChoice "C"
$indices | Should -Be @(2)
}
It "should handle mixed valid and invalid input correctly" {
Mock Read-Host { return "A,X,B,Y,C,Z" }
$options = @("Option1", "Option2", "Option3")
$indices = Get-UserSelection -prompt "Select options" -options $options -defaultChoice "A"
$indices | Should -Be @(0, 1, 2)
}
It "should handle invalid input gracefully" {
Mock Read-Host { return "x,y,z" }
$options = @("Option1", "Option2", "Option3")
$indices = Get-UserSelection -prompt "Select options" -options $options -defaultChoice "A"
$indices | Should -Be @()
}
It "should handle input without whitespace" {
Mock Read-Host { return "a,b,c" }
$options = @("Option1", "Option2", "Option3")
$indices = Get-UserSelection -prompt "Select options" -options $options
$indices | Should -Be @(0, 1, 2)
}
}
Context "Exit-Script Tests" -Tag "Unit" {
BeforeAll {
# Set environment variables for the test
$global:OldVirtualPath = "C:\old\path"
$global:LogFilePath = "C:\path\to\logfile.log"
}
BeforeEach {
Mock Write-Log {}
Mock Start-Process {}
Mock Read-Host { return "Y" }
# Backup the original PATH
$global:OriginalPath = $env:PATH
}
AfterEach {
# Restore the original PATH
$env:PATH = $OriginalPath
}
It "should exit with the given exit code without waiting for key press" {
$exitCode = Exit-Script -exitCode 0 -isSubShell $true -waitForKeypress $false
$exitCode | Should -Be 0
}
It "should prompt to open log file on error" {
Exit-Script -exitCode 1 -isSubShell $true -waitForKeypress $false
Assert-MockCalled Read-Host -Exactly 1
Assert-MockCalled Start-Process -Exactly 1
}
It "should restore the environment path if OldVirtualPath is set" {
# Set a different PATH to simulate the change
$env:PATH = "C:\new\path"
Exit-Script -exitCode 0 -isSubShell $true -waitForKeypress $false
$env:PATH | Should -Be "C:\old\path"
}
}
Context "Get-PythonVersionTag Tests" -Tag "Unit" {
It "should return the correct Python version tag" {
Mock Invoke-Expression { param($cmd) return "cp39-win_amd64" }
$tag = Get-PythonVersionTag
$tag | Should -Be "cp39-win_amd64"
}
}
}

View File

@ -14,6 +14,7 @@ function Write-Log {
[string]$Message,
[string]$Level = 'INFO'
)
switch ($Level) {
'INFO' { Write-Host $Message -ForegroundColor Green }
'WARNING' { Write-Host $Message -ForegroundColor Yellow }
@ -47,15 +48,20 @@ function Get-UserSelection {
$_.Trim().ToUpper()
}
# Convert each selection from letter to index
$indices = $selections | ForEach-Object {
if ($_ -match '^[A-Z]$') {
# Ensure the input is a single uppercase letter
[int][char]$_ - [int][char]'A'
# Convert each selection from letter to index and validate
$indices = @()
foreach ($selection in $selections) {
if ($selection -match '^[A-Z]$') {
$index = [int][char]$selection - [int][char]'A'
if ($index -ge 0 -and $index -lt $options.Length) {
$indices += $index
}
else {
Write-Log "Invalid input: $selection. Please enter letters within the valid range of options." -Level 'ERROR'
}
}
else {
Write-Log "Invalid input: $_. Please enter letters between A and Z." -Level 'ERROR'
continue
Write-Log "Invalid input: $selection. Please enter letters between A and Z." -Level 'ERROR'
}
}
@ -65,14 +71,14 @@ function Get-UserSelection {
function Exit-Script {
param (
[int]$exitCode,
[bool]$isSubShell = $true
[bool]$isSubShell = $true,
[bool]$waitForKeypress = $true
)
if ($OldVirtualPath) {
$env:PATH = $OldVirtualPath
}
# Check if the script is exiting with an error and it's not a subshell
if ($exitCode -ne 0 -and $isSubShell) {
Write-Log "Script failed. Would you like to open the log file? (Y/N)" -Level 'PROMPT'
$openLog = Read-Host
@ -81,25 +87,29 @@ function Exit-Script {
}
}
Write-Log "Press any key to exit..."
$host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown") | Out-Null
exit $exitCode
if ($waitForKeypress) {
Write-Log "Press any key to exit..."
$host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown") | Out-Null
}
return $exitCode
}
# Function to handle installation and conflict resolution
function Install-And-Resolve {
# Function to handle installation
function Install {
param ([string]$InputPath)
if (-not $InputPath) {
Write-Log "ERROR: No input provided for installation." -Level 'ERROR'
Write-Log "No input provided for installation." -Level 'ERROR'
Exit-Script -exitCode 1
}
Write-Log "Installing $InputPath..."
$installCmd = if (Test-Path $InputPath) { $VenvPip + @('install', '-r', $InputPath) } else { $VenvPip + @('install', $InputPath) }
$output = & $installCmd[0] $installCmd[1..$installCmd.Length] 2>&1
$output | Out-File $LogFilePath -Append
if ($LASTEXITCODE -ne 0) {
Write-Log "Conflict detected, attempting to resolve..." -Level 'ERROR'
& $VenvPip[0] $VenvPip[1..$VenvPip.Length] 'check' | Out-File "conflicts.txt"
Write-Log "Conflict detected. Exiting now..." -Level 'ERROR'
Exit-Script -exitCode 1
}
}
@ -111,6 +121,11 @@ function Get-PythonVersionTag {
return "$pythonVersion-$architecture"
}
# Exit in test environment
if ($MyInvocation.InvocationName -ne $MyInvocation.MyCommand.Name) {
exit
}
# Check for admin privileges and elevate if necessary
if (-NOT ([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)) {
Write-Log "Requesting administrative privileges..." -Level 'ERROR'
@ -179,7 +194,7 @@ foreach ($index in $selectedIndices) {
$filePath = Join-Path $ProjectDir $RequirementFiles[$index]
if (Test-Path $filePath) {
Install-And-Resolve $filePath
Install $filePath
}
else {
Write-Log "Requirement file not found: $filePath" -Level 'ERROR'