Your Web News in One Place

Help Webnuz

Referal links:

Sign up for GreenGeeks web hosting
December 15, 2021 09:24 am GMT

Implementing Approval Tests For PDF Document Generation

In the previous blog post, we discussed how to use Approval Tests for verifying generated PDF documents. In this blog post Im going to show how to extend the Approval Test library for Java in order to support PDF documents. Lets just dive right into the code.

The first thing that needs to happen is making a new implementation of the ApprovalApprover interface, which is provided by the Approval Test library. The following code demonstrates how this can be implemented.

public class PdfFileApprover implements ApprovalApprover {    public static final Field<String> PDF_DIFF_OUTPUT_DIRECTORY =        new Field<>("PdfDiffOutputDirectory", String.class);    private final ApprovalNamer namer;    private final ApprovalWriter writer;    private final double allowedDiffInPercent;    private final List<PageArea> excludedAreas;    private File received;    private final File approved;    public PdfFileApprover(ApprovalWriter writer, PdfFileOptions options) {        this.writer = writer;        this.allowedDiffInPercent = options.getAllowedDiffInPercent();        this.excludedAreas = options.getExcludedAreas();        namer = options.getParent().forFile().getNamer();        received = namer.getReceivedFile(writer.getFileExtensionWithDot());        approved = namer.getApprovedFile(writer.getFileExtensionWithDot());    }    public VerifyResult approve()    {        received = writer.writeReceivedFile(received);        return approvePdfFile(received, approved);    }    public void cleanUpAfterSuccess(ApprovalFailureReporter reporter)    {        received.delete();        if(reporter instanceof ApprovalReporterWithCleanUp) {            ((ApprovalReporterWithCleanUp) reporter)                .cleanUp(received.getAbsolutePath(), approved.getAbsolutePath());        }    }    public VerifyResult reportFailure(ApprovalFailureReporter reporter)    {        reporter.report(received.getAbsolutePath(), approved.getAbsolutePath());        if (reporter instanceof ReporterWithApprovalPower)        {            ReporterWithApprovalPower reporterWithApprovalPower = (ReporterWithApprovalPower) reporter;            return reporterWithApprovalPower.approveWhenReported();        }        return VerifyResult.FAILURE;    }    public void fail()    {        throw new Error(String.format("Failed Approval
Approved:%s
Received:%s"
, approved.getAbsolutePath(), received.getAbsolutePath())); } private VerifyResult approvePdfFile(File received, File approved) { try { SimpleEnvironment environment = new SimpleEnvironment(); environment.setAllowedDiffInPercent(this.allowedDiffInPercent); PdfComparator<CompareResultImpl> pdfComparator = new PdfComparator<>(approved, received) .withEnvironment(environment); excludedAreas.forEach(pdfComparator::withIgnore); CompareResultImpl comparisonResult = pdfComparator.compare(); if(comparisonResult.isNotEqual()) { String outputFileName = determineDiffOutputFileName(); comparisonResult.writeTo(outputFileName); } return VerifyResult.from(comparisonResult.isEqual()); } catch (IOException e) { return VerifyResult.FAILURE; } } private String determineDiffOutputFileName() { var outputDirectory = PackageLevelSettings.getValueFor(PDF_DIFF_OUTPUT_DIRECTORY); if(null == outputDirectory) { outputDirectory = namer.getSourceFilePath(); } return Path.of(outputDirectory, "diffOutput").toString(); }}

The PdfFileApprover class provides the core implementation for supporting PDF documents. Most of the code is quite similar to the FileApprover class of the Approval Test library. However, the approvePdfFile method is the most important part. This method expects two arguments; the received PDF file and the approved PDF file. The purpose of the approvePdfFile method is to compare both incoming PDF files. For doing the actual comparison we make use of the PDFCompare library.

When theres a difference between these PDF files, we save the result of the comparison to a PDF file so that we can visually inspect the differences as well as instruct the framework to fail the test. Also notice that the PDFCompare library has the ability to exclude certain areas within a PDF file from the comparison as well as allowing a certain percentage of differences.

