Автоматизируем проверку содержимого PDF-файлов с помощью pdf-test
Многие сервисы в различных отраслях генерируют печатные формы счетов, отчётов и прочего в формате PDF. И конечно, перед специалистами тестирования встаёт вопрос о проверке этих документов.
Обычно получается так, что сам факт генерации документа достаточно несложно покрыть автотестами, а вот проверку содержимого оставляют для ручного тестирования. Однако в подобных документах может быть много незаметных мест, различий и неточностей, которые человек может просто не заметить. Поэтому появляется необходимость проверку этих документов автоматизировать.
В этой статье мы познакомим вас с инструментом, который достаточно просто может закрыть потребность в проверке содержания PDF-файлов. Это инструмент с открытым исходным кодом — pdf-test. Он по сути является обёрткой pdfbox и позволяет из коробки использовать основные мэтчеры, не задумываясь о том, чтобы писать свои или о том, как именно парсить документ. Рассмотрим далее его применение на языке Java.
Установка
Как и для любого другого инструмента, необходимо добавить зависимость в ваш файл проекта (актуальная версия на момент февраля 2024 года — 1.8.1):
pom.xml для Maven
com.codeborne
pdf-test
1.8.1
test
build.gradle для Gradle
testImplementation 'com.codeborne:pdf-test:1.8.1'
Можно начинать пользоваться.
Использование
Сценарий использования данного инструмента состоит всего из двух шагов:
Создание экземпляра класса PDF;
Проверка этого объекта средствами AssertJ или Hamcrest;
Рассмотрим всё по порядку.
Создание экземпляра класса PDF
Pdf-test позволяет создать экземпляр для дальнейшей работы несколькими способами:
Из файла:
PDF pdf = new PDF(new File("test.pdf"));
Из адреса URL или URI:
PDF pdf = new PDF(URL())/PDF pdf = new PDF(URI());
Из InputStream:
PDF pdf = new PDF(getClass().getClassLoader().getResourceAsStream("test.pdf"));
Из массива байтов:
PDF pdf = new PDF(byteArray);
Для каждого из этих способов создать экземпляр класса PDF, существует перегрузка с указанием страниц, которые нужно парсить в объект:
PDF pdf = new PDF(new File("test.pdf"), 1, 2);
Данный метод создаст экземпляр класса PDF, в котором будут страницы исходного документа с 1 по 2. Если вы попытаетесь создать объект из того, что файлом PDF не является, pdf-test вас об этом предупредит, выдав следующее исключение:
IllegalArgumentException – Invalid PDF file: test.pdf
Итак, теперь у нас есть объект PDF, который мы можем проверять.
Проверки PDF-файла
Что же мы можем проверить в нашем файле? Вообще, весь текст, кроме картинок и таблиц (хотя на таблицы в репозитории есть задача, за которую, возможно, кто-то возьмётся). Кроме содержимого мы можем проверить свойства файла при их наличии. Вот список свойств, которые доступны для проверки в pdf-test:
int numberOfPages — число страниц в файле;
String author — автор файла;
Calendar creationDate — время создания файла;
String creator — источник файла;
String keywords — ключевые слова;
String producer — программа-генератор файла;
String subject — тема;
String title название файла;
boolean encrypted — присутствие шифрования;
boolean signed — присутствие электронной подписи;
String signerName — имя подписанта;
Calendar signatureTime — время подписания;
Следующие методы нужны уже для проверки содержимого PDF:
containsText(String text, String... texts)
— проверка вхождения переданных строк в файл. Данная проверка регистрозависима, игнорирует множественные пробелы в переданной строке (то есть строки «Hello world» и «Hello world» посчитает одинаковыми). Если будет передано несколько строк для проверки, то будет проверятся их вхождение в документ именно в том порядке, в каком они были переданы в метод. Если в файле несколько одинаковых подстрок, то находится только первое вхождение.
doesNotContainText(String text, String... texts)
— проверка отсутствия переданных строк в тексте. Обладает теми же свойствами, что и предыдущая проверка.
containsExactText(String substring)
— проверка присутствия в файле в точности переданного текста. Регистрозависима и не пропускает пробелы, в отличие от метода containsText (String text, String… texts).
doesNotContainExactText(String substring)
— проверка, противоположная по смыслу предыдущей. Регистрозависима и не пропускает пробелы, в отличие от метода doesNotContainsText (String text, String… texts).
containsTextCaseInsensitive(String substring)
— регистронезависимая проверка присутствия в файле строки текста. Игнорирует пробелы, как и метод containsText (String text, String… texts).
И самое интересное:
matchesText(String regex) / matchesText(Pattern regex)
— проверка того, что в файле есть подстрока, удовлетворяющая регулярному выражению. С помощью этой проверки можно проверять повторные вхождения текста, взаимное расположение текста, а также большие текстовые формы или текст, в котором есть меняющиеся данные (номера, имена, название и прочее).
Перейдём к практике
Приведём немного утрированный, но показательный пример того, как всё это может применяться на практике. Допустим, у нас есть генерируемое платёжное поручение с названием transaction.pdf:
Тогда тест по проверке нашего документа с использованием AssertJ будет выглядеть примерно так:
@Test
public void bankTransactionTest() throws Exception {
PDF pdf = new PDF(new File("transaction.pdf"));
assertThat(pdf, containsText("11.11.2023"));
assertThat(pdf, containsText("Поступ. в банк плат.", "Списано со сч. плат."));
assertThat(pdf, matchText(".*ПЛАТЕЖНОЕ ПОРУЧЕНИЕ № \\d{3}.*"));
assertThat(pdf, containsText("Дата", "Вид платежа", "Сумма прописью"));
assertThat(pdf, containsText("ИНН", "КПП"));
assertThat(pdf, containsExactText("Иван Тестов"));
assertThat(pdf, containsText("Плательщик"));
assertThat(pdf, matchText(".*Сч.№ \\d{20}.*"));
assertThat(pdf, containsTextCaseInsensitive("ПАО \"БАНК \"САНКТ-ПЕТЕРБУРГ\""));
assertThat(pdf, containsText("Отметки банка"));
assertThat(pdf, matchText(".*БИК \\d{9}.*"));
assertThat(pdf, matchText(".*Код операции \\d{12}.*"));
assertThat(pdf, doesNotContainsText("Test", "dev"));
}
Вывод
Теперь вы знаете, как применить несложный и достаточно удобный инструмент проверки текста внутри pdf-файлов, и сможете прокачать им свои тесты. Пусть в нём не так много функциональности, но этого вполне достаточно, чтобы проверить PDF на то, что в нём есть вся нужная информация и ничего не потеряно, например, при генерации какой-нибудь важной квитанции.
К тому же, это опенсорс-проект, и, скорее всего, со временем в нём появятся новые методы. Например, в данный момент открыта задача на добавление метода для проверки таблиц, может, именно вы её и решите.
Подробнее познакомиться с исходниками pdf-test, примерами использования и предложить свои нововведения можно, перейдя в репозиторий.
Конечно, это не единственный инструмент для работы с PDF, но кажется, наиболее простой в освоении и в работе. Про библиотеку pdfbox, которая находится у него под капотом, можно почитать здесь.
Спасибо за внимание!
Больше авторских материалов для разработчиков в тестировании от моих коллег читайте в соцсетях SimbirSoft — ВКонтакте и Telegram.