Skip to content

VerifyTests/Verify.OpenXml

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

111 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Verify.OpenXML

Discussions Build status NuGet Status

Extends Verify to allow verification of Word, Excel, and PowerPoint documents via OpenXML.

Supports Excel (xlsx), Word (docx), and PowerPoint (pptx) documents.

Features

Excel (xlsx)

  • Converts workbooks to CSV format for each worksheet
  • Extracts formulas and displays them alongside cell values
  • Captures document metadata (title, subject, creator, keywords, category, etc.)
  • Supports date scrubbing and GUID scrubbing for deterministic tests
  • Generates deterministic XLSX output using DeterministicIoPackaging

Word (docx)

  • Extracts document text content from paragraphs and tables
  • Captures document properties (title, subject, creator, keywords, etc.)
  • Captures custom document properties
  • Extracts font information
  • Generates deterministic DOCX output using DeterministicIoPackaging
  • Optionally renders each page to PNG via Morph (opt-in)

PowerPoint (pptx)

  • Extracts slide text from every slide, separated by ---
  • Captures document properties (title, subject, creator, keywords, etc.)
  • Reports slide count
  • Generates deterministic PPTX output using DeterministicIoPackaging

See Milestones for release notes.

Sponsors

Entity Framework Extensions

Entity Framework Extensions is a major sponsor and is proud to contribute to the development this project.

Entity Framework Extensions

Developed using JetBrains IDEs

JetBrains logo.

NuGet

Usage

Enable Verify.OpenXml

[ModuleInitializer]
public static void Initialize() =>
    VerifyOpenXml.Initialize();

snippet source | anchor

Excel

Verify a file

[Test]
public Task VerifyExcel() =>
    VerifyFile("sample.xlsx");

snippet source | anchor

Verify a Stream

[Test]
public Task VerifyExcelStream()
{
    var stream = new MemoryStream(File.ReadAllBytes("sample.xlsx"));
    return Verify(stream, "xlsx");
}

snippet source | anchor

Verify a SpreadsheetDocument

[Test]
public async Task VerifySpreadsheetDocument()
{
    await using var stream = File.OpenRead("sample.xlsx");
    using var reader = SpreadsheetDocument.Open(stream, false);
    await Verify(reader);
}

snippet source | anchor

Example snapshot

0,First Name,Last Name,Gender,Country,Date,Age,Id,Formula
1,Dulce,Abril,Female,United States,2017-10-15,32,1562,G2+H21594 (G2+H2)
2,Mara,Hashimoto,Female,Great Britain,2016-08-16,25,1582,1607
3,Philip,Gent,Male,France,2015-05-21,36,2587,2623
4,Kathleen,Hanner,Female,United States,2017-10-15,25,3549,3574
5,Nereida,Magwood,Female,United States,2016-08-16,58,2468,2526
6,Gaston,Brumm,Male,United States,2015-05-21,24,2554,2578

snippet source | anchor

Word

Verify a file

[Test]
public Task VerifyWord() =>
    VerifyFile("sample.docx");

snippet source | anchor

Verify a Stream

[Test]
public Task VerifyWordStream()
{
    var stream = new MemoryStream(File.ReadAllBytes("sample.docx"));
    return Verify(stream, "docx");
}

snippet source | anchor

Binary output across .NET frameworks

When verifying binary package output (xlsx, docx, nupkg, etc.) across multiple target frameworks (e.g. net48 and net10.0), the binary output may differ due to Deflate compression implementation differences. The XML content within entries is identical — only the compressed bytes differ. Use UniqueForRuntime to generate framework-specific verified files:

await Verify(stream, extension: "xlsx")
    .UniqueForRuntime();

See Verify Naming docs for more details.

Verify a WordprocessingDocument

[Test]
public async Task VerifyWordprocessingDocument()
{
    await using var stream = File.OpenRead("sample.docx");
    using var reader = WordprocessingDocument.Open(stream, false);
    await Verify(reader);
}

snippet source | anchor

Render pages to PNG (opt-in)

