PowerShell Modul Entwicklung: Pester Tests

This post is also available in English

Mittels Pester Tests lässt sich bei der PowerShell Modul Entwicklung ein Grad an Qualität sicherstellen, die man sonst nur sehr aufwändig manuell erreichen würde. Dabei gilt es zwei wichtige Faktoren zu prüfen. Modul- und Funktions-Integrität.

Funktions-Integrität

Auf diesen Punkt werde ich in einem späteren Blogeintrag genauer eingehen. Kurz gesagt muss die eigentliche Funktion des Moduls sichergestellt werden.

Ein beliebtes Beispiel ist eine Funktion die zwei Zahlen addiert. Pester erlaubt es zu prüfen ob die Funktion bei der Übergabe von 2 + 3 wirklich 5 zurückliefert.
Bei einem echtem Modul ist dies schnell komplexer.

Modul-Integrität

Alle Funktionen in einem Modul und auch das Modul selbst sollten gewissen Qualitätsanforderungen entsprechen und natürlich gültige PowerShell Scripte beinhalten.

Bei der Entwicklung meines Moduls AzureSimpleREST habe ich mich umgesehen wie andere Entwickler dies bewerkstelligen. Bei Kevin Marquette bin ich über seinen Blogeintrag „PowerShell: Let’s build the CI/CD pipeline for a new module“ fündig geworden und habe damit die Basis für mein Modul Pester Test gefunden.

Dabei sollten folgende Punkte berücksichtigt werden:

  • Ist in jeder PowerShell Datei auch valider Code
  • Ist das Modul Manifest, die Beschreibung des Moduls, gültig
  • Sind die exportierten Funktionen im Manifest vorhanden
  • Werden interne Funktionen nicht exportiert
  • Sind alle Aliasse im Manifest definiert
  • Entsprechen die Scripte den PSScriptAnalyzer Best Practice

Nicht alle diese Funktionen hat die ursprüngliche Version mitgebracht, daher habe ich Sie stark erweitert und modifiziert. Im Folgenden werde ich die einzelnen Tests erklären. Das komplette Script findet Ihr im GitHub Repo.

Pester Tests

Allgemeine Variablen

Einige der folgenden Variablen werden in den Tests weiter verwendet z.B. für die Namen der Tests oder Pfadangaben. Außerdem ermöglich das dynamische Auslesen des Modulnamens, -Manifests und -Pfads ein einfaches Wiederverwenden.

Modulprüfung

Jedes PowerShell Script, sowie das Modul Manifest und die Modul Datei wird im Abschnitt ‚Basic Module Testing‘ überprüft. Dabei wird vorerst nur geprüft ob es gültigen PowerShell Code und keine Syntaxfehler enthält.
Zusätzlich wird geprüft ob die Datei vorhanden ist und zum Abschluss ob das Modul sauber importiert werden kann.

PowerShell Manifest prüfen

Im nächsten Abschnitt wird die Manifest Datei (PSD1) überprüft. Dazu gehören folgende Tests

  • Gibt es kritische Fehler in der Manifestdatei (Test-ModuleManifest)
  • Entspricht der Name des Moduls dem im Manifest
  • Ist eine Version hinterlegt
  • Wurde eine Beschreibung definiert
  • Ist die Modul Datei (PSM1) vorhanden
  • Wurde die eindeutige Modul GUID nicht verändert
  • Werden keine „Format Files“ exportiert
  • Sind alle benötigten Module auch angegeben

Funktionen

Bei den Funktionen wird geprüft ob diese in der Manifest Datei angegeben sind und somit sauber in der PowerShell Gallery angezeigt werden. Das wird einmal anhand der Dateinamen gemacht und abschließend noch geprüft ob die Anzahl korrekt ist. So vergisst man nicht eine neue Funktion einzutragen.

Bei den internen Funktionen, also Funktionen die nicht für den Endanwender gedacht sind, wird geprüft ob der Aufruf auch einen Fehler provoziert.

Aliasse

Auch bei den Aliassen wird geprüft ob diese alle im Manifest hinterlegt sind und ob auch alle exportiert werden.

PSScriptAnalyzer

Der Abschnitt für die PSScriptAnalyzer Tests ist etwas umfangreicher. Das Modul ‚PSScriptAnalyzer‘ erlaubt die automatisierte Prüfung der Scripte in einem Modul auf bestimmte Best Practices. Somit ist sichergestellt das z.B. keine unnötigen Leerzeichen in den Scripten sind oder auch das keine Variablen deklariert werden, die später nicht verwendet werden. Aktuell kann das Script 55 verschiedene Regeln prüfen, wobei ich nur 45 nutze.
Alles was der Severity Warning oder Error entspricht wird so als Fehler gewertet.

Im Internet finden sich viele Implementierungen für Pester und jede hat Ihre Vorzüge. Persönlich war es mir wichtig auch anzuzeigen wenn eine Datei „sauber“ ist, also keine Regelverstöße meldet.
Außerdem sollte jeder Verstoß in den Tests genau zu sehen sein und nicht nur der Hinweis auf mehrere Fehler in einer Funktion.

Dazu musste ich etwas in die Trickkiste greifen.

Alle Verstöße gegen die definierten Regeln werden in die Variable $ScriptAnalyzerErrors geschrieben und anschließend in ein PSCustomObject $testCase geschrieben.
Dabei werden der Regelname, Scriptname, der Fehler sowie Zeilennummer und Severity gespeichert. Aus diesen Fehlern generiert Pester jetzt dynamische Tests die in Ihrem Namen den Funktionsname, den Fehler und die Zeilennummer beinhalten. So ist es leicht nachvollziehbar warum der Test fehlgeschlagen ist und was korrigiert werden muss.

Zusätzlich werden alle Funktionen mit Fehlern in die Variable $FunctionsWithErrors geschrieben. Diese Variable wird anschließend mit der kompletten Liste von Funktionen verglichen und solche ohne Fehler in die Variable $FunctionsWithoutErrors gespeichert.
Diese Liste wird dann genutzt um eine Reihe an immer erfolgreichen Tests zu generieren und somit jene zu belohnen die keine Fehler gemacht haben.

Ich arbeite als IT Consultant bei Aequitas Integration und habe einen Fokus auf die Microsoft Enterprise Produktpalette.
Jedoch beschäftige ich mich schon lange auch mit Linux und finde auch die unteren OSI Schichten interessant.