Practical testing reference

PDF Testing Guide

A sample PDF is most useful when it is tied to a clear test case. This guide shows how to test retrieval, upload validation, browser rendering, text extraction, visual output, email attachments, and automated workflows using predictable synthetic fixtures.

Last reviewed: August 13, 2026

Start with the behavior, not the filename

Teams often collect a folder full of random PDFs and reuse whichever file is easiest to find. That works until a bug appears. A 20 MB scanned contract, a password-protected statement, and a one-page text PDF exercise very different parts of a document workflow. If you do not know which file property matters, the same test can pass one day and fail the next for reasons unrelated to your code.

A better approach is to define one expected behavior and choose the smallest fixture that can prove or disprove it. Use a tiny text PDF for upload acceptance, a selectable-text file for extraction, a visual fixture for thumbnails, and a one-page file for print or signing flows. Once the simple case is stable, add edge cases deliberately.

GoalRecommended fixturePrimary assertion
Basic downloadsample.pdfThe final response is a PDF and the downloaded bytes are the expected fixture.
Small-file uploadsmall-sample.pdfThe form accepts a valid PDF well below the size limit.
Text extractionsample-text.pdfNative text can be found, copied, or parsed without OCR.
Rendering / thumbnailsample-with-images.pdfVisual blocks render without cropping, blank output, or unexpected scaling.
Single-page previewone-page-sample.pdfViewer, iframe, print, or signing UI handles one predictable page.

1. Test the download path

A successful click is not enough. A browser can show a download animation even when the server returned the wrong content after a redirect. For a reliable download test, check the final URL, status, content type, filename behavior, and—when reproducibility matters—the file hash.

Manual checklist

Command-line smoke check

curl -I https://samplepdf.org/files/sample.pdf
curl -L https://samplepdf.org/files/sample.pdf -o sample.pdf
shasum -a 256 sample.pdf

The current repository fixture sample.pdf is 843 bytes with SHA-256 f1054db56eaef90249677915b7604f075faf01756529f85dfdc1660b8f27b88d. If that hash changes after a deployment, investigate whether the file was intentionally regenerated.

2. Test an upload form in layers

Upload bugs are easier to diagnose when client validation, network transfer, server validation, storage, and post-upload preview are treated as separate stages. A single “upload failed” message hides which layer is responsible.

Client validationDoes the picker accept .pdf? Is the size rule shown before transfer? Is an invalid extension rejected with a useful message?
Network transferDoes the request start, show progress where appropriate, and finish without a timeout or retry loop?
Server validationDoes the backend verify more than the filename—such as MIME type or file signature—before accepting the document?
Storage and retrievalAfter upload, can the exact file be retrieved without being silently renamed, truncated, or replaced?

Start with small-sample.pdf to prove the happy path. Then add separate negative fixtures for an oversized file, a non-PDF renamed to .pdf, an encrypted PDF, a malformed PDF, and a document with many pages. Keeping those cases separate makes failures interpretable.

3. Verify PDF type by content, not extension alone

A filename ending in .pdf is not proof that the content is a PDF. Basic validators can inspect the first bytes for the PDF header signature and then hand the file to a real parser for structural validation. The synthetic core fixtures generated by this project begin with the standard %PDF-1.4 signature.

This distinction matters in security and reliability testing. An HTML error page saved as report.pdf may pass a naive extension check but fail immediately in a PDF viewer. Conversely, a valid PDF served with a generic content type may be rejected by a strict API even though a browser opens it.

4. Test browser preview and embedded viewers

Browser PDF behavior is not identical across Chrome, Safari, Firefox, Edge, mobile browsers, and embedded webviews. A good viewer test checks both rendering and the surrounding UI.

Use one-page-sample.pdf when debugging layout because it removes multi-page navigation from the test. Use sample-with-images.pdf when you want visible blocks that make clipping, scaling, or blank rendering easier to spot.

5. Separate text extraction from OCR

Native PDF text extraction and OCR are different problems. A PDF can contain selectable text objects, raster images of text, or a mixture of both. If you test OCR with a native-text fixture, an OCR engine may appear successful even when the real scanned-document path is never exercised.

sample-text.pdf is designed for native text checks: search, copy, parser output, and conversion. A text extractor should find the embedded text without needing OCR. For OCR testing, add a dedicated image-only scanned fixture and assert the recognized text separately.

Useful extraction assertions

6. Test visual rendering with an intentional fixture