Verify.OpenXml can additionally snapshot a rendered PNG of every page of a .docx using the Morph renderer. This catches visual regressions (layout, fonts, images, tables) that the text-based snapshot would miss.

Enabling rendering

The base Morph.OpenXml package is referenced automatically by Verify.OpenXml on net10.0. To turn on rendering, add exactly one backend package to the test project:

Morph.OpenXml.Skia — uses SkiaSharp:

<PackageReference Include="Morph.OpenXml.Skia" />

or Morph.OpenXml.ImageSharp — uses ImageSharp, fully managed:

<PackageReference Include="Morph.OpenXml.ImageSharp" />

The backend is detected at runtime by probing for the assembly. No code changes are needed in ModuleInitializer.cs — the existing VerifyOpenXml.Initialize() call picks it up automatically.

Output

When a backend is present, every Word verification (file, stream, or WordprocessingDocument) produces additional PNG targets — one per page — alongside the existing .verified.docx and .verified.txt files. For example, a two-page VerifyWord test produces:

Samples.VerifyWord.verified.docx
Samples.VerifyWord#00.verified.txt
Samples.VerifyWord#01.verified.txt
Samples.VerifyWord#page01.verified.png
Samples.VerifyWord#page02.verified.png

Pages are zero-padded to two digits (page01, page02, ...) so file ordering matches page order.

Backend selection rules
  • Neither backend referenced — rendering is silently skipped. The text and binary targets are still produced. This is the default for consumers who do not opt in.
  • One backend referenced — that backend is used for all Word verifications.
  • Both backends referenced — an exception is thrown on the first Word verification with a clear message. Pick one.
Target framework support

Rendering is only available on net10.0 because Morph targets net10.0 only. On net472, net48, net8.0, and net9.0, Word verification continues to produce only the existing text and binary targets — the rendering code is conditionally compiled out.

Cross-platform PNG stability

PNG output from Skia and ImageSharp depends on installed fonts and platform-specific rasterization. A .verified.png generated on one machine may not be byte-identical on another OS or with different fonts installed. Recommendations:

  • Generate and commit .verified.png files from a single canonical machine (often a CI agent).
  • For cross-platform CI, combine with UniqueForOSPlatform() so each OS gets its own .verified.png:
await Verify(stream, "docx")
    .UniqueForOSPlatform();
  • Consider Verify's image comparison tooling (e.g. Verify.ImageMagick) for tolerance-based PNG diffing.

See Verify Naming docs for the full list of UniqueFor* modifiers.

Sharing one test suite across both backends

For a worked example of running the same test suite against both backends side-by-side, see the Tests.Skia and Tests.ImageSharp projects in this repository. Both projects link the source files from Tests and use DerivePathInfo in their ModuleInitializer to redirect snapshots into the per-backend project directory:

[ModuleInitializer]
public static void Initialize()
{
    VerifyOpenXml.Initialize();

    var projectDir = ProjectDir();
    Verifier.DerivePathInfo(
        (sourceFile, projectDirectory, type, method) =>
            new(directory: projectDir, typeName: type.Name, methodName: method.Name));
}

static string ProjectDir([CallerFilePath] string here = "") =>
    Path.GetDirectoryName(here)!;

This pattern lets a single set of tests produce two parallel sets of .verified.* snapshots — one per rendering backend.

PowerPoint

Verify a file

[Test]
public Task VerifyPowerpoint() =>
    VerifyFile("sample.pptx");

snippet source | anchor

Verify a Stream

[Test]
public Task VerifyPowerpointStream()
{
    var stream = new MemoryStream(File.ReadAllBytes("sample.pptx"));
    return Verify(stream, "pptx");
}

snippet source | anchor

Verify a PresentationDocument

[Test]
public async Task VerifyPresentationDocument()
{
    await using var stream = File.OpenRead("sample.pptx");
    using var reader = PresentationDocument.Open(stream, false);
    await Verify(reader);
}

snippet source | anchor

About

Extends Verify to allow verification of Word and Excel documents via OpenXML.

Resources

License

Code of conduct

Stars

Watchers

Forks

Sponsor this project

 

Contributors

Languages