Avez-vous déjà voulu tester automatiquement le PDF de sortie final, y compris la mise en page, lors du développement d'une application qui produit des PDF tels que des formulaires? Dans ce document, je vais vous montrer comment effectuer des tests de régression, y compris la mise en page par imagerie et la comparaison de deux fichiers PDF.
La création d'images PDF est plus facile que vous ne le pensez avec Apache PDFBox. Comme mentionné précédemment, le but est un test de régression automatique, donc si le nombre de pages ou la taille de la page est différent, le test échouera et abandonnera.
Plus le DPI pour l'imagerie est élevé, plus des comparaisons plus précises peuvent être effectuées à l'aide d'images haute résolution, mais cela nécessite des ressources de la machine (CPU, mémoire).
static void assertPdfEquals(InputStream expected, InputStream actual) throws IOException {
try (PDDocument doc1 = PDDocument.load(expected);
PDDocument doc2 = PDDocument.load(actual)) {
//Le test a échoué si le nombre de pages est différent
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);
//Le test échoue même si la taille est différente
assertEquals(image1.getWidth(), image2.getWidth());
assertEquals(image1.getHeight(), image2.getHeight());
//Tester la correspondance de l'image et générer l'image différentielle dans un fichier temporaire si elles ne correspondent pas
Path path = Files.createTempFile("diff-" + i + "-", ".png ");
try (OutputStream os = Files.newOutputStream(path)) {
assertTrue(compareImage(image1, image2, os), path);
}
}
}
}
La comparaison d'images n'est pas particulièrement difficile tant que vous ne vérifiez que la correspondance exacte des valeurs RVB pixel par pixel. Le but n'est pas seulement de comparer, mais de repeindre les pixels incompatibles avec une couleur de surbrillance pour créer une image différentielle.
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);
//Laissez les pixels correspondants tels quels et changez les pixels sans correspondance en magenta
if (p1 != p2) {
matched = false;
image1.setRGB(x, y, Color.MAGENTA.getRGB());
}
}
}
//Image de différence de sortie
if (os != null) {
ImageIO.write(image1, "png", os);
}
return matched;
}
Contrairement au PDF attendu, dans le PDF réel, «la date de l'en-tête a été ajoutée», «l'élément 3 de l'élément a été supprimé» et «les sous-totaux et totaux ont changé en raison de la suppression de l'élément 3». Peut être lu en le comparant à l'image de différence.
PDF attendu
PDF réel
Image de différence
//Les pixels correspondants sont noirs, les pixels sans correspondance sont blancs
if (p1 == p2) {
image1.setRGB(x, y, Color.BLACK.getRGB());
} else {
matched = false;
image1.setRGB(x, y, Color.WHITE.getRGB());
}
J'ai présenté comment effectuer un test d'instantané en convertissant la sortie PDF en image. Il y a une limite au test de régression visuelle pour les humains lorsque l'on essaie de confirmer que "non seulement les données sont sorties mais également affichées dans la bonne mise en page" comme PDF.
Si vous utilisez la méthode introduite cette fois, vous détecterez non seulement le dégraissage de l'application que vous implémentez, mais vous remarquerez également des changements de mise en page involontaires lors de la mise à niveau de la bibliothèque de sortie PDF, afin que vous puissiez développer avec plus de tranquillité d'esprit. Il n'y en a pas.
Recommended Posts