«1. Введение

В этой статье мы рассмотрим библиотеку PDFUnit для тестирования PDF-файлов.

Используя мощные API, предоставляемые PDFUnit, мы можем работать с PDF-файлами и проверять текст, изображения, закладки и ряд других вещей.

В конечном итоге мы можем написать довольно сложные тестовые примеры с помощью PDFUnit, но давайте начнем с наиболее распространенных вариантов использования, которые будут применяться к большинству ваших производственных PDF-файлов и обеспечат отличную основу для дальнейшей разработки.

Важное примечание: PDFUnit доступен бесплатно для ознакомительных целей, но не для коммерческого использования.

2. Установка и настройка

Текущая версия PDFUnit (2016.05) недоступна в репозитории Maven Central. Следовательно, нам нужно загрузить и установить банки вручную. Пожалуйста, следуйте инструкциям на официальном сайте для ручной установки.

3. Количество страниц

Давайте начнем с простого примера, который просто проверяет количество страниц в заданном файле PDF:

@Test
public void givenSinglePage_whenCheckForOnePage_thenSuccess() {
 
    String filename = getFilePath("sample.pdf");
    AssertThat.document(filename)
      .hasNumberOfPages(1);
}

getFilePath() — это простой метод, не связанный с PDFUnit, который просто возвращает путь к файлу PDF в виде строки.

Все тесты PDFUnit начинаются с вызова AssertThat.document(), который подготавливает документ к тестированию. hasNumberOfPages() принимает int в качестве аргумента, который указывает количество страниц, которые должен содержать PDF. В нашем случае файл sample.pdf содержит только одну страницу, поэтому тест проходит успешно.

Если фактическое количество страниц не совпадает с аргументом, генерируется исключение.

Давайте рассмотрим пример тестирования сценария при возникновении исключения:

@Test(expected = PDFUnitValidationException.class)
public void givenMultiplePages_whenCheckForOnePage_thenException() {
    String filename = getFilePath("multiple_pages.pdf");
    AssertThat.document(filename)
      .hasNumberOfPages(1);
}

В этом случае файл multiple_pages.pdf содержит несколько страниц. Следовательно, создается исключение PDFUnitValidationException.

4. Файлы, защищенные паролем

Работать с файлами, защищенными паролем, снова очень просто. Единственная разница заключается в вызове AssertThat.document(), где нам нужно передать второй аргумент, который является паролем файла:

@Test
public void givenPwdProtected_whenOpenWithPwd_thenSuccess() {
    String filename = getFilePath("password_protected.pdf");
    String userPassword = "pass1";

    AssertThat.document(filename, userPassword)
      .hasNumberOfPages(1);
}

5. Сравнение текста

Давайте теперь сравним тестовый PDF (пример .pdf) по сравнению с эталонным PDF (sample_reference.pdf). Если текст тестируемого файла совпадает с эталонным файлом, то тест завершается успешно:

@Test
public void whenMatchWithReferenceFile_thenSuccess() {
    String testFileName = getFilePath("sample.pdf");
    String referenceFileName = getFilePath("sample_reference.pdf");

    AssertThat.document(testFileName)
      .and(referenceFileName)
      .haveSameText();
}

Метод haveSameText() выполняет всю работу по сравнению текста между двумя файлами.

Если мы не хотим сравнивать полный текст между двумя файлами, а вместо этого хотим проверить наличие определенного текста на определенной странице, нам пригодится метод contains():

@Test
public void whenPage2HasExpectedText_thenSuccess() {
 
    String filename = getFilePath("multiple_pages.pdf");
    String expectedText = "Chapter 1, content";
 
    AssertThat.document(filename)
      .restrictedTo(PagesToUse.getPage(2))
      .hasText()
      .containing(expectedText);
}

Вышеупомянутое test завершается успешно, если страница № 2 файла multiple_pages.pdf содержит ожидаемый текст в любом месте страницы. Отсутствие или присутствие любого другого текста, кроме ожидаемого текста, не влияет на результаты.

Давайте теперь сделаем тест более строгим, проверив, присутствует ли конкретный текст в определенной области страницы, а не на всей странице. Для этого нам нужно понять концепцию PageRegion.

PageRegion — это прямоугольный подраздел внутри тестируемой страницы. PageRegion должен полностью находиться под фактической страницей. Если какая-либо часть PageRegion выходит за пределы фактической страницы, это приведет к ошибке.

PageRegion определяется четырьмя элементами:

  1. leftX – the number of millimeters a verticle line is away from the leftmost vertical edge of the page
  2. upperY – the number of millimeters a horizontal line is away from the topmost horizontal edge of the page
  3. width – the width of the region in millimeters
  4. height – the height of the region millimeters

Чтобы лучше понять эту концепцию, давайте создадим PageRegion, используя следующие атрибуты:

  1. leftX = 20
  2. upperY = 10
  3. width = 150
  4. height = 50

