Как провести модульное тестирование функции Python, которая рисует графику PDF?
Я пишу CAD-приложение, которое выводит PDF-файлы с использованием графической библиотеки Cairo. Большая часть модульного тестирования не требует фактической генерации файлов PDF, таких как вычисление ожидаемых ограничивающих рамок объектов. Однако я хочу убедиться, что сгенерированные PDF-файлы "выглядят" правильно после того, как я изменил код. Есть ли автоматизированный способ сделать это? Как я могу максимально автоматизировать? Нужно ли визуально проверять каждый сгенерированный PDF? Как я могу решить эту проблему, не вырывая мои волосы?
6 ответов
Вы можете захватить PDF как растровое (или, по крайней мере, сжатое без потерь) изображение, а затем сравнить изображение, сгенерированное каждым тестом, с эталонным изображением того, как оно должно выглядеть. Любые различия будут помечены как ошибка для теста.
(Смотрите также обновление ниже!)
Я делаю то же самое, используя сценарий оболочки в Linux, который оборачивает
- ImageMagick-х
compare
команда pdftk
полезность- Ghostscript (опционально)
(Было бы довольно легко перенести это на .bat
Пакетный файл для DOS/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
сравнить
Используйте эту команду для создания PDF-страницы diff для каждой из страниц:
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 не работает хорошо для сравнений файлов на основе 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
Если MD5sum - это то, что вы ожидаете для полностью белой страницы 595x842 точек PostScript, то ваш модульный тест пройден.
Обновить:
Я не знаю, почему я раньше не думал о создании вывода гистограммы из ImageMagick compare
...
Ниже приведен конвейер команд, объединяющий две разные команды:
- первый такой же, как указано выше
compare
который генерирует формат "белые пиксели равны, красные пиксели - различия", только выводит внутренний ImageMagickmiff
формат. Он пишет не в файл, а в стандартный вывод. - второй использует
convert
читать стандартный ввод, генерировать гистограмму и выводить результат в текстовом виде. Там будет две строки:- один указывает на количество белых пикселей
- другой, указывающий количество красных пикселей.
Здесь это идет:
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 на основе определенного порога (если вам не обязательно нужен "ноль красного" по какой-то причине).
Первая идея, которая появляется у меня в голове, - использовать утилиту diff. Они обычно используются для сравнения текстов документов, но могут также сравнивать формат PDF. Используя его, вы можете сравнить ожидаемый результат с предоставленным выходом.
Первый результат Google дает мне это. Хотя это и коммерчески, могут быть и другие бесплатные / открытые альтернативы.
Я написал инструмент на Python для проверки PDF-файлов для документации моего работодателя. Он имеет возможность сравнивать отдельные страницы с основными изображениями. Я использовал библиотеку swftools для экспорта страницы в формат PNG, а затем использовал библиотеку изображений Python для сравнения ее с мастером.
Соответствующий код выглядит примерно так (он не будет работать, так как есть некоторые зависимости от других частей скрипта, но вы должны понять):
# exporting
gfxpdf = gfx.open("pdf", self.pdfpath)
if os.path.isfile(pngPath):
os.remove(pngPath)
page = gfxpdf.getPage(pagenum)
img = gfx.ImageList()
img.startpage(page.width, page.height)
page.render(img)
img.endpage()
img.save(pngPath)
return os.path.isfile(pngPath)
# comparing
outPng = os.path.join(outpath, pngname)
masterPng = os.path.join(outpath, "_master", pngname)
if os.path.isfile(masterPng):
output = Image.open(outPng).convert("RGB") # discard alpha channel, if any
master = Image.open(masterPng).convert("RGB")
mismatch = any(x[1] for x in ImageChops.difference(output, master).getextrema())
Я хотел бы попробовать это с помощью xpresser - (https://wiki.ubuntu.com/Xpresser). Вы можете попытаться сопоставить изображения с похожими изображениями, а не с точными копиями - что является проблемой в этих случаях.
Я не знаю, разрабатывается ли xpresser, или его можно использовать с автономными файлами изображений (я так думаю) - в любом случае он берет свои идеи из проекта Sikuli (который является Java с интерфейсом Jython, в то время как xpresser - это Python).
«cmppdf» сравнивает либо внешний вид, либо текстовое содержимое PDF-файлов.
Это bash-скрипт, который можно загрузить с https://abhweb.org/jima/cmppdf?v .
Оно используетpdftk
иcompare
для графического сравнения PDF-файлов, аналогично тому, что другие описали в других ответах. Метаданные (все, что не меняет фактический внешний вид) не сравниваются.
Опция сравнения текста используетpdftotxt
иdiff
.