BeforeDiscovery ou BeforeAll?

En ce moment je travaille beaucoup avec Pester.

Pester c’est un outil de tests unitaires pour PowerShell. Comme tous les outils de ce genre il apporte un support aux scénarios Data Driven Test.

C’est justement là que j’ai rencontré une difficulté qui m’a fait perdre un peu de temps. Je vais la discuter ici.

Le scénario

[CmdletBinding()]
param(
    [Array]$resources,
	[string]$resourceGroupName
)

Describe 'Testing webapps deployment' {
    BeforeAll {
        $data = @()

        $data += foreach ($resourceToDeploy in $resources) {
  
            
            @{
                webappNameName   = $resourceToDeploy.name 
            }
        }
    }

    It "Webapps <resourceName> exists" -TestCases $data {
        param($webappNameName)

        $instance = Get-AzResource -ResourceGroupName $resourceGroupName -Name $webappNameName -ErrorAction SilentlyContinue
        $instance | Should -Not -BeNullOrEmpty $webappNameName
    }
}

Un test attend un paramètre $resourceGroupName et un tableau $resources en entrée. Je construis un bloc BeforeAll dans laquelle je créé un tableau de valeurs appelées $parameters. Ce paramètre est ensuite injecté dans mes tests It avec l’attribut -TestCases. Chaque item est ensuite consommé par le test.

Le problème

Le problème est assez simple, le test ne reçoit qu’un tableau vide.

L’explication

Oh rien de très compliqué, une mauvaise compréhension de la documentation.

Un test Pester est composé de deux phases:

  1. découverte (discovery)
  2. exécution (run)

Durant la phase de découverte, Pester découvre et analyse les fichiers. Il recherche les blocs comme Describe, Context

On peut découvrir les détails ici:

Discovery and Run | Pester

Le problème est donc là. BeforeAll est évalué durant l’exécution. Les variables créées lors de cette phase ne seront donc pas disponibles durant la découverte.

Hors c’est précisément durant cette phase que –TestCases est évalué. Je tente donc d’utiliser une variable, $data, avant qu’elle ne soit créée.

La façon correcte d’écrire ce test est donc:

[CmdletBinding()]
param(
    [Array]$resources,
	[string]$resourceGroupName
)


BeforeDiscovery {
	$parameters = @()

	$parameters += foreach ($resourceToDeploy in $resources) {
		@{
			webappNameName   = $resourceToDeploy.name 
		}
	}
}

Describe 'Testing webapps deployment' {
	It "Webapps <resourceName> exists" -TestCases $parameters {
		param($webappNameName)

		$instance = Get-AzResource -ResourceGroupName $resourceGroupName -Name $webappNameName -ErrorAction SilentlyContinue
		$instance | Should -Not -BeNullOrEmpty $webappNameName
	}
}

La règle générale sera donc:

  • Le code de test:
    dans les blocs It, BeforeAll, BeforeEach, AfterAll, AfterEach
  • Code non directement lié aux tests:
    Describe, Contexte, BeforeDiscovery

 

Un dernier point: Pester, contrairement à PowerShell est sensible à la casse.

Laisser un commentaire