Im Blog Einfacher Testreport aus Tosca über Jenkins-Testdurchführung habe ich in Form einer ersten Version beschrieben, wie sich mit einfachen Mitteln ein grundlegender Testreport aus den Resultaten der Testdurchführung mit Jenkins erstellen lässt. Die inzwischen gesammelte Erfahrung zeigt, dass der dort beschriebene Ansatz sich in den meisten Fällen als nicht genügend effizient erweisen dürfte. Die Verwendung von Tosca-Testfällen zur Report-Erstellung erfordert verhältnismässig viel Zeit und die Vorgehensweise skaliert nicht. Denn der Aufwand zur Implementierung, Wartung und Durchführung steigt mindestens linear mit der Anzahl an Testfällen, die im Report zu berücksichtigen sind. Zunächst angedacht wurde eine andere Art des Auslesens der relevanten Daten aus den XML-Dateien sowie die Verwendung von XML-Modulen in Tosca. Im weiteren Verlauf hat sich gezeigt, dass der Umweg über Tosca nicht erforderlich ist. Im Folgenden lege ich dar, wie sich derselbe Testreport deutlich effizienter mittels eines PowerShell-Skripts erzeugen lässt.
Aus Gründen des Aufwands und des Zwecks erfolgt die Reporterstellung schneller, wenn dazu keine Tosca-Testfälle erforderlich sind. Stattdessen erfolgt der Prozess zur Erstellung eines Testreports wie in Abb. 1 dargestellt.
Die XSL-Transformation der Jenkins-Resultatdateien vom XML- ins CSV-Format erfolgt sequentiell mittels eines PowerShell-Skripts, das am Ende der Testdurchführung ausgeführt wird. Aus diesen Rohdaten wird schliesslich ein Testreport im HTML-Format generiert.
Eine beispielhafte XML-Datei als Resultat der Jenkins-Testdurchführung sieht wie folgt aus (vgl. Listing 1):
Listing 1: Beispielhafte Jenkins-Resultatdatei im XML-Format
Die relevanten Daten werden jeweils aus dem Beginn des Elements <testcase> extrahiert, und zwar aus diesem Teil:
testcase name=“Finanzieren Smoketests – 01_Grundstück erfassen“ time=“168.5116337″ timestamp=“2020-02-10T16:13:05.6008759+01:00″ log=“+ Passed …
Der XML-Transformation ins CSV-Format liegt das folgende XSL-Stylesheet zugrunde (vgl. Listing 2):
<?xml version="1.0" encoding="UTF-8"?><xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"><xsl:output method="text"/><xsl:template match="/"><xsl:for-each select="testsuites/testsuite/testcase"><xsl:value-of select="@name"/><xsl:text>;</xsl:text><xsl:choose><xsl:when test="@timestamp = ''"><xsl:text>Nicht ausgeführt;</xsl:text></xsl:when><xsl:otherwise><xsl:value-of select="substring(@timestamp,0,11)"/><xsl:text> </xsl:text><xsl:value-of select="substring(@timestamp,12,8)"/><xsl:text>;</xsl:text></xsl:otherwise></xsl:choose><xsl:choose><xsl:when test="not(@log)"><xsl:text>--
</xsl:text></xsl:when><xsl:otherwise><xsl:value-of select="substring(@log,3,6)"/><xsl:text>
</xsl:text></xsl:otherwise></xsl:choose></xsl:for-each></xsl:template></xsl:stylesheet>
Listing 2: XSL-Stylesheet für die XML-Transformation
Mittels des folgenden PowerShell-Skripts werden aus dieser Jenkins-Resultatdatei im XML-Format die für den Testreport relevanten Daten extrahiert und im CSV-Format gespeichert (vgl. Listing 3). Zugrunde liegt dabei ein ähnliches Skript, das unter XSL Transformation von XML-Dokumenten per PowerShell beschrieben wird. Aufgelistet sind nur die inhaltlich relevanten Funktionen (z.B. ohne Pfadprüfung oder Fehlerbehandlung).
# XML-Transformation mit einer XSLT-Datei ins CSV- und HTML-Format# Skript-Aufruf: *.ps1 [XML-QuellDatei(en)] [XSLT-Datei] [Fachgebiet]# Parameterinitialisierungparam ( $xml = @("D:\Tosca\Resultat\Jenkins\Finanzieren\Eigenheim_Resultat.xml","D:\Tosca\Resultat\Jenkins\Finanzieren\ Smoketests_Resultat.xml"), $xslt = "D:\Tosca\Resultat\XSL\XSL-Stylesheet.xsl", $area = "Finanzieren" )# Funktion für die XML-Transformationfunction XML-Transformation($xml, $xsltFile, $area){ # Zeitstempel erstellen $timestamp = ([datetime]::now).tostring("yyyy-MM-dd HH-mm") # Temporäre CSV-Ausgabedatei definieren $csv = "D:\Tosca\Resultat\XSL\Testreport.csv" # Resultatdateien mit Pfad initialisieren $resultCSV = "D:\Tosca\Resultat\XSL\Report_" + $area + "_$timestamp.csv" $resultHTML = "D:\Tosca\Resultat\XSL\Report_" + $area + "_$timestamp.html" # Header in die CSV-Datei schreiben Add-Content -Path $resultCSV -Value 'Testfall;Zeitstempel;Testergebnis' # Array der XML-Inputdateien bearbeiten ForEach ($xmlFile in $xml) { $xmlFile = resolve-path $xmlFile # XSL-Objekt erstellen $script:xslt = new-object system.xml.xsl.xslcompiledtransform $script:xslt = new-object system.xml.xsl.xsltransform $xslt.Load($xsltFile) # Xslt-Datei laden $xslt.Transform($xmlFile, $csv) # XSLT-Transformation ausführen # Ergebnis in Resultatdatei anhängen Add-Content -Path $resultCSV -Value (Get-Content $csv) -Encoding UTF8 } # Temporäre Ausgabedatei löschen Remove-Item $csv}# Funktionsaufruf zur XML-TransformationXML-Transformation $xml $xslt $area
Listing 3: PowerShell-Skript zur XSL-Transformation ins CSV-Format
Die folgenden Parameter können beim Skriptaufruf übergeben werden:
-xmlJenkins-Resultatdateien im XML-Format als kommagetrennte Liste-xslPfad zur XSLT-Stylesheet-Datei (optional, wenn im Skript hinterlegt)-areaFachbereich (z.B. Finanzieren, Zahlungsverkehr)
Ein weiterer Parameter könnte dazu verwendet werden, die Ablage der generierten Reportdateien zu bestimmen.
Das Ergebnis im CSV-Format sieht beispielsweise so aus:
Finanzieren Smoketests – Grundstück erfassen;2020-02-10 16:13:05;Passed
Finanzieren Smoketests – Versicherung erfassen;2020-02-10 16:16:58;Passed
Finanzieren Smoketests – Finanzierung zusammenstellen;2020-02-10 16:19:37;Failed
Kreditportfolio überprüfen;Nicht ausgeführt;–
Da der Import ins binäre Format von Microsoft Excel kein einfacher Prozess ist und der Testreport primär über das reine Testergebnis informieren soll, wird dafür das HTML-Format eingesetzt. Wie im vorherigen Blog erwähnt, liesse sich der Excel-Import mittels Tosca durchführen. Darauf wird hier jedoch verzichtet.
Die Transformation der CSV-Rohdaten in einen HTML-Testreport erfolgt mit dem zweiten Teil des PowerShell-Skripts am Ende der Funktion zur XML-Transformation (vgl. Listing 4; reduziert auf die wesentlichen Inhalte):
$head = @"<title>Testreport</title><meta charset="utf-8"><style type="text/css"> BODY{background-color:#FFFFFF;color:black;font-family:Arial,sans-serif;font-size:14px;margin:25pt;} TABLE{border-width:2px;border-style:solid;border-color:black;border-collapse:collapse;} TH{border-width:1px;padding:8px;border-style:solid;border-color:black;background-color:#D5D8DC; font-size:18px;text-align:left;} TD{border-width:1px;padding:8px;border-style:solid;border-color:black;background-color:#F9F9F9;}</style><script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.4.4/jquery.js"></script><script type="text/javascript"> jQuery(document).ready(function(){ jQuery('td:contains("Passed")').css('background-color','#2ECC71'); jQuery('td:contains("Failed")').css('background-color','#EC7063'); jQuery('td:contains("--")').css('background-color','#D0D3D4'); });</script>"@ $body = "<h1>Testreport $area</h1>" Import-Csv -Delimiter ";" -Path $resultCSV -Encoding UTF8 | ConvertTo-Html -Head $head -Body $body | Out-File $resultHTML
Listing 4: PowerShell-Skript zur Erstellung des HTML-Testreports aus der CSV-Datei
Der Testreport im HTML-Format lässt sich beispielsweise so wie in Abb. 2 gestalten:
Abb. 2: Testreport im HTML-Format
Die Konfiguration für die Jenkins-Testdurchführung ist in Listing 5 dargestellt:
pipeline { agent any options { timeout(time: 120, unit: 'MINUTES') } parameters { choice(name: 'ENV', choices: ['CT', 'INT'], description: 'Selektiere Environment') } environment { TRICENTIS_CI_HOME = 'C:\\Program Files (x86)\\TRICENTIS\\Tosca Testsuite\\ToscaCommander\\ToscaCI\\Client' TRICENTIS_CI_CONFIG = 'D:\\Tosca\\Konfigurationen\\' TRICENTIS_CI_ENVIRONMENT = "${params.ENV}" JUNIT_RESULT_FILE = 'D:\\Tosca\\Resultat\\Jenkins\\Finanzieren' } stages { stage('Kreditantrag erstellen') { steps { parallel("Eigenheim": { echo "Starten der Tosca-Tests für Finanzierung: Eigenheim" bat label: 'Eigenheim', script: '"%TRICENTIS_CI_HOME%\\ToscaCIClient.exe" -t junit -r "%JUNIT_ RESULT_FILE%\\Eigenheim_Resultat.xml" -m distributed -c "%TRICENTIS_CI_CONFIG%\\%TRICENTIS_CI _ENVIRONMENT%_Finanzieren_Eigenheim.xml"' } ) } } stage('Prozessneutrale Tests') { steps { parallel("Smoketests": { echo "Starten der Tosca-Tests für Finanzierung: Smoketests" bat label: 'Smoketests', script: '"%TRICENTIS_CI_HOME%\\ToscaCIClient.exe" -t junit -r "%JUNIT_ RESULT_FILE%\\Smoketests_Resultat.xml" -m distributed -c "%TRICENTIS_CI_CONFIG%\\%TRICENTIS_ CI_ENVIRONMENT%_Finanzieren_Smoketests.xml"' } ) } } stage('Testreport') { steps { parallel("Testreport": { echo "Starten des Testreports" bat label: 'Testreport', script: '"C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell. exe" -ExecutionPolicy Bypass -Command "D:\\Tosca\\Resultat\\XSL\\XML-Transformation.ps1" -xml "%JUNIT_RESULT_FILE%\\Eigenheim_Resultat.xml,%JUNIT_RESULT_FILE%\\Smoketests_Resultat.xml" -area "Finanzieren"' } ) } } }}
Listing 5: Beispielhafte Jenkins-Konfiguration
Mit PowerShell lässt sich diese Reportdatei im HTML-Format als Anhang automatisch an die gewünschten Empfänger versenden (vgl. Emails mit PowerShell versenden). Der Testreport kann auch direkt in die E-Mail integriert werden, wenn das HTML-Format zugelassen ist. Mit der Version zur HTML-Generierung in Listing 4 geht dabei die farbliche Hervorhebung des Testergebnisses verloren, da die Ausführung von JavaScript bei E-Mails im HTML-Format aus Sicherheitsgründen meist deaktiviert ist. Dafür können bei der Umwandlung des CSV-Reports in HTML-Code in der Spalte «Testergebnis» CSS-Klassen für die visuelle Unterscheidung eingesetzt werden. Die Skript-Definitionen mit den jQuery-Funktionen sind dann nicht erforderlich. Das entsprechend angepasste Skript findet sich in Listing 6:
$head = @"<title>Testreport</title><meta charset="utf-8"><style type="text/css"> BODY{background-color:#FFFFFF;color:black;font-family:Arial,sans-serif;font-size:14px;margin:25pt;} TABLE{border-width:2px;border-style:solid;border-color:black;border-collapse:collapse;} TH{border-width:1px;padding:8px;border-style:solid;border-color:black;background-color:#D5D8DC; font-size:18px;text-align:left;} TD{border-width:1px;padding:8px;border-style:solid;border-color:black;background-color:#F9F9F9;} TD.passed {background-color:#58D68D} TD.failed {background-color:#EC7063} TD.unexecuted {background-color:#D0D3D4}</style>"@ $body = "<h1>Testreport $area</h1>" Import-Csv -Delimiter ";" -Path $resultCSV -Encoding UTF8 | ConvertTo-Html -Head $head -Body $body | ForEach { if ($_ -like "*<td>Passed*") {$_ -replace "<td>Passed", "<td class=`"passed`">Passed"} elseif ($_ -like "*<td>Failed*") {$_ -replace "<td>Failed","<td class=`"failed`">Failed"} else {$_ -replace "<td>--", "<td class=`"unexecuted`">--"}} | Out-File $resultHTML
Listing 6: Angepasstes PowerShell-Skript zur Erstellung des HTML-Testreports aus der CSV-Datei
Eine andere Option könnte der Versand einer E-Mail über ein Jenkins-Plugin sein, nachdem der Testlauf (resp. Build) ausgeführt worden ist. Diese Variante wurde jedoch nicht weiter geprüft, da sich der Prozess mit der gewählten Vorgangsweise direkter steuern lässt.
Das Passwort für den Zugang zum Mailserver sollte verschlüsselt abgelegt werden. Dies kann in PowerShell mit dem Code in Listing 7 erfolgen:
$KeyFile = "C:\Temp\AES256.key"$PasswordFile = "C:\Temp\Passwort.txt"$Password = "Passwort"# Schlüsseldatei mit AES-256 erzeugen$CryptoKey = New-Object Byte[] 32[Security.Cryptography.RNGCryptoServiceProvider]::Create().GetBytes($CryptoKey)$CryptoKey | out-file $KeyFile# Passwort verschlüsseln$CryptoKey = Get-Content $KeyFile$SecurePassword = $Password | ConvertTo-SecureString -AsPlainText -Force$SecurePassword | ConvertFrom-SecureString -key $CryptoKey | Out-File $PasswordFile
Listing 7: Erzeugung eines verschlüsselten Passwortes in PowerShell
Der Testreport kann im Hauptteil der E-Mail mitgesandt werden (vgl. Listing 8 – reduziert auf die wesentlichen Inhalte, ohne Fehlerbehandlung).
# Zugangsdaten$KeyFile = "C:\Temp\AES256.key"$PasswordFile = "C:\Temp\Passwort.txt"$MailUser = "Benutzername"# SMTP-Einstellungen$PSEmailServer = "mail.example.com"$smtpFrom = "absender@example.com"$smtpTo = "empfaenger@example.com"$messageSubject = "Testreport " + $area$messageBody = (Get-Content ".\Report_Finanzieren_2020-02-10 16-32.html" | Out-String)# Zugangsdaten erzeugen$CryptoKey = Get-Content $KeyFile$creds = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $MailUser, (Get-Content $PasswordFile | ConvertTo-SecureString -Key $CryptoKey)# E-Mail versendenSend-MailMessage -Credential $creds -From $smtpFrom -To $smtpTo -Subject $messageSubject -Body $messageBody -BodyAsHtml -Encoding ([System.Text.Encoding]::UTF8) -port 587 -UseSsl
Listing 8: Automatischer E-Mail-Versand mittels PowerShell
Abhängig von der Konfiguration der konkreten Umgebung ist für Send-MailMessage anstelle der letzten beiden Parameter auch nur -port 25 zu verwenden, z.B. auf dem Jenkins-Server.
Zu prüfen wäre der Einsatz von Jenkins-Plugins für denselben Zweck der Reportgenerierung und -verteilung basierend auf den XML-Resultatdateien, z.B. HTML Publisher oder Test Results Aggregator. Abhängig vom genauen Verwendungszweck erlaubt die hier beschriebene Vorgehensweise jedoch eine gezieltere Verwendung, indem die Konfiguration leichter oder überhaupt erst anzupassen ist (z.B. beim Versand von E-Mail-Anhängen).
Diese Darlegung hat gezeigt, wie sich ein Report über die Durchführung von Tests mit Jenkins in wenigen Sekunden erstellen lässt. Im Vergleich zum Einsatz von Tosca-Testfällen erfolgt die Reportgenerierung in einem Bruchteil des vorherigen Zeitbedarfs. Der Konfigurationsaufwand ist deutlich geringer, insofern nicht mehr pro sachlichem Testfall Strukturen zu definieren sind, sondern nur noch einmal pro Fachgebiet und entsprechend der Gliederung der Jenkins-Resultatdateien. Diese Art der Reporterzeugung erlaubt einen vielseitigeren Einsatz. Um neu hinzugekommene Testfälle zu berücksichtigen, sind bei Bedarf nur die Jenkins-Konfigurationsdateien anzupassen. Zudem ist die Verteilung per E-Mail ein effizienter Weg zur direkten Information der relevanten Kreise.
Sie möchten unsere Expertise nutzen und technologische Innovationen umsetzen?
Haben Sie eine Frage oder suchen Sie weitere Informationen? Geben Sie Ihre Kontaktinformationen an und wir rufen Sie zurück.