Powershell Skripte können je nach Anwendungsfall komplex werden. Daher sind auch für Robustheit und Qualität automatisierte Tests wichtig. Das Powershell Module Pester hat sich hierfür bewährt und lässt wenig Wünsche offen.

Powershell kommt aber auch häufig zum Einsatz, wenn es darum geht verschiedene Systeme oder Dienste zu integrieren, also für Dateiaustausch oder Deployment. Das Mocken von Funktionen kommt dabei schnell an Grenzen. Tests gegen existirerende Systeme sind nicht immer möglich oder schwer zu isolieren.

Eine mögliche Lösung ist hier Docker Container zu verwenden. Im Test-Setup können die benötigten Dienste und Server als Container instanziiert werden und im Tear-Down einfach wieder gelöscht werden. Zur besseren Integration von Powershell und Docker habe ich dazu PSDocker entwickelt.

Demo

Hier ein Beispiel zum Test eines SFTP-Skriptes.
Vor dem Start muss erst Pester und PSDocker installiert werden:

Install-Module Pester -Scope CurrentUser
Install-Module PSDocker -Scope CurrentUser

Dann geht es los mit der Testdefinition für die Funktion Connect-Server.

Describe 'Connect-Server' {

Wir erzeugen einen neuen Kontext mit einem laufenden SFTP-Server.

    Context 'running SFTP server' {

Um diesen Kontext herzustellen, erzeugen wir einen neuen Docker Container.
Wir installieren das Docker Image aus einem Repository (atmoz/sftp) für den Fall, dass es noch nicht existiert, mit der Funktion Install-DockerImage. Das entspricht einem docker pull. Das Ergebnis ist ein Image-Objekt, dass an die Funktion New-DockerContainer übergeben wird um einen neuen Container zu erzeugen. Dazu werden noch Portmapping, Umgebungsvariablen und gemappte Verzeichnisse spezifiziert.
Die Funktion New-DockerContainer entspricht einem docker run. Das Ergebnis davon ist dann ein Container-Objekt, dass wir noch mit der Eigenschaft VolumePath erweitern, die wir später im Test verwenden wollen und uns den lokalen Pfad gibt, den der Docker Container intern verwendet.

        BeforeAll {
            $container = Install-DockerImage `
                -Repository 'atmoz/sftp' |
            New-DockerContainer `
                -Ports @{ 2222 = 22 } `
                -Environment @{
                    SFTP_USERS = 'myuser:mypass:::upload'
                } `
                -Volumes @{ 
                    $Testdrive.FullName = '/home/myuser/upload'
                } `
                -Detach
            $container | Add-Member VolumePath $Testdrive.FullName | Out-Null
        }

Zum Aufräumen des Kontext, nach abschluss der Tests, löschen wir den Container wieder mit Remove-DockerContainer.

        AfterAll {
            Remove-DockerContainer -Name $Container.Name -Force
        }

Der Rest ist ein relativ normaler Pester-Test. Wir definieren diverse Testfälle für die Funktion Connect-Server. Also z.B. mit oder ohne bekanntem Fingerprint oder ob die Funktion bei ungültigen Parametern eine Fehlermeldung erzeugt.

        It 'connects with any fingerprint' {
            $session = Connect-ScpServer `
                -HostName 'localhost' `
                -Port 2222 `
                -UserName 'myuser' `
                -Password 'mypass' `
                -AnyFingerprint

            $session.Opened | Should -Be $true
        }

        It 'connects with correct fingerprint' {
            $fingerprint = Get-ScpFingerprint `
                -HostName 'localhost' `
                -Port 2222 `
                -UserName 'myuser' `
                -Password 'mypass' `
                -AnyFingerprint `
                -Algorithm SHA256

            $session = Connect-ScpServer `
                -HostName 'localhost' `
                -Port 2222 `
                -UserName 'myuser' `
                -Password 'mypass' `
                -Fingerprint $fingerprint

            $session.Opened | Should -Be $true
        }

        It 'fails with wrong fingerprint' {
            {
                Connect-ScpServer `
                    -HostName 'localhost' `
                    -UserName 'myuser' `
                    -Password 'mypass' `
                    -Fingerprint 'nonsense'
            } | Should -Throw
        }
    }
}

Fazit

Wieder eine Ausrede weniger, nicht zu testen 🙂

0 Kommentare

Dein Kommentar

An Diskussion beteiligen?
Hinterlasse uns Deinen Kommentar!

Schreiben Sie einen Kommentar

Ihre E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert