Use ARM template test toolkit

The Azure Resource Manager template (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. This article describes how to run the test toolkit and how to add or remove tests. For more information about how to run tests or how to run a specific test, see Test parameters.

The toolkit is a set of PowerShell scripts that can be run from a command in PowerShell or CLI. These tests are recommendations but not requirements. You can decide which tests are relevant to your goals and customize which tests are run.

The toolkit contains four sets of tests:

Microsoft Learn

To learn more about the ARM template test toolkit, and for hands-on guidance, see Validate Azure resources by using the ARM Template Test Toolkit on Microsoft Learn.

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 [-].

Tests with a warning are displayed in yellow and prefaced with [?].

view test results.

The text results are:

deploymentTemplate
[+] adminUsername Should Not Be A Literal (6 ms)
[+] apiVersions Should Be Recent In Reference Functions (9 ms)
[-] apiVersions Should Be Recent (6 ms)
    Api versions must be the latest or under 2 years old (730 days) - API version 2019-06-01 of
    Microsoft.Storage/storageAccounts is 760 days old
    Valid Api Versions:
    2021-04-01
    2021-02-01
    2021-01-01
    2020-08-01-preview

[+] artifacts parameter (4 ms)
[+] CommandToExecute Must Use ProtectedSettings For Secrets (9 ms)
[+] DependsOn Best Practices (5 ms)
[+] Deployment Resources Must Not Be Debug (6 ms)
[+] DeploymentTemplate Must Not Contain Hardcoded Uri (4 ms)
[?] DeploymentTemplate Schema Is Correct (6 ms)
    Template is using schema version '2015-01-01' which has been deprecated and is no longer
    maintained.

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. Tests are also run for parameter files and all JSON files in the folder.

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 and provide the test name. For the test names, see ARM templates, parameter files, createUiDefinition.json, and all files.

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

Customize tests

You can customize the default tests or create your own tests. If you want to permanently remove a test, delete the .test.ps1 file from the folder.

The toolkit has four folders that contain the default tests that are run for specific file types:

  • ARM templates: \arm-ttk\testcases\deploymentTemplate
  • Parameter files: \arm-ttk\testcases\deploymentParameters
  • createUiDefinition.json: \arm-ttk\testcases\CreateUIDefinition
  • All files: \arm-ttk\testcases\AllFiles

Add a custom test

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