Wenn Inhalte eines PDF-Dokumentes weiterverarbeitet werden sollen, spielen Formularfelder eine entscheidende Rolle. Diese sollten schon bei der Erstellung des PDF-Dokumentes korrekt erstellt sein. Dafür sind vor allem korrekte und eindeutige Feldnamen wichtig.
Mit dem Hilfsprogramm ExtractFieldsInfo
können alle Informationen
zu Formularfeldern in eine XML-Datei extrahiert und für XML- und XPath-basierte
Tests genutzt werden.
In den folgenden Abschnitten werden viele Tests auf Feldeigenschaften, Größe und natürlich auch die Inhalte von Feldern beschrieben. Je nach Anwendungkontext kann der eine oder andere Tests für Sie wichtig sein:
<!-- Tags for tests on fields: --> <hasField withName (required) width=".." (optional, ... height=".." ... but used together) unit=".." (optional, default = MILLIMETER) hasMultipleLines".." (optional) hasSingleLine".." (optional) isEditable".." (optional) isExportable".." (optional) isHidden".." (optional) isMultiSelectable".." (optional) isPasswordProtected".." (optional) isReadOnly".." (optional) isPrintable".." (optional) isRequired".." (optional) isSigned".." (optional) isVisible".." (optional) withType".." (optional) /> ... continued
... continuation <!-- Nested tags of <hasField /> are described later in this chapter --> <!-- The constants for the attribute 'withType' ard described later in this chapter --> <hasFields /> <hasNumberOfFields /> <hasSignedSignatureFields /> <hasUnsignedSignatureFields /> <!-- Nested tags of <hasFields /> are: --> <allithoutDuplicateNames /> <allWithoutTextOverflow /> <matchingXPath /> <matchingXML />
Dieser Test wird in Kapitel 3.12: „Formularfelder, Textüberlauf“ separat beschrieben. |
Mit dem folgenden Test können Sie prüfen, ob es überhaupt Felder gibt:
<testcase name="hasFields_NoFieldsAvailable" errorExpected="YES" > <assertThat testDocument="acrofields/noAcrofieldDemo.pdf"> <hasFields /> </assertThat> </testcase>
Wenn es lediglich wichtig ist, wieviele Formularfelder ein PDF-Dokument enthält,
nutzen Sie das Tag <hasNumberOfFields />
:
<testcase name="hasNumberOfFields"> <assertThat testDocument="acrofields/simpleRegistrationForm.pdf"> <hasNumberOfFields>4</hasNumberOfFields> </assertThat> </testcase>
Möglicherweise ist es auch interessant, sicherzustellen, dass ein PDF-Dokument keine Felder (mehr) besitzt:
<testcase name="hasNumberOfFields_NoFieldsAvailable"> <assertThat testDocument="acrofields/noAcrofieldDemo.pdf"> <hasNumberOfFields>0</hasNumberOfFields> </assertThat> </testcase>
Da bei der Verarbeitung von PDF-Dokumenten über die Feldnamen auf deren Inhalte zugegriffen wird, muss sichergestellt sein, dass es das erwartete Feld auch gibt:
<testcase name="hasField_MultipleInvocation"> <assertThat testDocument="acrofields/simpleRegistrationForm.pdf"> <hasField withName="name" /> <hasField withName="address" /> <hasField withName="postal_code" /> <hasField withName="email" /> </assertThat> </testcase>
Doppelte Feldnamen sind zwar nach der PDF-Spezifikation erlaubt, bereiten bei der Weiterverarbeitung von PDF-Dokumenten höchstwahrscheinlich aber Überraschungen. PDFUnit stellt deshalb ein Tag zur Verfügung, um die Abwesenheit doppelter Namen zu prüfen:
<testcase name="hasFields_AllWithoutDuplicateNames"> <assertThat testDocument="acrofields/javaScriptForFields.pdf"> <hasFields> <allWithoutDuplicateNames /> </hasFields> </assertThat> </testcase>
Am einfachsten ist ein Test, der prüft, ob ein bestimmtes Feld überhaupt Daten enthält:
<testcase name="hasField_WithAnyValue"> <assertThat testDocument="acrofields/javaScriptForFields.pdf"> <hasField withName="ageField"> <withAnyValue /> </hasField> </assertThat> </testcase>
Zur Überprüfung der Inhalte von Feldern stehen ähnliche Tags zur Verfügung, wie für die Überprüfung der Inhalte von Dokumenteneigenschaften:
<!-- Tags to check content in fields --> <containing /> <endingWith /> <havingJavaScriptAction /> <matchingComplete /> <matchingRegex /> <notContaining /> <notMatchingRegex /> (useful, because regular expressions are not designed to find 'Not-Matches') <startingWith /> <withAnyValue /> <withoutTextOverflow />
Die nachfolgenden Beispiele sollen Ihnen ein paar Anregungen für die Verwendung dieser Tags geben:
<testcase name="hasField_MatchingComplete"> <assertThat testDocument="acrofields/plugin-pdf_form_maker.pdf"> <hasField withName="Text 1"> <matchingComplete> Single Line Text </matchingComplete> </hasField> </assertThat> </testcase>
<!-- This is a small test to protect fields against SQL injection. --> <testcase name="hasField_NotContaining_SQLComment"> <assertThat testDocument="acrofields/plugin-pdf_form_maker.pdf"> <hasField withName="Text 1"> <notContaining>--</notContaining> <notContaining>/></notContaining> </hasField> </assertThat> </testcase>
Formularfelder haben einen bestimmten Typ. Auch wenn die Bedeutung
des Typs wohl nicht so groß ist, wie die des Namens, so gibt
es trotzdem das Attribut withType=".."
, um den
Typ eines Feldes zu überprüfen:
<testcase name="hasFieldWithType_MultipleInvocation"> <assertThat testDocument="acrofields/plugin-pdf_form_maker.pdf"> <hasField withName="Text 25" withType="TEXT" /> <hasField withName="Check Box 7" withType="CHECKBOX" /> <hasField withName="Radio Button 4" withType="RADIOBUTTON" /> <hasField withName="Button 19" withType="PUSHBUTTON" /> <hasField withName="List Box 1" withType="LIST" /> <hasField withName="List Box 1" withType="CHOICE" /> <hasField withName="Combo Box 5" withType="CHOICE" /> <hasField withName="Combo Box 5" withType="COMBO" /> </assertThat> </testcase>
Die möglichen Feldtypen sind als Konstanten für das Attribut withType
definiert. Die Namen der Konstanten entsprechen den gängigen, sichtbaren
Elementen einer graphischen Anwendung. Innerhalb von PDF gibt es aber
andere Typen. Weil die in einer Fehlermeldungen auftauchen können,
gibt die folgende Liste die Zuordnung wider:
<!-- Mapping between PDFUnit constants and PDF-internal types. --> PDFUnit-Constant PDF-intern ------------------------------- CHOICE -> "choice" COMBO -> "choice" LIST -> "choice" CHECKBOX -> "button" PUSHBUTTON -> "button" RADIOBUTTON -> "button" SIGNATURE -> "sig" TEXT -> "text"
Das vorhergehende Code-Listing enthält bis auf das Signaturfeld alle Feldtypen, die überprüft werden können. Mit dem nächsten Beispiel wird auf Signaturfelder geprüft:
<testcase name="hasField_WithType_Signature"> <assertThat testDocument="signed/sampleSignedPDFDocument.pdf"> <hasField withName="Signature2" isSigned="YES" /> </assertThat> </testcase>
Ausführliche Tests zu Signaturen und Zertifikaten werden in Kapitel 3.21: „Signaturen und Zertifikate“ beschrieben.
Falls die Größe von Formularfeldern wichtig ist, stehen für die
Überprüfung von Länge und Breite die Attribute width=".."
und height=".."
zur Verfügung:
<testcase name="hasField_WidthAndHeight"> <assertThat testDocument="acrofields/notExportableAcrofield.pdf"> <hasField withName="Title of 'someField'" width="159" (default is MILLIMETER) height="11" (default is MILLIMETER) /> </assertThat> </testcase>
<!-- When @unit is omitted, the values of width are taken as "MILLIMETER". --> <testcase name="hasField_Width"> <assertThat testDocument="acrofields/notExportableAcrofield.pdf"> <hasField withName="Title of 'someField'" width="159" /> <hasField withName="Title of 'someField'" width="159" unit="MILLIMETER" /> <hasField withName="Title of 'someField'" width="15.9" unit="CENTIMETER" /> <hasField withName="Title of 'someField'" width="450" unit="DPI72" /> <hasField withName="Title of 'someField'" width="450" unit="POINTS" /> <hasField withName="Title of 'someField'" width="6.26" unit="INCH" /> </assertThat> </testcase>
Sie werden beim Erstellen eines Testes wahrscheinlich nicht die Maße eines Feldes kennen. Kein Problem, nehmen Sie eine beliebige Zahl für die Höhe und Breite und starten den Test. Die dann auftretende Fehlermeldung enthält die richtigen Werte in Millimetern.
Ob ein Text tatsächlich in ein Formularfeld passt, lässt sich durch die Größenbestimmung alleine nicht sicherstellen. Neben der Schriftgröße bestimmen auch die Worte am Zeilenende in Zusammenhang mit der Silbentrennung die Anzahl der benötigten Zeilen und damit die benötigte Höhe. Das Kapitel 3.12: „Formularfelder, Textüberlauf“ beschäftigt sich ausführlich mit diesem Thema.
Formularfelder haben neben ihrer Größe noch weitere Eigenschaften,
wie z.B. editable
und printable
. Viele dieser
Eigenschaften können manuell gar nicht getestet werden. Deshalb gehören
passende Tests in jedes PDF-Testwerkzeug. Das folgende Beispiele
stellt das Prinzip dar:
<testcase name="hasField_Editable"> <assertThat testDocument="acrofields/plugin-pdf_form_maker.pdf"> <hasField withName="Combo Box 4" isEditable="YES" /> </assertThat> </testcase>
Insgesamt stehen folgende Attribute zur Überprüfung von Feldeigenschaften zur Verfügung:
<!-- Attributes to check field properties: -->
hasMultipleLines="YES"
hasSingleLine="YES"
isEditable="YES/NO"
isExportable="YES/NO"
isHidden="YES/NO"
isMultiSelectable="YES/NO"
isPasswordProtected="YES"
isPrintable="YES/NO"
isReadOnly="YES/NO"
isRequired="YES/NO"
isSigned="YES"
isVisible="YES/NO"
Bei den Vergleichen spielen Whitespaces keine Rolle:
<testcase name="hasField_MultiLineField_MultipleInvocations"> <assertThat testDocument="acrofields/plugin-pdf_form_maker.pdf"> <hasField withName="Text multi" hasMultipleLines="YES" isExportable="YES" > <matchingComplete> Multiple Line Support: First Line; Second Line; </matchingComplete> </hasField> </assertThat> </testcase>
Wenn PDF-Dokumente Teil eines Workflows sind, unterliegen Formularfelder normalerweise bestimmten Plausibilitäten. Diese Plausibilitäten werden häufig durch eingebettetes JavaScript umgesetzt, um die Prüfungen schon zum Zeitpunkt der Eingabe auszuführen.
Mit PDFUnit kann geprüft werden, ob ein Formularfeld mit einer Aktion verknüft ist:
<testcase name="hasField_HavingJavaScriptAction_MultipleInvocation"> <assertThat testDocument="acrofields/javaScriptForFields.pdf"> <hasField withName="ageField" > <havingJavaScriptAction>Validate</havingJavaScriptAction> </hasField> <hasField withName="nameField" > <havingJavaScriptAction>Keystroke</havingJavaScriptAction> </hasField> <hasField withName="commentField" > <havingJavaScriptAction>Keystroke</havingJavaScriptAction> </hasField> </assertThat> </testcase>
Tags für das Testen des eigentlichen JavaScript-Codes sind in Kapitel 3.13: „JavaScript“ beschrieben.
Wenn PDF-erstellende Werkzeuge Unicode-Sequenzen nicht richtig verarbeiten, wird es schwierig, diese Sequenzen in PDFUnit-Tests zu verwenden. Schwierig heißt aber nicht unmöglich. Das folgende Bild zeigt, dass der Name eines Feldes PDF-intern unglücklicherweise als UTF-16BE mit Byte-Order-Mark (BOM) gespeichert wird:
Auch wenn es schwierig ist, dieser Feldname kann als Java-Unicode-Sequenz getestet werden:
<!-- The name of the field consists of UTF-16BE code represented as ASCII. Use a Unicode sequence for the field name to test it. --> <testcase name="hasField_NameContainingUnicode_UTF16"> <assertThat testDocument="unicode/unicode_inFieldnames.pdf"> <hasField withName="\u00fe\u00ff\u0000F\u0000o\u0000r\u0000m\...\u0000]" /> </assertThat> </testcase> <!-- The Unicode sequence in this example is abbreviated. -->
Mehr Informationen zu Unicode und Byte-Order-Mark liefern gute Artikel auf Wikipedia.
Das Kapitel
9.4: „Feldeigenschaften nach XML extrahieren“
beschreibt, wie mit dem Extraktionsprogramm ExtractFieldsInfo
Informationen über alle Formularfelder eines PDF-Dokumentes
extrahiert werden können. Die dabei entstehende XML-Datei kann
in Tests als Vergleichsinstanz benutzt werden:
<testcase name="hasField_MatchingXML"> <assertThat testDocument="acrofields/plugin-pdf_form_maker.pdf"> <hasFields> <matchingXML file="acrofields/plugin-pdf_form_maker.xml"/> </hasFields> </assertThat> </testcase>
Diese extrahierten XML-Daten von Formularfeldern können auch für XPath-Abfragen genutzt werden. Das ermöglicht es, Abhängigkeiten zwischen mehreren Feldern zu testen („cross-constraints“). Die folgenden Beispiele vermitteln eine Idee von den Möglichkeiten:
<testcase name="hasField_MatchingXPath_NumberOfTextFields"> <assertThat testDocument="acrofields/plugin-pdf_form_maker.pdf"> <hasFields> <matchingXPath expr="count(//field[./@type='text']) = 43"/> </hasFields> </assertThat> </testcase>
Das Tag <matchingXPath />
kann mehrfach in
einem Test auftauchen:
<testcase name="hasField_MatchingXPath_MultipleInvocation"> <assertThat testDocument="acrofields/plugin-pdf_form_maker.pdf"> <hasFields> <matchingXPath expr="count(//field[./@type='text']) = 43"/> <matchingXPath expr="count(//field[./@type='button']) = 54"/> <matchingXPath expr="count(//field[./@type='choice']) = 5"/> <matchingXPath expr="count(//field[./@type='signatur']) = 0"/> </hasFields> </assertThat> </testcase>
Die beiden folgenden Beispiele überprüfen, ob es unsignierte Signaturfelder gibt:
<testcase name="hasField_MatchingXPath_HavingUnSignedSignatureFields_1"> <assertThat testDocument="acrofields/certificateform.pdf"> <hasUnsignedSignatureFields /> </assertThat> </testcase>
<testcase name="hasField_MatchingXPath_HavingUnSignedSignatureFields_2"> <assertThat testDocument="acrofields/certificateform.pdf"> <hasFields> <matchingXPath expr="count(//field[./@type='sig'][./@isSigned='false']) > 0"/> </hasFields> </assertThat> </testcase>
PDFUnit verwendet den XSLT-Prozessor der aktuellen Java Runtime. Ob alle Syntaxelemente und Funktionen von XPath 2.0 unterstützt werden, entnehmen Sie daher bitte der Dokumentation Ihrer eingesetzten JRE bzw. des JDK. Einschränkungen seitens PDFUnit bestehen nicht.