Page objects

PageObjects, por Martin Fowler

O texto abaixo é a uma tradução autorizada do artigo PageObjects escrito pelo Martin Fowler. Para acessar a versão original em inglês, clique aqui . Caso você tenha sugestões para tornar a tradução melhor, compartilhe através da seção de comentários no final da página. The text bellow is an authorized translation of the article PageObjects written by […]

Background Image

O texto abaixo é a uma tradução autorizada do artigo PageObjects escrito pelo Martin Fowler. Para acessar a versão original em inglês, clique aqui . Caso você tenha sugestões para tornar a tradução melhor, compartilhe através da seção de comentários no final da página.

The text bellow is an authorized translation of the article PageObjects written by Martin Fowler. To access the original english version, click here . If you have any suggestion to make the translation better, share it via comments section at the end of the page.

PageObjects 

Quando você escreve testes para uma página web, você precisa criar referências a elementos na página para clicar nos links e checar sua exibição. Entretanto, se você escrever testes que manipulem os elementos HTML diretamente seus testes vão estar frágeis a mudanças na UI. Um page object abstrai uma página HTML (ou parte) em uma API específica da aplicação, permitindo você manipular os elementos de página sem se aprofundar no HTML.

PageObjects
Page Objects. Fonte: Martin Fowler

A regra básica para um page object é que ele deve permitir um software cliente fazer qualquer coisa e ver qualquer coisa que um humano pode. Ele deve também prover uma interface que seja fácil para programar e esconda as camadas internas da janela. Assim, para acessar uma caixa de texto você deve ter métodos de acesso que recebam ou retornem uma string, check boxes que permitam usar booleans e botões que devem usar métodos que correspondam a sua ação. O page object deve então encapsular os mecânismos necessários para encontrar e manipular os dados no controle da interface gráfica. Uma boa regra é imaginar mudando o elemento de fato – no caso a interface do page object não deve mudar.

Indiferente do termo “page” object, esses objetos não devem geralmente ser construídos para cada página, mas ao invés disso, para elementos relevantes na página. Uma página que exibe vários álbuns, por exemplo, deve ter um page object de uma lista de álbuns, contendo vários page objects de álbuns. Eles deve possivelmente também ter um page object de cabeçalho e um page object de rodapé. Com isso, parte da hierarquia de uma UI complexa existe somente para estruturar a UI – os page objects não tem que revelar tal composição de estruturas. A idéia é modelar a estrutura da página de modo que faça sentido para o usuário da aplicação.

Da mesma forma, se você navegar para outra página, o page object inicial deve retornar outro page object para a nova página. No geral, operações de page objects devem retornar tipos fundamentais (strings, datas) ou outros page objects.

Existem diferenças de opinião se page objects devem incluir assertions em si, ou simplesmente prover dados para que os scripts de teste façam os assertions. Adeptos por incluir os assertions nos page objects dizem que isso ajuda a evitar duplicação de assertions nos scripts de testes, facilitando a produção de melhores mensagens de erro e suportando mais uma API no estilo TellDonAsk*. Adeptos de page objects sem assertions dizem que a inclusão de assertions misturam as responsabilidades de prover acesso aos dados da página com a lógica de assertions, e levam a um page object inchado.

Eu sou a favor de não criarmos assertions nos page objects. Eu acho que você pode evitar a duplicação criando bibliotecas de assertions para os assertions comuns – o qual pode também facilitar a provisão de diagnósticos.

Os testes geralmente são o destino dos Page objects, mas estes não devem fazer assertions eles mesmos. Sua responsabilidade é providenciar acesso ao estado das partes internas da página. É responsabilidade dos clientes levar a lógica dos assertions.

Eu descrevi esse padrão usando como base o HTML, mas o mesmo padrão pode ser aplicado em qualquer tecnologia de UI. Eu tenho visto esse padrão sendo usado efetivamente para ocultar detalhes de UI em Java Swing e não tenho dúvidas que isso é amplamente usado em quase todas frameworks de UI existentes.

Problemas de concorrência são outro tópico que um page object pode encapsular. Esses casos podem ter que ocultar a assincronia em operações assíncronas que os usuários não podem identifica-las como tal. Page objects podem encapsular problemas de threads em frameworks UI onde você tem que se preocupar em um comportamento entre UI e threads em funcionamento.

Page objects são geralmente usados para testar, mas também pode ser usados para providenciar uma interface de scripts sobre uma aplicação. Geralmente é bom ter uma interface script por debaixo da UI – o que é mais rápido e mais seguro. Entretanto, com uma aplicação que tem muitos comportamentos na UI, usar page objects pode ser a melhor ajuda em um trabalho ruim – mas tente mover a lógica se possível, será melhor tanto para os scripts quanto para uma UI saudável por mais tempo.

É comum escrever testes usando alguma Linguagem Específica de Domínio (DSL), tal como Cucumber ou outra DSL interna. Se for o seu caso, é melhor arranjar sua DSL de testes para usar os page objects, permitindo você ter um parser que traduza suas chamadas a DSL em chamadas aos page objects.

Caso você tenha chamadas a um WebDriver em seus testes, você esta fazendo isso errado

Simon Stwart.

Padrões que digam para mover a lógica para fora dos elementos UI (tal como Presentation Mode, Supervising Controller ou Passive View) tornam menos úteis os testes na UI e assim, reduzem a necessidade dos page objects.

Page objects são um exemplo clássico de encapsulamento – eles ocultam detalhes da estrutura do UI e a componentização de outros componentes (e testes). É um bom princípio de design procurar situações como essa enquanto você desenvolve – perguntando a você mesmo “como eu posso ocultar alguns detalhes do resto do software?”. Como em qualquer encapsulamento, isto envolve dois benefícios. Eu tenho ressaltado que você deve colocar a lógica que manipula a UI em um único lugar onde você pode mudar sem afetar outras partes do sistema. Um benefício consequente é que isso permite ao cliente testar um código mais fácil de entender, uma vez que a lógica ali é sobre a intenção do que se ter testar, não relacionando a detalhes de UI.