Use ARM template test toolkit

The Azure Resource Manager (ARM) template test toolkit checks whether your template uses recommended practices. When your template isn't compliant with recommended practices, it returns a list of warnings with the suggested changes. By using the test toolkit, you can learn how to avoid common problems in template development.

The test toolkit provides a set of default tests. These tests are recommendations but not requirements. You can decide which tests are relevant to your goals and customize which tests are run.

This article describes how to run the test toolkit and how to add or remove tests. For descriptions of the default tests, see toolkit test cases.

The toolkit is a set of PowerShell scripts that can be run from a command in PowerShell or CLI.

Install on Windows

  1. If you don't already have PowerShell, install PowerShell on Windows.

  2. Download the latest .zip file for the test toolkit and extract it.

  3. Start PowerShell.

  4. Navigate to the folder where you extracted the test toolkit. Within that folder, navigate to arm-ttk folder.

  5. If your execution policy blocks scripts from the Internet, you need to unblock the script files. Make sure you're in the arm-ttk folder.

    Get-ChildItem *.ps1, *.psd1, *.ps1xml, *.psm1 -Recurse | Unblock-File
    
  6. Import the module.

    Import-Module .\arm-ttk.psd1
    
  7. To run the tests, use the following command:

    Test-AzTemplate -TemplatePath \path\to\template
    

Install on Linux

  1. If you don't already have PowerShell, install PowerShell on Linux.

  2. Download the latest .zip file for the test toolkit and extract it.

  3. Start PowerShell.

    pwsh
    
  4. Navigate to the folder where you extracted the test toolkit. Within that folder, navigate to arm-ttk folder.

  5. If your execution policy blocks scripts from the Internet, you need to unblock the script files. Make sure you're in the arm-ttk folder.

    Get-ChildItem *.ps1, *.psd1, *.ps1xml, *.psm1 -Recurse | Unblock-File
    
  6. Import the module.

    Import-Module ./arm-ttk.psd1
    
  7. To run the tests, use the following command:

    Test-AzTemplate -TemplatePath /path/to/template
    

Install on macOS

  1. If you don't already have PowerShell, install PowerShell on macOS.

  2. Install coreutils:

    brew install coreutils
    
  3. Download the latest .zip file for the test toolkit and extract it.

  4. Start PowerShell.

    pwsh
    
  5. Navigate to the folder where you extracted the test toolkit. Within that folder, navigate to arm-ttk folder.

  6. If your execution policy blocks scripts from the Internet, you need to unblock the script files. Make sure you're in the arm-ttk folder.

    Get-ChildItem *.ps1, *.psd1, *.ps1xml, *.psm1 -Recurse | Unblock-File
    
  7. Import the module.

    Import-Module ./arm-ttk.psd1
    
  8. To run the tests, use the following command:

    Test-AzTemplate -TemplatePath /path/to/template
    

Result format

Tests that pass are displayed in green and prefaced with [+].

Tests that fail are displayed in red and prefaced with [-].

view test results

The text results are:

[+] adminUsername Should Not Be A Literal (24 ms)
[+] apiVersions Should Be Recent (18 ms)
[+] artifacts parameter (16 ms)
[+] DeploymentTemplate Schema Is Correct (17 ms)
[+] IDs Should Be Derived From ResourceIDs (15 ms)
[-] Location Should Not Be Hardcoded (41 ms)
     azuredeploy.json must use the location parameter, not resourceGroup().location (except when used as a default value in the main template)

Test parameters

When you provide the -TemplatePath parameter, the toolkit looks in that folder for a template named azuredeploy.json or maintemplate.json. It tests this template first and then tests all other templates in the folder and its subfolders. The other templates are tested as linked templates. If your path includes a file named CreateUiDefinition.json, it runs tests that are relevant to UI definition.

Test-AzTemplate -TemplatePath $TemplateFolder

To test one file in that folder, add the -File parameter. However, the folder must still have a main template named azuredeploy.json or maintemplate.json.

Test-AzTemplate -TemplatePath $TemplateFolder -File cdn.json

By default, all tests are run. To specify individual tests to run, use the -Test parameter. Provide the name of the test. For the names, see Test cases for toolkit.

Test-AzTemplate -TemplatePath $TemplateFolder -Test "Resources Should Have Location"

