如何对绘制PDF图形的Python函数进行单元测试?

Nat*_*ton 19 python pdf-generation unit-testing imagemagick cairo

我正在编写一个使用Cairo图形库输出PDF文件的CAD应用程序.许多单元测试不需要实际生成PDF文件,例如计算对象的预期边界框.但是,我想确保在更改代码后生成的PDF文件"看起来"正确.有没有自动化的方法来做到这一点?我怎样才能尽可能自动化?我是否需要目视检查每个生成的PDF?如何在不拔头发的情况下解决这个问题?

Kur*_*fle 21

(另请参阅下面的更新!)

我在Linux上使用shell脚本做同样的事情

  1. ImageMagick的compare命令
  2. pdftk实用程序
  3. Ghostscript(可选)

(将其移植到.batDOS/Windows 的批处理文件中会相当容易.)

我有一些参考PDF由我的应用程序创建,是"已知的好".将代码更改后新生成的PDF与这些参考PDF进行比较.比较是逐个像素完成的,并保存为新的PDF.在此PDF中,所有未更改的像素都涂成白色,而所有不同的像素都涂成红色.

以下是构建基块:

PDFTK

使用此命令将多页PDF文件拆分为多个单页PDF:

pdftk  reference.pdf  burst  output  somewhere/reference_page_%03d.pdf
pdftk  comparison.pdf burst  output  somewhere/comparison_page_%03d.pdf
Run Code Online (Sandbox Code Playgroud)

相比

使用此命令为每个页面创建"diff"PDF页面:

compare \
       -verbose \
       -debug coder -log "%u %m:%l %e" \
        somewhere/reference_page_001.pdf \
        somewhere/comparison_page_001.pdf \
       -compose src \
        somewhereelse/reference_diff_page_001.pdf
Run Code Online (Sandbox Code Playgroud)

Ghostscript的

由于自动插入的元数据(例如当前日期+时间),PDF输出不适用于基于MD5hash的文件比较.

如果要自动发现由纯白页组成的所有案例,您还可以使用bmp256输出设备转换为无元数据的位图格式.您可以为原始PDF(参考和比较)或diff-PDF页面执行此操作:

 gs \
   -o reference_diff_page_001.bmp \
   -r72 \
   -g595x842 \
   -sDEVICE=bmp256 \
    reference_diff_page_001.pdf

 md5sum reference_diff_page_001.bmp
Run Code Online (Sandbox Code Playgroud)

如果MD5sum是您对595x842 PostScript点的全白页所期望的,那么您的单元测试通过了.


更新:

我不知道为什么我以前没想过从ImageMagick 生成直方图输出compare......

以下是链接2个不同命令的命令管道:

  1. 第一个与上面相同,compare它产生'白色像素相等,红色像素是差异' -格式,只有它输出​​ImageMagick内部miff格式.它不会写入文件,而是写入stdout.
  2. 第二个用于convert读取标准输入,生成直方图并以文本形式输出结果.将有两行:
    • 一个表示白色像素的数量
    • 另一个表示红色像素的数量.

在这里:

compare \
   reference.pdf \
   current.pdf \
  -compose src \
   miff:- \
| \
convert \
   - \
  -define histogram:unique-colors=true \
  -format %c \
   histogram:info:-
Run Code Online (Sandbox Code Playgroud)

样本输出:

 56934: (61937,    0, 7710,52428) #F1F100001E1ECCCC srgba(241,0,30,0.8)
444056: (65535,65535,65535,52428) #FFFFFFFFFFFFCCCC srgba(255,255,255,0.8)
Run Code Online (Sandbox Code Playgroud)

(样本输出是使用这些reference.pdfcurrent.pdf文件生成的.)

我认为这种类型的输出非常适合自动单元测试.如果您评估这两个数字,您可以轻松计算"红色像素"百分比,甚至可以根据某个阈值决定返回PASSEDFAILED(如果由于某种原因您不一定需要"零红色").


jpr*_*ete 8

您可以将PDF捕获为位图(或至少是无损压缩的)图像,然后将每个测试生成的图像与其应该看起来的参考图像进行比较.任何差异都将被标记为测试的错误.

  • 就我而言,PDF图形存储为矢量,因此文件大小非常小。我与Cairo进行了测试,结果证明PDF生成是确定性的,这意味着一个简单的`diff`就足以标记一个错误,就像您建议的那样。 (2认同)