19

I want to write a unit-test for some code which generates a powershell script and then check that the script has valid syntax.

What's a good way to do this without actually executing the script?

A .NET code solution is ideal, but a command line solution that I could use by launching an external process would be good enough.

1

3 Answers 3

33

I stumbled onto Get-Command -syntax 'script.ps1' and found it concise and useful.

ETA from the comment below: This gives a detailed syntax error report, if any; otherwise it shows the calling syntax (parameter list) of the script.

Sign up to request clarification or add additional context in comments.

5 Comments

For me, this just produces the name of the scriupt file.
Indeed it does. Now try it on a script that has syntax errors.
This gives a detailed syntax error report, if any; otherwise it shows the calling syntax (parameter list) of the script. This is much easier to use for a quick error check than the accepted answer.
@royappa: This answer is only useful because of your comment, which has 10 times more information than the answer. +1 for both.
This is just entirely awesome.
15

You could run your code through the Parser and observe if it raises any errors:

# Empty collection for errors
$Errors = @()

# Define input script
$inputScript = 'Do-Something -Param 1,2,3,'

[void][System.Management.Automation.Language.Parser]::ParseInput($inputScript,[ref]$null,[ref]$Errors)

if($Errors.Count -gt 0){
    Write-Warning 'Errors found'
}

This could easily be turned into a simple function:

function Test-Syntax
{
    [CmdletBinding(DefaultParameterSetName='File')]
    param(
        [Parameter(Mandatory=$true, ParameterSetName='File', Position = 0)]
        [string]$Path, 

        [Parameter(Mandatory=$true, ParameterSetName='String', Position = 0)]
        [string]$Code
    )

    $Errors = @()
    if($PSCmdlet.ParameterSetName -eq 'String'){
        [void][System.Management.Automation.Language.Parser]::ParseInput($Code,[ref]$null,[ref]$Errors)
    } else {
        [void][System.Management.Automation.Language.Parser]::ParseFile($Path,[ref]$null,[ref]$Errors)
    }

    return [bool]($Errors.Count -lt 1)
}

Then use like:

if(Test-Syntax C:\path\to\script.ps1){
    Write-Host 'Script looks good!'
}

3 Comments

This is likely the most direct on-point answer to the question. Mine is more general unit testing.
If someone could make this answer a bit more dummy proof, I'd appreciate it. Do I understand correctly that the first and the second code are redundant? Or rather: it's the second one I'm supposed to use?
Could it be that to use the function, you need the -path option? For me only Test-Syntax -path C:\path\to\script.ps1 seems to work, not Test-Syntax C:\path\to\script.ps1
5

PS Script Analyzer is a good place to start at static analysis of your code.

PSScriptAnalyzer provides script analysis and checks for potential code defects in the scripts by applying a group of built-in or customized rules on the scripts being analyzed.

It also integrates with Visual Studio Code.

There are a number of strategies for mocking PowerShell as part of unit tests, and also have a look at Pester.

The Scripting Guy's Unit Testing PowerShell Code With Pester
PowerShellMagazine's Get Started With Pester (PowerShell unit testing framework)

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.