page objects_ PAGE OBJECTS Organizando seus Testes Funcionais AUMENTANDO A MANUTENIBILIDADE DE TESTES FUNCIONAIS ATRAVÉS DA ORIENTAÇÃO A OBJETOS. Testes são parte fundamental do processo de desenvolvimento de software. Testes são criados com o objetivo de garantir que os requisitos funcionais de um sistema são atendidos. Contudo, testar a interface de uma aplicação (especialmente Web) não é algo trivial. Ferramentas, como o Selenium, foram criadas com o objetivo de automatizar o processo de reprodução das ações de navegação em uma aplicação. O problema é que estas ferramentas automatizadas nem sempre geram um código simples de se manter. Como solução para este problema, apresentamos o design pattern Page Object que tem como objetivo aplicar as técnicas da programação orientada a objetos aos testes funcionais. O - - - - - - Testes de Interface com o Usuário (UI) - - - - - - / 46
Eder Ignatowicz @ederign Doutorando em Engenharia Elétrica na Unicamp, é mestre em Engenharia Elétrica pela Unicamp (2009) e formado em Ciência da Computação pela Universidade Estadual de Londrina (2007). Atualmente é engenheiro de Software na Dextra Sistemas e leciona diversos cursos de graduação e pós-graduação na Faccamp e Unisal e editor do InfoQ Brasil. Leandro Guimarães @leguimas Biólogo formado pela Unicamp (2007) e técnico em Processamento de Dados formado pelo Colégio Técnico da Unicamp (1999). Atua com desenvolvimento de software há 11 anos sendo 8 deles com Java. Atualmente, é engenheiro de Software na Dextra Sistemas. - Utilizando Page Objects - - -» Encapsulamento de detalhes da implementação: - -» Métodos representam serviços:» Figura 1. Representação do pattern Page Object: as páginas de busca do Google são representadas por objetos PageObject que fornecem métodos públicos, encapsulando os detalhes para manipulação da página e disponibilizando o acesso aos diversos testes que a utilizam. 47 \
» Métodos retornam outros Page Objects: - - - - - - - Implementando o padrão - sua - - - public class TestaMecanismoBusca private static WebDriver driver; @BeforeClass public static void preparatestes() // browsers. Nesse caso driver = new FirefoxDriver(); @Test public void testabuscaseleniumtest() PaginaDeBusca.acessa(driver); PaginaDeResultadoDaBusca paginaderesultadodabusca = paginadebusca.realizabusca( selenium test ); Assert.assertTrue(paginaDeResultadoDaBusca.encontrouSite( seleniumhq.org )); @Test public void testabuscapageobjectpattern() PaginaDeBusca.acessa(driver); PaginaDeResultadoDaBusca paginaderesultadodabusca = paginadebusca.realizabusca ( pageobject pattern ); Assert.assertT rue(paginaderesultadodabusca.encontrousite( code.google.com/p/sele nium/wiki/pageobjects )); @AfterClass public static void () driver.close(); Listagem 1. Classe que implementa o teste a ser executado. - Listagem 2. Implementação dos PageObjects referentes à da Página de Busca e Resultado. public class PaginaDeBusca private static String URL = http://www.google. com.br ; private static long WAIT_TIME = 2000l; private WebDriver driver; private PaginaDeBusca(WebDriver driver) this.driver = driver; public static PaginaDeBusca acessa( WebDriver driver) // navega para a URL desta pagina driver.navigate().to(url); // retorna uma nova instancia do objeto que // representa a pagina da busca / 48
/eu uso Desenvolvedor de Software, com 7 anos de experiência em projetos de desenvolvimento de sistemas corporativos na plataforma Java Enterprise Edition e Ruby on Rails. Formado em Ciência da Computação na Universidade de São Paulo/São Carlos, atuando ainda como consultor de arquitetura de sistemas e instrutor de treinamentos. - - return new PaginaDeBusca(driver); public PaginaDeResultadoDaBusca realizabusca(string conteudodabusca) // escreve o valor de conteudodabusca em um driver. (By.name( q )).sendkeys( conteudodabusca); // pelo nome btng driver. (By.name( btng )).click(); try // aguarda um tempo ate a pagina do // resultado de busca ser carregada Thread.sleep(WAIT_TIME); catch (InterruptedException e) throw new RuntimeException( Can not wait for page to load., e); // retorna um novo objeto que representa a // pagina do resultado da busca return new PaginaDeResultadoDaBusca(driver); //--------------- public class PaginaDeResultadoDaBusca private WebDriver driver; public PaginaDeResultadoDaBusca( WebDriver driver) this.driver = driver; public boolean encontrousite(string urlsiteprocurado) // procura por todos os elementos li de classe // css g que estiverem dentro de um div de id res List<WebElement> itensencontrados = driver. (By.cssSelector( div#res li.g )); boolean elementoencontrado = false; for (WebElement itemencontrado : itensencontrados) // obtem o conteudo de um elemento cite // dentro de cada item encontrado String linkdoelementoencontrado = itemencontrado. (By.tagName( cite )).gettext(); elementoencontrado = linkdoelementoencontrado.contains (urlsiteprocurado); if (elementoencontrado) break; return elementoencontrado; - - 49 \
/eu uso da Computação pela Unicamp e bacharel em Ciência da Computação pela UFMG. Na Receita Federal (V&V). Participa ativamente do curso de especialização em Engenharia de Software da Unicamp desde temas relacionados a testes e qualidade de software em instituições e eventos, e possui uma série de publicações nacionais e internacionais relacionadas. - - - - - - - Listagem 3. Refactoring dos Page Objects e da classe de testes. public abstract class PaginaBase private static long WAIT_TIME = 2000l; protected WebDriver driver; public PaginaBase(WebDriver driver) this.driver = driver; protected void preencheinputtext(string cssselector, String conteudo) WebElement inputtext = driver. ( By.cssSelector(cssSelector)); inputtext.clear(); inputtext.sendkeys(conteudo); protected void clica(string cssselector) driver. (By.cssSelector(cssSelector)). click(); try // aguarda um tempo ate a pagina do resultado // de busca ser carregada Thread.sleep(WAIT_TIME); catch (InterruptedException e) throw new RuntimeException( Nao foi possivel esperar a pagina ser carregada., e); protected List<WebElement> buscaporelementos( String cssselector) return driver. (By.cssSelector( cssselector)); / 50
public abstract String geturl(); //--------------- public class PaginaDeBusca extends PaginaBase private static String INPUT_BUSCA = input[name=q] ; private static String BOTAO_DE_BUSCA = input[name=btng] ; public PaginaDeBusca(WebDriver driver) super(driver); public static PaginaDeBusca acessa(webdriver driver) protected void acessapagina() driver.navigate().to(this.geturl()); new PaginaDeBusca(driver); paginadebusca.acessapagina(); return paginadebusca; quandousuarioprocurapor( selenium test ); /para saber mais private void entaomecanismodebuscaencontrasite( String siteesperado) Assert.assertTrue(paginaDeResultadoDaBusca. encontrousite(siteesperado)); @AfterClass public static void () driver.close(); entaomecanismodebuscaencontrasite( seleniumhq.org ); @Test public void testabuscapageobjectpattern() dadoqueusuarioacessamecanismodebusca(); quandousuarioprocurapor( pageobject pattern ); entaomecanismodebuscaencontrasite( code.google.com/p/selenium/wiki/ PageObjects); private void dadoqueusuarioacessamecanismodebusca() paginadebusca = PaginaDeBusca.acessa(driver); private void quandousuarioprocurapor(string conteudo) paginaderesultadodabusca = paginadebusca.realizabusca(conteudo); - - - - - - /referências 51 \
Listagem 6. public class PaginaDeBusca extends PaginaBase private static String INPUT_BUSCA = input#sb_form_q ; private static String BOTAO_DE_BUSCA = input#sb_form_go ; public PaginaDeBusca(WebDriver driver) super(driver); public static PaginaDeBusca acessa(webdriver driver) new PaginaDeBusca(driver); paginadebusca.acessapagina(); return paginadebusca; public PaginaDeResultadoDaBusca realizabusca(string conteudodabusca) this.preencheinputtext(input_busca, conteudodabusca); this.clica(botao_de_busca); return new PaginaDeResultadoDaBusca(driver); @Override public String geturl() return http://www.bing.com.br ; //--------------- public class PaginaDeResultadoDaBusca extends PaginaBase private static String LISTA_DE_RESULTADO = div#results li cite ; public PaginaDeResultadoDaBusca(WebDriver driver) super(driver); public boolean encontrousite(string urlsiteprocurado) List<WebElement> itensencontrados = this.buscaporelementos(lista_de_ RESULTADO); boolean elementoencontrado = false; for (WebElement itemencontrado : itensencontrados) // obtem o conteudo de um elemento cite // dentro de cada itemencontrado String linkdoelementoencontrado = itemencontrado.gettext().replaceall(, ); elementoencontrado = linkdoelementoencontrado.contains( urlsiteprocurado); - - - - - - - - - - - - - - - - - - / 52