The visual sample uses simple vector blocks instead of a copyrighted photograph or third-party artwork. That makes it useful for checking whether a renderer preserves visible regions, page boundaries, and basic color blocks without introducing licensing or privacy concerns into a test asset.

For production-grade visual QA, compare the rendered output against a known baseline image and allow a small tolerance for anti-aliasing differences between rendering engines. Large changes—missing blocks, clipped edges, blank pages, rotated output, or an incorrect page size—should fail the test.

7. Use hashes when the fixture must stay stable

A SHA-256 hash is useful when a test depends on exactly the same bytes over time. Store the expected hash next to the test case. If the fixture is intentionally regenerated, update the hash in one controlled change and record why. If the hash changes unexpectedly, stop treating the fixture as stable until the cause is understood.

FileBytesSHA-256
sample.pdf843f1054db56eaef90249677915b7604f075faf01756529f85dfdc1660b8f27b88d
small-sample.pdf82065adae5a24baddea47d07dfcad10572f184334d091b8ae7d5f1d4dc09a3538a7
one-page-sample.pdf8274aa90a0e0533ae6faa548c80f144b88839370532e0c5e0e1c773b12de34d7f52
sample-text.pdf8484529bbf3bb9d154aa6a4626642849b2b6fbaab660d85c65500cffa7ba9e7dd72
sample-with-images.pdf945e5825bb4824ef77e6196eb7b11816d31cae178328ea13102db31eb18e9f8e9b3

8. Build a small automated regression test

You do not need a large framework to catch basic regressions. A lightweight browser test can verify that the page is reachable, the download link points to a PDF, and the direct file request succeeds. A separate parser test can inspect the downloaded fixture.

test('sample PDF download is reachable', async ({ page, request }) => {
  await page.goto('https://samplepdf.org/sample-pdf-download/');
  const link = page.getByRole('link', { name: /download sample pdf/i }).first();
  const href = await link.getAttribute('href');
  expect(href).toMatch(/\.pdf$/);

  const response = await request.get(new URL(href, page.url()).href);
  expect(response.ok()).toBeTruthy();
  const bytes = await response.body();
  expect(bytes.subarray(0, 5).toString()).toBe('%PDF-');
});

Keep this test narrow. Browser automation should prove the user-facing path. Parser tests should prove document structure. Security scanning should prove the file is acceptable under your own security policy. Mixing every concern into one test makes failures harder to understand.

9. Add edge cases only after the baseline passes

The core fixtures on samplepdf.org are intentionally simple. They are not a comprehensive PDF conformance suite. Once your baseline works, add fixtures that target the features your product actually supports: multi-page documents, large files, embedded fonts, annotations, forms, encryption, digital signatures, rotated pages, unusual page sizes, image-only scans, damaged cross-reference tables, or incremental updates.

For each edge case, write down the expected outcome. “The app should handle this PDF” is vague. “The app should reject an encrypted PDF with an actionable password-protected-file message before upload completion” is testable.

10. Do not test with real private documents

Using a customer's invoice or an employee's resume because it is convenient creates unnecessary privacy and security risk. Synthetic fixtures make bug reports easier to share and reproduce. They also reduce the chance that screenshots, CI logs, support tickets, or demo recordings accidentally expose personal information.

When a bug only reproduces with a complex real document, create a sanitized or synthetic reproduction that keeps the relevant PDF feature while removing private content. That becomes a much better long-term regression fixture.

A reusable PDF test matrix

StageHappy-path assertionFailure exampleNext diagnostic
DownloadFinal response returns intended PDF bytesHTML error saved as .pdfInspect redirects, status, content type
UploadValid small PDF is acceptedRejected as unknown fileInspect client/server MIME and signature checks
StorageRetrieved bytes match uploaded bytesFile truncated or replacedCompare byte length and hash
PreviewFirst page rendersBlank iframeInspect viewer errors and frame/security headers
TextExpected native text extractedEmpty or garbled outputInspect text layer, fonts, parser
VisualVisible blocks match baselineCropping or missing regionInspect page size, scale, renderer
PrintCorrect one-page outputExtra blank pageInspect paper size, margins, orientation

Choose the next file

For a fast download and HTTP-path check, use Sample PDF Download. For structural details, use Sample PDF File. For test-goal selection, use Sample PDF for Testing. For native text behavior, use Sample PDF Text. For visual rendering, use Sample PDF With Images.