Вот примерное изображение вышеуказанного PageRegion:

Когда концепция Ясно, соответствующий тестовый пример относительно проще:

@Test
public void whenPageRegionHasExpectedtext_thenSuccess() {
    String filename = getFilePath("sample.pdf");
    int leftX = 20;
    int upperY = 10;
    int width = 150;
    int height = 50;
    PageRegion regionTitle = new PageRegion(leftX, upperY, width, height);

    AssertThat.document(filename)
      .restrictedTo(PagesToUse.getPage(1))
      .restrictedTo(regionTitle)
      .hasText()
      .containing("Adobe Acrobat PDF Files");
}

Здесь мы создали PageRegion на странице №1 файла PDF и проверили текст в этой области.

6. Закладки

Давайте рассмотрим пару тестов, связанных с закладками:

@Test
public void whenHasBookmarks_thenSuccess() {
    String filename = getFilePath("with_bookmarks.pdf");

    AssertThat.document(filename)
      .hasNumberOfBookmarks(5);
}

Этот тест завершится успешно, если в файле PDF будет ровно пять закладок.

Метки закладок также можно проверить:

@Test
public void whenHasBookmarksWithLabel_thenSuccess() {
    String filename = getFilePath("with_bookmarks.pdf");

    AssertThat.document(filename)
      .hasBookmark()
      .withLabel("Chapter 2")
      .hasBookmark()
      .withLinkToPage(3);
}

Здесь мы проверяем, есть ли в данном PDF закладка с текстом «Глава 2». Он также проверяет, есть ли закладка, которая ссылается на страницу № 3.

7. Изображения

Изображения — еще один важный аспект PDF-документов. Модульное тестирование изображений внутри PDF снова очень просто:

@Test
public void whenHas2DifferentImages_thenSuccess() {
    String filename = getFilePath("with_images.pdf");

    AssertThat.document(filename)
      .hasNumberOfDifferentImages(2);
}

«

«Этот тест проверяет, что в PDF-файле используются ровно два разных изображения. Количество различных изображений относится к фактическому количеству изображений, хранящихся в документе PDF.

Однако возможно, что внутри документа хранится одно изображение логотипа, но оно отображается на каждой странице документа. Это относится к количеству видимых изображений, которое может быть больше, чем количество различных изображений.

@Test
public void whenHas2VisibleImages_thenSuccess() {
    String filename = getFilePath("with_images.pdf");
    AssertThat.document(filename)
      .hasNumberOfVisibleImages(2);
}

Давайте посмотрим, как проверять видимые изображения:

PDFUnit достаточно мощен, чтобы сравнивать содержимое изображений побайтно. Это также означает, что изображение в PDF-файле и эталонное изображение должны точно совпадать.

@Test
public void whenImageIsOnAnyPage_thenSuccess() {
    String filename = getFilePath("with_images.pdf");
    String imageFile = getFilePath("Superman.png");

    AssertThat.document(filename)
      .restrictedTo(AnyPage.getPreparedInstance())
      .hasImage()
      .matching(imageFile);
}

Из-за сравнения байтов различные форматы изображений, такие как BMP и PNG, считаются неравными:

Обратите внимание на использование AnyPage здесь. Мы не ограничиваем появление изображения на какой-либо конкретной странице, а на любой странице всего документа.

Изображение для сравнения может принимать форму BufferedImage, File, InputStream или URL, за исключением строки, представляющей имя файла.

8. Встроенные файлы

@Test
public void whenHasEmbeddedFile_thenSuccess() {
    String filename = getFilePath("with_attachments.pdf");
 
    AssertThat.document(filename)
      .hasEmbeddedFile();
}

Некоторые PDF-документы содержат встроенные файлы или вложения. Их также необходимо протестировать:

Это проверит, есть ли в тестируемом документе хотя бы один встроенный файл.

@Test
public void whenHasmultipleEmbeddedFiles_thenSuccess() {
    String filename = getFilePath("with_attachments.pdf");

    AssertThat.document(filename)
      .hasNumberOfEmbeddedFiles(4)
      .hasEmbeddedFile()
      .withName("complaintform1.xls")
      .hasEmbeddedFile()
      .withName("complaintform2.xls")
      .hasEmbeddedFile()
      .withName("complaintform3.xls");
}

Мы также можем проверить имя встроенного файла:

@Test
public void whenEmbeddedFileContentMatches_thenSuccess() {
    String filename = getFilePath("with_attachments.pdf");
    String embeddedFileName = getFilePath("complaintform1.xls");

    AssertThat.document(filename)
      .hasEmbeddedFile()
      .withContent(embeddedFileName);
}

Мы можем сделать еще один шаг и проверить содержимое встроенных файлов:

Все примеры в этом разделе относительно просты и не требуют пояснений.

9. Заключение

В этом руководстве мы рассмотрели несколько примеров, которые охватывают наиболее распространенные варианты использования, связанные с тестированием PDF.