Customize tests

For ARM templates, the toolkit runs all of the tests in the folder \arm-ttk\testcases\deploymentTemplate. If you want to permanently remove a test, delete that file from the folder.

For CreateUiDefinition files, it runs all of the tests in the folder \arm-ttk\testcases\CreateUiDefinition.

To add your own test, create a file with the naming convention: Your-Custom-Test-Name.test.ps1.

The test can get the template as an object parameter or a string parameter. Typically, you use one or the other, but you can use both.

Use the object parameter when you need to get a section of the template and iterate through its properties. A test that uses the object parameter has the following format:

param(
    [Parameter(Mandatory=$true,Position=0)]
    [PSObject]
    $TemplateObject
)

# Implement test logic that evaluates parts of the template.
# Output error with: Write-Error -Message

The template object has the following properties:

  • $schema
  • contentVersion
  • parameters
  • variables
  • resources
  • outputs

For example, you can get the collection of parameters with $TemplateObject.parameters.

Use the string parameter when you need to do a string operation on the whole template. A test that uses the string parameter has the following format:

param(
    [Parameter(Mandatory)]
    [string]
    $TemplateText
)

# Implement test logic that performs string operations.
# Output error with: Write-Error -Message

For example, you can run a regular expression of the string parameter to see if a specific syntax is used.

To learn more about implementing the test, look at the other tests in that folder.

Integrate with Azure Pipelines

You can add the test toolkit to your Azure Pipeline. With a pipeline, you can run the test every time the template is updated, or run it as part of your deployment process.

The easiest way to add the test toolkit to your pipeline is with third-party extensions. The following two extensions are available:

Or, you can implement your own tasks. The following example shows how to download the test toolkit.

{
    "environment": {},
    "enabled": true,
    "continueOnError": false,
    "alwaysRun": false,
    "displayName": "Download TTK",
    "timeoutInMinutes": 0,
    "condition": "succeeded()",
    "task": {
        "id": "e213ff0f-5d5c-4791-802d-52ea3e7be1f1",
        "versionSpec": "2.*",
        "definitionType": "task"
    },
    "inputs": {
        "targetType": "inline",
        "filePath": "",
        "arguments": "",
        "script": "New-Item '$(ttk.folder)' -ItemType Directory\nInvoke-WebRequest -uri '$(ttk.uri)' -OutFile \"$(ttk.folder)/$(ttk.asset.filename)\" -Verbose\nGet-ChildItem '$(ttk.folder)' -Recurse\n\nWrite-Host \"Expanding files...\"\nExpand-Archive -Path '$(ttk.folder)/*.zip' -DestinationPath '$(ttk.folder)' -Verbose\n\nWrite-Host \"Expanded files found:\"\nGet-ChildItem '$(ttk.folder)' -Recurse",
        "errorActionPreference": "stop",
        "failOnStderr": "false",
        "ignoreLASTEXITCODE": "false",
        "pwsh": "true",
        "workingDirectory": ""
    }
}

The next example shows how to run the tests.

{
    "environment": {},
    "enabled": true,
    "continueOnError": true,
    "alwaysRun": false,
    "displayName": "Run Best Practices Tests",
    "timeoutInMinutes": 0,
    "condition": "succeeded()",
    "task": {
        "id": "e213ff0f-5d5c-4791-802d-52ea3e7be1f1",
        "versionSpec": "2.*",
        "definitionType": "task"
    },
    "inputs": {
        "targetType": "inline",
        "filePath": "",
        "arguments": "",
        "script": "Import-Module $(ttk.folder)/arm-ttk/arm-ttk.psd1 -Verbose\n$testOutput = @(Test-AzTemplate -TemplatePath \"$(sample.folder)\")\n$testOutput\n\nif ($testOutput | ? {$_.Errors }) {\n   exit 1 \n} else {\n    Write-Host \"##vso[task.setvariable variable=result.best.practice]$true\"\n    exit 0\n} \n",
        "errorActionPreference": "continue",
        "failOnStderr": "true",
        "ignoreLASTEXITCODE": "false",
        "pwsh": "true",
        "workingDirectory": ""
    }
}

Next steps

To learn about the default tests, see Test cases for toolkit.