PdfPecker.Testing 1.23.0

dotnet add package PdfPecker.Testing --version 1.23.0
                    
NuGet\Install-Package PdfPecker.Testing -Version 1.23.0
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="PdfPecker.Testing" Version="1.23.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="PdfPecker.Testing" Version="1.23.0" />
                    
Directory.Packages.props
<PackageReference Include="PdfPecker.Testing" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add PdfPecker.Testing --version 1.23.0
                    
#r "nuget: PdfPecker.Testing, 1.23.0"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package PdfPecker.Testing@1.23.0
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=PdfPecker.Testing&version=1.23.0
                    
Install as a Cake Addin
#tool nuget:?package=PdfPecker.Testing&version=1.23.0
                    
Install as a Cake Tool

PdfPecker.Testing

Snapshot tests for PDFs. PdfAssert.MatchesSnapshot compares the PDF your code makes with a stored one, leaving out what changes on every run (creation dates, file IDs, the compressed bytes of streams), and when they differ it writes page images with the changed pixels marked. It also checks for text and page counts.

dotnet add package PdfPecker.Testing

It works with xUnit, NUnit, MSTest or any other test framework, because a failed check throws PdfAssertException, which every framework reports as a failed test. Its only dependency is PdfPecker, which reads and renders the PDFs; the PDFs under test can come from PdfPecker, PdfPecker.Fluent or anything else. PdfPecker.Testing is released together with PdfPecker and always has the same version.

using PdfPecker.Testing;

[Fact]
public void Invoice_looks_as_before()
{
    byte[] pdf = InvoiceService.Render(SampleData.Invoice);

    PdfAssert.MatchesSnapshot(pdf, "invoice");          // Snapshots/invoice.pdf next to this test file
    PdfAssert.ContainsText(pdf, "Total due: 1,500.00");
    PdfAssert.ContainsText(pdf, "Payment terms", pageNumber: 2);
    PdfAssert.DoesNotContainText(pdf, "{{");             // no template placeholder left
    PdfAssert.HasPageCount(pdf, 2);
}

Snapshots

The first run has no snapshot, so it fails and writes the PDF as Snapshots/invoice.received.pdf. Look at it, and rename it to invoice.pdf to make it the snapshot. Commit the snapshots with the tests.

When a later PDF differs, the check fails with the first difference it found, for example

The PDF doesn't match the snapshot …/Snapshots/invoice.pdf: the stream of object 8 differs (260 bytes in the
snapshot, 265 in the PDF): line 7 is "1 0 0 1 38.25 486.53 Tm (Consulting) Tj" in the snapshot and
"1 0 0 1 38.25 486.53 Tm (Design work) Tj" in the PDF. Page 1 (1,561 pixels) looks different; the diff images are
next to the snapshot. …

and writes next to the snapshot:

  • invoice.received.pdf, the new PDF;
  • for each page that looks different, invoice.page-1.expected.png and invoice.page-1.actual.png, and invoice.page-1.diff.png: the new page faded to grey with the changed pixels in magenta.

To accept a change, replace the snapshot with the received file, or run the tests with the environment variable PDFPECKER_UPDATE_SNAPSHOTS=1, which writes every missing or changed snapshot and passes. A check that passes deletes the files an earlier failure left. Add the failure files to .gitignore:

*.received.pdf
*.page-*.expected.png
*.page-*.actual.png
*.page-*.diff.png

What has to match

By default the comparison is of the files' content: every object in the same order, with streams inflated, and without dates, file IDs and XMP document IDs. PdfPecker writes the same objects for the same input, so this catches every change, including those that don't show on the page, such as a link target, a bookmark, the title or the text that copy and paste and screen readers get. A PDF made again from the same input matches without a fixed CreationDate.

PdfSnapshotComparison.Appearance compares the rendered pages instead. Use it for PDFs from other producers, or when only the look matters, for example across a PdfPecker update that writes the same pages with different objects:

var options = new PdfSnapshotOptions
{
    Comparison = PdfSnapshotComparison.Appearance,
    ColorTolerance = 2,         // a channel may differ by up to 2 of 255
    MaxDifferentPixels = 50,    // per page
};
PdfAssert.MatchesSnapshot(pdf, "invoice", options);
PdfSnapshotOptions Default What it does
Directory Snapshots next to the test's source file Where the snapshots and failure files are
Comparison Content Content or Appearance, as above
Dpi 72 Resolution of the compared and written page images
ColorTolerance 0 How far a pixel's channel may differ before it counts as different
MaxDifferentPixels 0 How many different pixels a page may have in Appearance comparisons
UpdateSnapshots false Write the PDF as the snapshot instead of failing, like PDFPECKER_UPDATE_SNAPSHOTS=1
WriteDiffImages true Write the page images on a failure
Password none Password of encrypted PDFs

The default folder comes from the source file path the compiler records for the calling test. A build with ContinuousIntegrationBuild or PathMap records other paths, and the check then asks for Directory; for example Directory = Path.Combine(AppContext.BaseDirectory, "Snapshots") with the snapshots copied to the output.

Text and pages

ContainsText, DoesNotContainText and HasPageCount read the PDF with PdfPecker's text extraction. Line breaks and other runs of white space count as one space, so text that wraps differently still matches. A PDF that can't be read fails the check with a PdfAssertException that holds the reason.

Limitations

  • The content comparison reads objects in file order, so a PDF whose producer orders or numbers its objects differently on every run needs Appearance.
  • Signed and encrypted PDFs change on every run by design (the signature and the key are new each time); compare them with Appearance, giving Password for encrypted ones.
  • Rendering uses PdfPecker's renderer, so Appearance compares PdfPecker's picture of the pages, not a particular viewer's.
Product Compatible and additional computed target framework versions.
.NET net8.0 is compatible.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 is compatible.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 is compatible.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
1.23.0 100 11/4/2026

What changed in each release: https://pdfpecker.net/docs/changelog/