Wollten Sie schon immer die endgültige Ausgabe-PDF-Datei einschließlich des Layouts automatisch testen, wenn Sie eine Anwendung entwickeln, die PDF-Dateien wie Formulare ausgibt? In diesem Dokument werde ich Ihnen zeigen, wie Sie Regressionstests einschließlich Layout durchführen, indem Sie zwei PDF-Dateien abbilden und vergleichen.
Das Imaging von PDFs ist mit Apache PDFBox einfacher als Sie vielleicht denken. Wie bereits erwähnt, ist der Zweck ein automatischer Regressionstest. Wenn also die Anzahl der Seiten oder die Seitengröße unterschiedlich ist, schlägt der Test fehl und gibt auf.
Je größer der DPI für die Bildgebung ist, desto präzisere Vergleiche können mit hochauflösenden Bildern durchgeführt werden. Dies erfordert jedoch Maschinenressourcen (CPU, Speicher).
static void assertPdfEquals(InputStream expected, InputStream actual) throws IOException {
try (PDDocument doc1 = PDDocument.load(expected);
PDDocument doc2 = PDDocument.load(actual)) {
//Test fehlgeschlagen, wenn die Anzahl der Seiten unterschiedlich ist
assertEquals(doc1.getNumberOfPages(), doc2.getNumberOfPages());
PDFRenderer renderer1 = new PDFRenderer(doc1);
PDFRenderer renderer2 = new PDFRenderer(doc2);
for (int i = 0; i < doc1.getNumberOfPages(); i++) {
BufferedImage image1 = renderer1.renderImageWithDPI(i, 144, ImageType.RGB);
BufferedImage image2 = renderer2.renderImageWithDPI(i, 144, ImageType.RGB);
//Der Test schlägt fehl, auch wenn die Größe unterschiedlich ist
assertEquals(image1.getWidth(), image2.getWidth());
assertEquals(image1.getHeight(), image2.getHeight());
//Testen Sie die Bildübereinstimmung und geben Sie das Differenzbild in eine temporäre Datei aus, wenn sie nicht übereinstimmen
Path path = Files.createTempFile("diff-" + i + "-", ".png ");
try (OutputStream os = Files.newOutputStream(path)) {
assertTrue(compareImage(image1, image2, os), path);
}
}
}
}
Der Bildvergleich ist nicht besonders schwierig, solange Sie nur Pixel für Pixel die genaue Übereinstimmung der RGB-Werte überprüfen. Es geht nicht nur darum, zu vergleichen, sondern die nicht übereinstimmenden Pixel mit einer Hervorhebungsfarbe neu zu streichen, um ein differenzielles Bild zu erstellen.
static boolean compareImage(BufferedImage image1, BufferedImage image2, OutputStream os) throws IOException {
boolean matched = true;
for (int x = 0; x < image1.getWidth(); x++) {
for (int y = 0; y < image1.getHeight(); y++) {
int p1 = image1.getRGB(x, y);
int p2 = image2.getRGB(x, y);
//Lassen Sie die übereinstimmenden Pixel unverändert und ändern Sie die nicht übereinstimmenden Pixel in Magenta
if (p1 != p2) {
matched = false;
image1.setRGB(x, y, Color.MAGENTA.getRGB());
}
}
}
//Ausgangsdifferenzbild
if (os != null) {
ImageIO.write(image1, "png", os);
}
return matched;
}
Im Gegensatz zum erwarteten PDF wurden im tatsächlichen PDF "das Datum der Überschrift hinzugefügt", "Punkt 3 des Artikels wurde gelöscht" und "Zwischensummen und Summen haben sich aufgrund des Löschens von Punkt 3 geändert". Kann durch Vergleich mit dem Differenzbild gelesen werden.
Erwartetes PDF
Aktuelles PDF
Differenzbild
//Übereinstimmende Pixel sind schwarz, nicht übereinstimmende Pixel sind weiß
if (p1 == p2) {
image1.setRGB(x, y, Color.BLACK.getRGB());
} else {
matched = false;
image1.setRGB(x, y, Color.WHITE.getRGB());
}
Ich stellte vor, wie ein Schnappschuss-Test durchgeführt wird, indem die PDF-Ausgabe in ein Bild konvertiert wird. Der visuelle Regressionstest für Menschen ist begrenzt, wenn versucht wird zu bestätigen, dass "nicht nur die Daten ausgegeben, sondern auch im richtigen Layout angezeigt werden" wie PDF.
Wenn Sie die diesmal eingeführte Methode verwenden, erkennen Sie nicht nur die Entfettung der von Ihnen implementierten Anwendung, sondern bemerken auch unbeabsichtigte Layoutänderungen, wenn Sie die PDF-Ausgabebibliothek aktualisieren, sodass Sie beruhigter entwickeln können. Da ist gar nichts.
Recommended Posts