如何对绘制PDF图形的Python函数进行单元测试?
我正在开发一个CAD应用程序,它使用Cairo图形库来输出PDF文件。很多单元测试其实并不需要真的生成PDF文件,比如计算对象的预期边界框。不过,我想确保在我修改代码后,生成的PDF文件“看起来”是正确的。有没有什么自动化的方法可以做到这一点?我该如何尽可能地自动化这个过程?我需要逐个检查每个生成的PDF吗?我该如何解决这个问题,才能不抓狂呢?
7 个回答
我建议你试试xpresser这个工具 - (https://wiki.ubuntu.com/Xpresser)。这个工具可以帮助你找到相似的图片,而不是完全相同的图片,这正是这些情况下遇到的问题。
我不太确定xpresser是否还在积极开发中,或者它是否可以和独立的图片文件一起使用(我觉得可以)——总之,它的灵感来源于Sikuli项目(Sikuli是用Java写的,前端用的是Jython,而xpresser是用Python写的)。
(请查看下面的更新!)
我在Linux上用一个shell脚本做同样的事情,这个脚本包含了:
- ImageMagick的
compare
命令 pdftk
工具- Ghostscript(可选)
把这个移植到DOS/Windows的.bat
批处理文件也很简单。
我有一些由我的应用程序生成的参考PDF,这些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
compare
使用这个命令为每一页创建一个“差异”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
Ghostscript
由于自动插入的元数据(比如当前的日期和时间),PDF输出在基于MD5哈希的文件比较中效果不好。
如果你想自动发现所有纯白页面的情况,可以使用bmp256
输出设备转换为没有元数据的位图格式。你可以对原始PDF(参考和比较)或差异PDF页面进行这样的转换:
gs \
-o reference_diff_page_001.bmp \
-r72 \
-g595x842 \
-sDEVICE=bmp256 \
reference_diff_page_001.pdf
md5sum reference_diff_page_001.bmp
如果MD5值符合你对一个595x842 PostScript点的全白页面的预期,那么你的单元测试就通过了。
更新:
我不知道之前为什么没想到从ImageMagick的compare
生成一个直方图输出...
以下是一个命令管道,连接了两个不同的命令:
- 第一个命令和上面的
compare
一样,生成'白色像素相等,红色像素为差异'格式,只是它输出的是ImageMagick内部的miff
格式。它不会写入文件,而是输出到stdout。 - 第二个命令使用
convert
读取stdin,生成直方图并以文本形式输出结果。会有两行:- 一行表示白色像素的数量
- 另一行表示红色像素的数量。
下面是命令:
compare \
reference.pdf \
current.pdf \
-compose src \
miff:- \
| \
convert \
- \
-define histogram:unique-colors=true \
-format %c \
histogram:info:-
示例输出:
56934: (61937, 0, 7710,52428) #F1F100001E1ECCCC srgba(241,0,30,0.8)
444056: (65535,65535,65535,52428) #FFFFFFFFFFFFCCCC srgba(255,255,255,0.8)
(示例输出是通过使用这些reference.pdf和current.pdf文件生成的。)
我认为这种输出非常适合自动单元测试。如果你评估这两个数字,就可以轻松计算“红色像素”的百分比,甚至可以根据某个阈值决定返回PASSED或FAILED(如果你出于某种原因不一定需要“零红色”)。
你可以把PDF文件转换成一种叫做位图的图片格式(或者至少是无损压缩的图片),然后把每次测试生成的图片和一个标准的参考图片进行对比。只要有任何不同的地方,就会被标记为测试错误。