Guia para PDFUnit
1. Introdução
Neste artigo, vamos explorar a bibliotecaPDFUnit para testar PDFs.
Usando as poderosas APIs fornecidas pelo PDFUnit, podemos trabalhar com PDFs e verificar texto, imagens, favoritos e várias outras coisas.
Podemos, eventualmente, escrever casos de teste bastante complexos usando PDFUnit, mas vamos começar com os casos de uso mais comuns que se aplicam à maioria dos PDFs de produção e fornecem uma excelente base para desenvolvimento posterior.
Nota importante: O PDFUnit está disponível gratuitamente para fins de avaliação, mas não para uso comercial.
2. Instalação e Configuração
A versão atual do PDFUnit (2016.05) não está disponível no repositório do Maven Central. Portanto, precisamos baixar e instalar os frascos manualmente. Siga oinstructions on the official site para instalação manual.
3. Número de páginas
Vamos começar com um exemplo simples que simplesmente valida o número de páginas em um determinado arquivo PDF:
@Test
public void givenSinglePage_whenCheckForOnePage_thenSuccess() {
String filename = getFilePath("sample.pdf");
AssertThat.document(filename)
.hasNumberOfPages(1);
}
OgetFilePath() é um método simples, não relacionado ao PDFUnit, que simplesmente retorna o caminho do arquivo PDF comoString.
Todos os testes PDFUnit começam com uma chamada paraAssertThat.document(), que prepara o documento para teste. OhasNumberOfPages() levaint como o argumento que especifica o número de páginas que o PDF deve conter. Em nosso caso, o arquivosample.pdf contém apenas uma página, então o teste é bem-sucedido.
Se o número real de páginas não corresponder ao argumento, uma exceção será lançada.
Vejamos um exemplo de como testar um cenário quando uma exceção é lançada:
@Test(expected = PDFUnitValidationException.class)
public void givenMultiplePages_whenCheckForOnePage_thenException() {
String filename = getFilePath("multiple_pages.pdf");
AssertThat.document(filename)
.hasNumberOfPages(1);
}
Nesse caso, o arquivomultiple_pages.pdf contém várias páginas. Portanto, uma exceçãoPDFUnitValidationException é lançada.
4. Arquivos protegidos por senha
Manipular arquivos protegidos por senha é novamente realmente simples. A única diferença está na chamada paraAssertThat.document() onde precisamospass a second argument which is the password of the file:
@Test
public void givenPwdProtected_whenOpenWithPwd_thenSuccess() {
String filename = getFilePath("password_protected.pdf");
String userPassword = "pass1";
AssertThat.document(filename, userPassword)
.hasNumberOfPages(1);
}
5. Comparação de Texto
Vamos agora comparar um PDF de teste (sample.pdf) com um PDF de referência (sample_reference.pdf). Se o texto do arquivo em teste for o mesmo que o arquivo de referência, o teste será bem-sucedido:
@Test
public void whenMatchWithReferenceFile_thenSuccess() {
String testFileName = getFilePath("sample.pdf");
String referenceFileName = getFilePath("sample_reference.pdf");
AssertThat.document(testFileName)
.and(referenceFileName)
.haveSameText();
}
OhaveSameText() é o método que faz todo o trabalho de comparação do texto entre os dois arquivos.
Se não quisermos comparar o texto completo entre dois arquivos e, em vez disso, quisermos validar a existência de um determinado texto em uma determinada página, o métodocontaining() é útil:
@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);
}
O teste acima é bem-sucedido se a página # 2 do arquivomultiple_pages.pdf contiverexpectedText em qualquer lugar da página. A ausência ou presença de qualquer outro texto além deexpectedText não afeta os resultados.
Vamos agora tornar o teste mais restritivo, validando se um determinado texto está presente em uma determinada região de uma página, em vez de na página inteira. Para isso, precisamos entender o conceito dePageRegion.
APageRegion é uma subseção retangular dentro da página real em teste. OPageRegion deve cair completamente na página real. Se qualquer parte dePageRegion ficar fora da página real, isso resultará em um erro.
UmPageRegion é definido por quatro elementos:
-
leftX - o número de milímetros que uma linha vertical está longe da borda vertical mais à esquerda da página
-
upperY - o número de milímetros que uma linha horizontal está longe da borda horizontal superior da página
-
width - a largura da região em milímetros
-
height - a altura dos milímetros da região
Para entender melhor esse conceito, vamos criar umPageRegion usando os seguintes atributos:
-
leftX = 20
-
upperY = 10
-
width = 150
-
height = 50
Aqui está uma representação de imagem aproximada dosPageRegion: acima
Depois que o conceito é claro, o caso de teste correspondente é relativamente mais simples:
@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");
}
Aqui, criamos umPageRegion na página # 1 do arquivo PDF e verificamos o texto nesta região.
6. Favoritos
Vejamos alguns casos de teste relacionados a marcadores:
@Test
public void whenHasBookmarks_thenSuccess() {
String filename = getFilePath("with_bookmarks.pdf");
AssertThat.document(filename)
.hasNumberOfBookmarks(5);
}
Este teste será bem-sucedido se o arquivo PDF tiver exatamente cinco marcadores.
O rótulo dos favoritos também pode ser verificado:
@Test
public void whenHasBookmarksWithLabel_thenSuccess() {
String filename = getFilePath("with_bookmarks.pdf");
AssertThat.document(filename)
.hasBookmark()
.withLabel("Chapter 2")
.hasBookmark()
.withLinkToPage(3);
}
Aqui, estamos verificando se o PDF fornecido possui um marcador com o texto "Capítulo 2". Ele também verifica se há um marcador vinculado à Página # 3.
7. Imagens
As imagens são outro aspecto importante dos documentos PDF. Teste de unidade das imagens dentro do PDF novamente muito fácil:
@Test
public void whenHas2DifferentImages_thenSuccess() {
String filename = getFilePath("with_images.pdf");
AssertThat.document(filename)
.hasNumberOfDifferentImages(2);
}
Este teste verifica se há exatamente duas imagens diferentes utilizadas no PDF. O número de imagens diferentes refere-se a um número real de imagens armazenadas em um documento PDF.
No entanto, é possível que exista uma única imagem de logotipo armazenada dentro do documento, mas seja exibida em todas as páginas do documento. Refere-se ao número de imagens visíveis, que pode ser maior que o número de imagens diferentes.
Vamos ver como verificar as imagens visíveis:
@Test
public void whenHas2VisibleImages_thenSuccess() {
String filename = getFilePath("with_images.pdf");
AssertThat.document(filename)
.hasNumberOfVisibleImages(2);
}
PDFUnit is powerful enough to compare the content of images byte-by-byte. Isso também significa que a imagem no PDF e a imagem de referência devem ser exatamente iguais.
Devido à comparação de bytes, diferentes formatos de imagens como BMP e PNG são considerados desiguais:
@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);
}
Observe o uso deAnyPage aqui. Não estamos restringindo a ocorrência da imagem a nenhuma página específica, mas a qualquer página do documento inteiro.
A imagem a ser comparada pode assumir a forma deBufferedImage,File,InputStream ouURL além deString que representa o nome do arquivo.
8. Arquivos incorporados
Certos documentos em PDF vêm com arquivos ou anexos incorporados. É necessário testar também:
@Test
public void whenHasEmbeddedFile_thenSuccess() {
String filename = getFilePath("with_attachments.pdf");
AssertThat.document(filename)
.hasEmbeddedFile();
}
Isso verificará se o documento em teste possui pelo menos um arquivo incorporado.
Também podemos verificar o nome do arquivo incorporado:
@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");
}
Podemos dar um passo adiante e verificar o conteúdo dos arquivos incorporados também:
@Test
public void whenEmbeddedFileContentMatches_thenSuccess() {
String filename = getFilePath("with_attachments.pdf");
String embeddedFileName = getFilePath("complaintform1.xls");
AssertThat.document(filename)
.hasEmbeddedFile()
.withContent(embeddedFileName);
}
Todos os exemplos nesta seção são relativamente diretos e auto-explicativos.
9. Conclusão
Neste tutorial, vimos vários exemplos que cobrem os casos de uso mais comuns relacionados ao teste de PDF.
No entanto, há muito mais que o PDFUnit pode fazer; visitedocumentation page para saber mais.