4.3. Definieren des Berichts-Layouts

Klaros-Testmanagement verwendet das JBoss Seam PDF Framework um den Bericht zu erzeugen und die bereitgestellten Daten in das Layout-Template einzufügen.

  1. Wir starten mit einem leeren Dokument, das nur eine Kopf- und eine Fußzeile enthält.

    <p:document xmlns:ui="http://java.sun.com/jsf/facelets"
      xmlns:f="http://java.sun.com/jsf/core"
      xmlns:p="http://jboss.org/schema/seam/pdf"
      title="Klaros-Testmanagement Test Plan Report" marginMirroring="true"
      author="#{user.name}" creator="#{user.name}" pageSize="A4">
      <f:facet name="header">
        <p:font size="8">
          <p:header borderWidthBottom="0.1" borderColorBottom="black" borderWidthTop="0" alignment="center">
            <p:text value="Test Run Report - Generated on #{date} by #{user.name}" />
          </p:header>
          <p:footer borderWidthTop="0.1" borderColorTop="black" borderWidthBottom="0" alignment="center">
            <p:text value="Page " />
            <p:pageNumber />
            <p:text value=" - Created with Klaros-Testmanagement (www.klaros-testmanagement.com)" />
          </p:footer>
        </p:font>
      </f:facet>
      <p:paragraph>
        <p:text value=" " />
      </p:paragraph>
    </p:document>
    

    Dieses Codefragment erzeugt eine Kopfzeile, welche auf jeder Seite angezeigt wird. Diese beinhaltet das Datum der Erstellung und den Namen des Klaros-Testmanagement Benutzers, welcher den Report erzeugt hat. Die Fußzeile enthält die Seitennummer und einen Text, dass der Report mit Klaros-Testmanagement erstellt wurde. Für die Kopfzeile wurde das Attribut borderWidthBottom verwendet um die Kopfzeile vom restlichen Inhalt der Seite abzusetzen. Entsprechend wurde für die Fußzeile das Attribut borderWidthTop gesetzt.

  2. Als nächstes erstellen wir eine Titelseite, auf der die wichtigsten Informationen über den Bericht zusammengefasst sind.

    Für die Formatierung des Deckblattes verwenden wir hauptsächlich <p:paragraph> Elemente. Diese Elemente beschreiben die Textposition über ihre Attribute alignment und spacing. Um die Schriftart der Paragraphen zu wechseln, können Sie das <p:font> Element benutzen. Um Text hervorzuheben, können Sie die style und size Attribute des <p:font> Elements benutzen.

      <p:paragraph alignment="center" spacingAfter="100">
            <p:text value="" />
        </p:paragraph>
        <p:font style="bold" size="32">
            <p:paragraph alignment="center" spacingAfter="75">
                <p:text value="Test Run Report" />
            </p:paragraph>
        </p:font>
        <p:font style="normal" size="12">
            <p:paragraph alignment="center" spacingAfter="5">
                <p:text value="Created by" />
            </p:paragraph>
        </p:font>
        <p:font style="bold" size="16">
            <p:paragraph alignment="center" spacingAfter="5">
                <p:text value="#{user.name} (#{user.email})" />
            </p:paragraph>
        </p:font>
        <p:font style="normal" size="12">
            <p:paragraph alignment="center" spacingAfter="5">
                <p:text value="on" />
            </p:paragraph>
        </p:font>
        <p:font style="bold" size="16">
            <p:paragraph alignment="center" spacingAfter="75">
                <p:text value="#{date}" />
            </p:paragraph>
        </p:font>
        <p:font style="normal" size="12">
            <p:paragraph alignment="center" spacingAfter="30">
                <p:text value="Testsuite " />
                <p:text value="#{testSuite.name}" />
                <p:text value=" - " />
                <p:text value="#{testSuite.shortname}" />
                <p:text value=" - revision " />
                <p:text value="#{testSuite.revisionId}" />
            </p:paragraph>
            <p:paragraph alignment="center" spacingAfter="5">
                <p:text value="SUT: " />
                <p:text value="#{testSuite.sut.name}" />
                <p:text value=" - " />
                <p:text value="#{testSuite.sut.productversion}" />
            </p:paragraph>
        </p:font>
        <p:newPage />

    Das resultierende Deckblatt finden Sie nachfolgend.

    Beispiel Deckblatt für einen Report

    Abbildung 4.10. Beispiel Deckblatt für einen Report


    Wie bei der Kopf- und Fußzeilendefinition gesehen, kann auf die im Kontext gespeicherten Werte zugegriffen werden indem man der in geschweiften Klammern eingeschlossenen Kontextvariablen ein führendes # Zeichen vorangestellt wird, z. B. #{Benutzername}. Wir haben dies bereits verwendet, als wir die Daten für diesen Bericht vorbereitet und die Testsuite dem Kontext hinzugefügt haben. Die Kontextvariable für den Benutzer wird durch Klaros-Testmanagement automatisch in den Kontext eingefügt.

    context.add("testSuite", testSuite);
    

    Für das Deckblatt werten wir einige Attribute der Testsuite aus. Diese werden entsprechend dem Benutzer im letzten Schritt eingefügt. #{testSuite.name}, #{testSuite.shortname}, und #{testSuite.revisionId}. Die benutzbaren Attribute der Testsuite finden Sie in der Klaros-Testmanagement API Documentation in der Online Dokumentation. Auf alle Attribute, die eine get-Methode haben, kann zugegriffen werden. Für #{testSuite.name} finden Sie die Methode getName() in seiner abgeleiteten Schnittstelle IKlarosLabeledObject.

    Um einen Seitenumbruch in das Dokument einzufügen, können Sie folgendes verwenden:

      <p:newPage />
  3. Das Deckblatt ist fertig, jetzt geht es an die Aufbereitung der Daten. Um einen schnellen Überblick zu bieten wird zuerst ein Tortendiagramm für die Ergebnisse der Testsuite eingefügt.

      <p:paragraph horizontalAlignment="center" spacingAfter="25">
            <p:piechart title="Test Results per Test Run" direction="anticlockwise"
                circular="true" startAngle="30" labelGap="0.1" labelLinkPaint="#000000"
                plotBackgroundPaint="#ffffff" labelBackgroundPaint="#ffffff" is3D="true"
                borderVisible="false">
                <p:series key="results">
                    <p:data key="Error [#{error.size}]" value="#{error.size}"
                        sectionPaint="#FF0A0A" />
                    <p:data key="Success [#{success.size}]" value="#{success.size}"
                        sectionPaint="#33CC00" />
                    <p:data key="Failure [#{failure.size}]" value="#{failure.size}"
                        sectionPaint="#FFCC00" explodedPercent=".2" />
                    <p:data key="Skipped [#{skipped.size}]" value="#{skipped.size}"
                        sectionPaint="#FFFFFF" />
                </p:series>
            </p:piechart>
        </p:paragraph>

    Ein Beispiel für das erzeugte Tortendiagramm finden sie unten.

    Das erzeugte Tortendiagramm

    Abbildung 4.11. Das erzeugte Tortendiagramm


    Eine detaillierte Anleitung zum Layout des Tortendiagramms und zu anderen Charts finden Sie in der seam-pdf documentation. Erinnern Sie sich noch daran, dass wir vier List<KlarosTestCaseResult> Objekte in den Context eingefügt haben:

      context.add("error", error);
      context.add("failure", failure);
      context.add("success", success);
      context.add("skipped", skipped);
            

    Diese vier Listen repräsentieren die Ergebnisse innerhalb der Testsuite. Um das Tortendiagramm zu berechnen, verwenden wir die Anzahl der Elemente der einzelnen Listen:

    <p:data key="Error [#{error.size}]" value="#{error.size}" sectionPaint="#FF0A0A" />
  4. Als nächstes wollen wir für jeden in der Testsuite enthaltenen Testfall eine eigene Seite erzeugen und dessen Ergebnisse in einer Tabelle darstellen.

    Da dies ein wenig langatmig werden könnte, werden hier nur Fragmente des Codes vorgestellt. Ein Beispiel finden sie unten.

    Der Test Case Report

    Abbildung 4.12. Der Test Case Report


    Zuerst wird eine Schleife über alle Testcases der Testsuite benötigt:

      <ui:repeat value="#{testSuite.testCases}" var="testCase">
        ...
      </ui:repeat>

    Eine Schleife in der Template-Engine erzeugen wir mittels des <ui:repeat> Elements. Das Attribut value bekommt eine Collection zugewiesen, in unserem Fall die Liste der Testfälle. Das Attribut var definiert eine Variable, welche innerhalb der Schleife zur Adressierung des aktuellen Wertes verwendet werden kann, z.B. testCase. Mit jedem Durchlauf der Schleife bekommt die Variable testCase den nächsten Wert aus der Collection.

    Nun zur Tabelle. Wir benötigen eine zweispaltige Tabelle und die Breite der zweiten Spalte sollte die dreifache Größe der ersten Spalte haben. Der Code dafür sieht aus wie folgt:

      <p:table columns="2" widths="1 3">
        ...
      </p:table>

    Nun wird die Tabelle mit Daten gefüllt. Dazu muss definiert werden, wie jede Tabellenzelle auszusehen hat. Der folgende Code wird zwischen die <p:table> Elemente eingebettet.

      <p:cell horizontalAlignment="right">
            <p:font style="bold" size="8">
                <p:paragraph>
                    <p:text value="Project: " />
                </p:paragraph>
            </p:font>
        </p:cell>
        <p:cell>
            <p:paragraph alignment="left">
                <p:text value="#{testCase.configuration.name}" />
            </p:paragraph>
        </p:cell>
        <p:cell horizontalAlignment="right">
            <p:font style="bold" size="8">
                <p:paragraph>
                    <p:text value="Creator: " />
                </p:paragraph>
            </p:font>
        </p:cell>
        <p:cell>
            <p:paragraph alignment="left">
                <p:text value="#{testCase.creator.name}" />
            </p:paragraph>
        </p:cell>
        ...

    Die Tabelle soll zwei Spalten haben, somit müssen auch zwei Zellen pro Zeile angegeben werden. In obigem Code beinhaltet die erste Zelle einer Zeile den Namen des Testprojektes, während die zweite Zelle den Namen des Benutzers, der den Testcase erstellt hat, beinhaltet. Es ist wie am <p:font> Element ersichtlich möglich, den Text innerhalb einer Zelle zu formatieren.

  5. Als nächstes sollen die Testcase Ergebnisse angezeigt werden. Hier kommt jetzt ein weiteres Element ins Spiel. Wenn für einen Testfall kein Ergebnis vorliegt, so soll ein Standardtext anstatt einer leeren Zelle angezeigt werden.

      <ui:fragment rendered="#{testCase.results.isEmpty()}">
            <p:font style="normal" size="14">
                <p:paragraph alignment="left" spacingAfter="15"
                    indentationLeft="10">
                    <p:text value="No test runs found for this test case." />
                </p:paragraph>
            </p:font>
        </ui:fragment>

    Achten Sie auf das <ui:fragment rendered="..."> Element. Dieser Teil des Dokumentes wird nur ins PDF aufgenommen wenn die Bedingung im rendered-Attribut zu true ausgewertet wird. Diese Anweisung ist mit if-Anweisungen in anderen Programmiersprachen vergleichbar. Im Ausdruck #{testCase.results.isEmpty()} wird die isEmpty() Methode der Testfall-Ergebnisliste aufgerufen, welche zu einem boole'schen Wert ausgewertet wird. Als Nächstes wird ein Block definiert, der die Daten aufbereitet, wenn die Ergebnisliste nicht leer ist:

      <ui:fragment rendered="#{!testCase.results.isEmpty()}">
        ...
      </ui:fragment>

    Beachten Sie bitte das ! welches den Ausdruck, den wir zuvor benutzt haben, negiert. Der Code innerhalb dieses Blocks wird ausgeführt, wenn die Liste der Ergebnisse mindestens einen Eintrag besitzt.

  6. Jetzt wird über die Testcase Ergebnisse iteriert, welche alle Testläufe eines Testcase beinhalten. Ein Beispiel für einen Testlauf finden Sie unten.

      <ui:repeat value="#{testCase.results.toArray()}" var="testResult">
        <!-- Start Test Result summary (equivalent to Test Run) -->
        ...
      </ui:repeat>

    Dieser Code liefert ein Testergebnis in der Variable testResult. Das nächste Codefragment beinhaltet die Anzeige einer Zusammenfassung des Testergebnisses, die dem Code zur Anzeige der Testfallzusammenfassung sehr ähnlich ist. Den gesamten Code finden Sie beigefügten Quellcode.

    Next, the test steps and their results are displayed in the current test run.

    Als nächstes werden die Testschritte und deren Ergebnisse im aktuellen Testlauf angezeigt.

  7. Dazu muss eine weitere Schleife innerhalb der Testergebnis-Schleife angelegt werden.

      <!-- Start Test Step Result summary -->
        <ui:fragment rendered="#{!testResult.stepResults.isEmpty()}">
            <ui:repeat value="#{testResult.stepResults}" var="testStepResult">
            ...
            </ui:repeat>
        </ui:fragment>
        <ui:fragment rendered="#{testResult.stepResults.isEmpty()}">
            <p:font style="normal" size="10">
                <p:paragraph alignment="left" spacingAfter="35"
                    indentationLeft="25">
                    <p:text value="No test step results found." />
                </p:paragraph>
            </p:font>
        </ui:fragment>

    Innerhalb des <ui:repeat>...</ui:repeat> Blocks wird eine Tabelle angelegt. Diese Tabelle soll angezeigt werden, sobald es mindestens ein Ergebnis zu einem Testschritt gibt. Die Tabelle zeigt die Vorbedingung, Aktion und Nachbedingung des Testschritts an, ebenso wie das Testschrittergebnis, die Ergebniszusammenfassung und die Testschrittbeschreibung. Die Testschrittergebnis-Zelle wird entsprechend dem Ergebnis eingefärbt, z.B. grün, wenn der Testschritt erfolgreich absolviert wurde. Jede Tabelle hat die Testschrittanzahl als Überschrift.

  8. Anzeigen der Testschrittnummer.

      <p:font style="bold" size="8">
          <p:paragraph indentationLeft="20">
              <p:text value="Step #{testResult.stepResults.indexOf(testStepResult)+1}" />
          </p:paragraph>
      </p:font>

    Hier sehen Sie wie Sie den Index des Testschrittergebnisses aus der Liste der Testergebnisse abfragen können. testStepResult ist die Variable der innersten Schleife, während testResult die Schleifenvariable der äußeren Schleife bezeichnet. Da die Zählung bei null beginnt, müssen wir den ermittelten Wert inkrementieren, sonst würde der erste Schritt als Schritt 0 angezeigt werden.

  9. Die Tabelle soll nur dann angezeigt werden, wenn der Testfall mindestens einen Testschritt beinhaltet.

      <p:table columns="3" widths="3 3 3" spacingBefore="5"
            rendered="#{testCase.testCaseSteps!=null and testCase.testCaseSteps.size() > 0}">
        ...
      </p:table>
  10. Abfragen der Testschritt Eigenschaften (precondition, action, postcondition).

      <p:cell horizontalAlignment="left">
        <p:font style="normal" size="8">
            <p:paragraph>
                <p:text
                value="#{testCase.testCaseSteps.get(testStepResult.precondition}" />
            </p:paragraph>
        </p:font>
      </p:cell>

    Um die Testschritteigenschaften anzusprechen wird der Testcase benötigt. Über den Index des Testschrittergebnisses innerhalb der Testschritte wird der entsprechende Testschritt geholt und die Eigenschaften wie precondition, action und postcondition können abgefragt werden.

  11. Einfärben einer Tabellenzelle abhängig vom Testschrittergebnis.

        <ui:fragment rendered="#{testStepResult.isPassed()}">
            <p:cell backgroundColor="rgb(0,255,0)"
                horizontalAlignment="center">
                <p:font style="normal" size="8">
                    <p:paragraph>
                        <p:text value="Passed" />
                    </p:paragraph>
                </p:font>
            </p:cell>
        </ui:fragment>
        <ui:fragment rendered="#{testStepResult.isError()}">
            <p:cell backgroundColor="rgb(255,0,0)"
                horizontalAlignment="center">
                <p:font style="normal" size="8">
                    <p:paragraph>
                        <p:text value="Error" />
                    </p:paragraph>
                </p:font>
            </p:cell>
        </ui:fragment>
        <ui:fragment rendered="#{testStepResult.isFailure()}">
            <p:cell backgroundColor="rgb(255,215,0)"
                horizontalAlignment="center">
                <p:font style="normal" size="8">
                    <p:paragraph>
                        <p:text value="Failed" />
                    </p:paragraph>
                </p:font>
            </p:cell>
        </ui:fragment>
        <ui:fragment rendered="#{testStepResult.isSkipped()}">
            <p:cell horizontalAlignment="center">
                <p:font style="normal" size="8">
                    <p:paragraph>
                        <p:text value="Skipped" />
                    </p:paragraph>
                </p:font>
            </p:cell>
      </ui:fragment>

    Die Zellen werden abhängig vom Status der Testschritte eingefärbt. Dazu werden die Methoden isError(), isFailure() etc. ausgewertet. Die Zellen werden eingefärbt, indem das backgroundColor-Attribut auf den gewünschten RGB Wert gesetzt wird.