public class PdfApprovals {    public static void verify(ByteArrayOutputStream outputStream) {        verify(outputStream, PdfFileOptions.DEFAULT_ALLOWED_DIFF_IN_PERCENT, Collections.emptyList());    }    public static void verify(ByteArrayOutputStream outputStream, List<PageArea> excludedAreas) {        verify(outputStream, PdfFileOptions.DEFAULT_ALLOWED_DIFF_IN_PERCENT, excludedAreas);    }    public static void verify(ByteArrayOutputStream outputStream, double allowedDiffInPercentage) {        verify(outputStream, allowedDiffInPercentage, Collections.emptyList());    }    public static void verify(ByteArrayOutputStream outputStream, double allowedDiffInPercentage,                               List<PageArea> excludedAreas) {        ByteArrayInputStream inputStream = new ByteArrayInputStream(outputStream.toByteArray());        ApprovalBinaryFileWriter binaryFileWriter = new ApprovalBinaryFileWriter(inputStream, "pdf");        PdfFileOptions options = new PdfFileOptions()            .withAllowedDiffInPercent(allowedDiffInPercentage)            .withExcludedAreas(excludedAreas);        PdfApprovals.verify(binaryFileWriter, options);    }    private static void verify(ApprovalWriter writer, PdfFileOptions options) {        PdfFileApprover pdfFileApprover = new PdfFileApprover(writer, options);        Approvals.verify(pdfFileApprover, options.getParent());    }}

The PdfApprovals class provides a number of static helper methods that can be used by the tests themselves. These helper methods ultimately use the PdfFileApprover class to perform the actual comparison. A number of overloaded methods are available to provide the ability of excluding certain areas and/or tweaking the allowed percentage of differences when performing the comparison.

These can be used as follows:

PdfApprovals.verify(result);...PdfApprovals.verify(result, 0.18);...var excludedAreas = Arrays.asList(    new PageArea(4, 4, 12, 18),    new PageArea(35, 38, 42, 45));PdfApprovals.verify(result, excludedAreas);...PdfApprovals.verify(result, 0.18, excludedAreas);

For completeness, the following code shows the implementation of the PdfFileOptions and PackageSettings classes. These are necessary to provide the PdfFileApprover class with the necessary configuration settings for performing the comparison and saving the output files.

public class PdfFileOptions {    public static final double DEFAULT_ALLOWED_DIFF_IN_PERCENT = 0.001;    private enum CustomFields {        ALLOWED_DIFF_IN_PERCENT,        EXCLUDED_AREAS    }    private final Map<CustomFields, Object> customFields;    private final Options options;    public PdfFileOptions() {        customFields = new HashMap<>();        customFields.put(CustomFields.ALLOWED_DIFF_IN_PERCENT, DEFAULT_ALLOWED_DIFF_IN_PERCENT);        customFields.put(CustomFields.EXCLUDED_AREAS, Collections.emptyList());        options = new Options();        options.forFile().withExtension(".pdf");    }    public double getAllowedDiffInPercent() {        return (double) customFields.get(CustomFields.ALLOWED_DIFF_IN_PERCENT);    }    public List<PageArea> getExcludedAreas() {        return (List<PageArea>) customFields.get(CustomFields.EXCLUDED_AREAS);    }    public Options getParent() {        return options;    }    public PdfFileOptions withAllowedDiffInPercent(double allowedDiffInPercent) {        customFields.put(CustomFields.ALLOWED_DIFF_IN_PERCENT, allowedDiffInPercent);        return this;    }    public PdfFileOptions withExcludedAreas(List<PageArea> excludedAreas) {        customFields.put(CustomFields.EXCLUDED_AREAS, excludedAreas);        return this;    }}public class PackageSettings {    public static String ApprovalBaseDirectory = "../resources";    public static String PdfDiffOutputDirectory =         String.format("%s/build/tmp", System.getProperty("user.dir"));}

Thats all there is to it. With just this tiny bit of code were able to use Approval Tests for PDF documents.


Original Link: https://dev.to/janvanryswyck/implementing-approval-tests-for-pdf-document-generation-11lo

Share this article:    Share on Facebook
View Full Article

Dev To

An online community for sharing and discovering great ideas, having debates, and making friends

More About this Source Visit Dev To