The -or operator is a binary operation that “adds together” the value of the statements you’re testing, which means only one statement needs to be $true before it continues (1 + 0 is 1). The -and operator is a binary operation that “multiplies” the value of two statements, meaning both have to be $true for the evaluation to be $true (1 * 0 is 0).
Programming languages typically stop evaluating the rest of the if statement when it reaches a $true value, so as to not waste CPU cycles doing redundant checks, and the same goes for PowerShell.
An if statement is evaluated from left to right, so in your case you’re doing !$a first, then Test-Path.
You start by assigning $a a value of $null. Now an if statement needs a boolean value, that is a $true or $false value. If cast to a boolean type $null becomes $false, as does an empty string and the number 0, as demonstrated here:
PS C:\Users\mni> [bool]$null
False
PS C:\Users\mni> [bool]""
False
PS C:\Users\mni> [bool]0
False
So what you’re doing is you’re saying if !$a is $true, then proceed. If !$a is $false, then try the next. With $a being null, !$a, or -not $a, is $true, and it never reaches Test-Path. If you want both/all the checks in your if statement to be $true in order to proceed, you want to use -and.
Now if you’re combining both -or and -and operators in your if statement, for example
if($x -eq 1 -and $y -eq 2 -or $z -eq 3) { }
PowerShell first evaluates if $x -eq 1 is $true, and if $y -eq 2 is $true. If this is the case, it proceeds. If it is not the case, it will then evaluate $z -eq 3, and if this is found to be $true it will proceed despite the value of $x and $y.