Posts com a tag ‘locators’

O enésimo elemento em Xpath

6 de outubro de 2010

Cada dia aprendo uma coisa nova e surpreendente.
Estava eu lendo o “A Smattering of Selenium” do blog oficial do Selenium, que por sinal é muito bom para ficar antenado sobre as notícias do Selenium, e encontrei um post que fala justamente de um problema que comentei recentemente no blog, o problema do enésimo elemento.
Até então eu pensava que a única solução nativa era trabalhar com os índices dos elementos pais, mas há outras duas maneiras de resolver o problema.

Problema: dado abaixo um exemplo em html, quero verificar que o texto da quarta célula da tabela é “Produto 4″
Exemplo:

 <table>
   <tr>
    <td>Produto 1</td>
    <td>Produto 2</td>
    <td>Produto 3</td>
   </tr>
   <tr>
    <td>Produto 4</td>
    <td>Produto 5</td>
    <td>Produto 6</td>
   </tr>
 </table>

Solução 1: assertText | //tr[2]/td[1] | Produto 4
Explicação 1: essa é a solução simples onde você tem que trabalhar com o índice do elemento pai, no nosso caso o elemento tr.

Solução 2: assertText | xpath=/descendant::td[4] | Produto 4
Explicação 2: você deve trocar o // pela função descendant do xpath. A anotação // de xpath, corresponde à função descendant-or-self que para quando acha o primeiro elemento. Note que tem que forçar o xpath= já que você não vai usar o //. Você pode ler mais sobre isso aqui.

Solução 3: assertText | xpath=(//td)[4] | Produto 4
Explicação 3: essa solução só funciona com o Selenium, não é nativo do xpath. Você explicita que está usando xpath, coloca sua expressão em parênteses e em seguinda coloca o índice do elemento desejado.

Vivendo e aprendendo!!! To pensando em mudar o nome do blog para O Blog do Seu Enésimo :)
Até a próxima.

JQuery Selectors no Selenium

3 de setembro de 2010

Já expliquei aqui no blog quais são as diversas maneiras de selecionar os elementos da página com o Selenium. Mas em alguns casos, as expressões em Xpath ou CSS do Selenium ficam complicadas de serem montadas.

Vou dar um exemplo bom de quando isso acontece.

Temos a seguinte tabela em html:

<table>
	<tr>
		<td>Produto 1</td>
		<td>Produto 2</td>
		<td>Produto 3</td>
	</tr>
	<tr>
		<td>Produto 4</td>
		<td>Produto 5</td>
		<td>Produto 6</td>
	</tr>
</table>

Agora queremos validar o texto da quarta célula que é “Produto 4″.

Em Xpath, a primeira tentativa seria:

assertText | //td[4] | Produto 4

Porém isso não funciona. Como a quarta célula está na segunda linha da tabela, você tem que entrar primeiro na linha correta e usar índice 1 no td . Exemplo:

assertText | //tr[2]/td[1] | Produto 4

O mesmo ocorre com css locator.
Não funciona:

css=td:nth-child(4)

Funciona:

css=tr:nth-child(2) td:nth-child(1)

Não seria mais fácil se não precisasse usar o índice da linha?
Para isso, você terá que extender o Selenium com Jquery/Sizzle.

Por baixo dos panos o JQuery usa o Sizzle, que é uma implementação em Javascript de seletores CSS. Antigamente essa engine de css ficava dentro do próprio JQuery, mas ela foi separada para que evoluisse de forma independente.

Vou exemplificar passo a passo como configurar o Selenium IDE para usar o Sizzle:

1. Acesse http://sizzlejs.com e faça o download do arquivo zip.
2. Extraia o arquivo sizzle.js para algum diretório de sua preferência.
3. Renomeie o arquivo sizzle.js para user-extensions.js
4. Edite o final do arquivo acrescentando:

function eval_css(locator, inDocument) {
    var results = [];
    window.Sizzle(locator, inDocument, results);
    return results;
}

5. Abra a IDE e acesse Option -> Option e em Selenium Core extensions, coloque o path do arquivo editado.
6. Feche a IDE e abre-a de novo.
7. Pronto, os locators em css serão interpretados pelo Sizzle!!!

Para quem usa o Selenium RC, é só subir o selenium-server com o parâmetro “-userExtensions user-extensions.js”.

Voltando ao nosso exemplo, o comando abaixo funcionaria perfeitamente, usando apenas um índice:

assertText | css=td:eq(3) | Produto 4

Usamos o selector “eq” que faz exatamente o que precisamos. Note que o índice no Sizzle começa em 0 enquanto que no Selenium começa em 1.

Há outras funções que podem ser usadas. Dê uma olhada na documentação do Sizzle.

A boa notícia é que o Selenium irá trocar a api atual (cssQuery) que interpreta CSS locators para usar o Sizzle. Então na próxima versão, você não precisará mais alterar o user-extensions.js para sobrescrever o comportamento dos locators css.

Benefícios em usar CSS locators no Selenium

4 de novembro de 2009

Olá garotada, o velhinho voltou.

Desculpem-me. Estive ausente por um tempinho me dedicando a outros projetos pessoais. Gostaria de agradecer a todos que entraram em contato por email ou pelo blog nesse período de ausência. Não desanimei não, estou de volta :)

Resolvi falar sobre algo que vale a pena dar uma olhada. Vocês tirem as suas conclusões heheh!!!!

Se você não sabe o que é um locator, dê uma olhada no seguinte post: “Encontrando os elementos de uma página com o Selenium”

Os princípais benefícios em usar css locators são:

  1. Expressões sucintas
  2. Teste menos sensível à alteração de template
  3. Performance nos browsers
  4. Os webmasters conhecem bem CSS locators

Vamos tomar como base o seguinte código html que descreve o menu de uma página qualquer:

<div id="menu">
 <ul>
  <li class="first">Item 1</li>
  <li>Item 2</li>
  <li>Item 3</li>
 </ul>
</div>

O locator mais comum e o mais usado é o xpath. Com ele você consegue selecionar praticamente tudo da página. Mas em muitos casos ele pode não ser o ideal. Imagine que temos que fazer um teste de verificar o texto do primeiro elemento do menu. O locator em xpath para esse caso seria:

xpath=//div[@id='menu']//li[@class='first']

O locator em xpath não ficou tão simples. Agora usando css locator ficaria assim:

css=#menu .first

Bem mais simples, mais sucinto, não? Essa é a sintaxe do css. Para mais informações sobre a sintaxe você pode dar uma olhada aqui

Falando agora do segundo benefício, imagine que surgiu a necessidade de zebrar o menu. Para quem não conhece, zebrar significa alternar as cores. No nosso exemplo, as linhas pares passam a ter cores diferentes das linhas ímpares; questões de usabilidade :) Para fazer isso, as linhas ímpares do menu passaram a ter um css novo “odd” e as linhas pares “even”. O html ficou assim:

<div id="menu">
 <ul>
  <li class="first even">Item 1</li>
  <li class="odd">Item 2</li>
  <li class="even">Item 3</li>
 </ul>
</div>

Se você usar o mesmo locator em xpath do exemplo anterior para selecionar o primeiro item do menu, não funcionaria. Isso porque o locator em xpath dá match nos textos, não levando em conta o contexto css. Se você ama xpath, você teria que alterar o locator para passar no seu teste, ficando assim:

xpath=//div[@id='menu']//li[contains(@class,'first')]

Foi necessário usar a funcão “contains” que verifica se a string do atributo class contém o texto “first’.

Por outro lado, o css locator do exemplo anterior não quebraria com esse novo html. Ele funcionaria sem modificação alguma. Muito bom!!!!!!!!!!!!!!

Outro benefício é a performance da execução das expressões em css nos browsers. O css é resolvido muito mais rápido do que as expressões em xpath, já que todos os browsers possuem suporte nativo para css.
Além disso, você já deve ter notado que seus testes demoram muito mais para serem executados no IE do que no Firefox. Isso porque o IE demora muito mais para avaliar as expressões em XPath do que o Firefox. Se você usar css locators, seus testes no IE irão ser executados mais rápido. Boa dica, hein?!

Por último, os webmasters tiram de letra a sintaxe do css locator. Além de eles conhecerem bem de CSS, eles usam bastante essas expressões para selecionar elementos da página via JQuery. Portanto, se você está quebrando a cabeça para definir o locator ideal para o seu comando, vá buscar ajuda com um webmaster.

Bom galera, é isso.

Voltarei a postar em breve também. Não desistam do velhinho do Seu Enium heehhe!!! Até a próxima e deixem seus comentários. Valeu!!!!!

Locators do Selenium – O Retorno

20 de fevereiro de 2009

Continuando sobre o papo de locators do post anterior, há outros 2 tipos de locators que não são tão claros na documentação do Selenium. São eles:

  • attributeLocator
  • tableLocator ou tableCellAddress

Na realidade eles não são um locator por sí só. Eles são uma composição de um locator com um determinado padrão. A idéia é facilitar a seleção de um atributo html de um elemento ou a célula de uma tabela.

O padrão para usar o attributeLocator é concatenar “@nomeDoAtributo” ao fim de um locator. Não entendeu? Vou exemplificar.
Dê uma olhada no seguinte código html:

<div id="menu">
 <ul>
  <li><a href="/">Home</a></li>
  <li><a id="link-contato" title="Acesse a pagina de contato" href="/contato">Contato</a></li>
 </ul>
</div>

Para verificar que o atributo title do link Contato está com o texto correto, utilize o seguinte comando:

verifyAttribute link-contato@title Acesse a pagina de contato

Esse comando utiliza o locator identifier concatenando @title para indicar o atributo a ser selecionado.
Você pode também usar outro locator, como por exemplo o xpath:

verifyAttribute //a[@id='link-contato']@title Acesse a pagina de contato

Ou então o locator de link:

verifyAttribute link=Contato@title Acesse a pagina de contato

O outro locator que fica obscuro na documentação é o tableLocalor. Ele funciona praticamente igual ao anterior, porém deve-se concatenar “.numeroDaLinha.numeroDaColuna” a um locator de sua preferência para encontrar uma tabela. Dê uma olhada no seguinte código html que contém literalmente ou matematicamente uma tabela:

<h1>Tabela do 7</h1>
<table>
 <tr><td>7*1</td><td>7</td></tr>
 <tr><td>7*2</td><td>14</td></tr>
 <tr><td>7*3</td><td>21</td></tr>
 <tr><td>7*4</td><td>28</td></tr>
 <tr><td>7*5</td><td>35</td></tr>
 <tr><td>7*6</td><td>42</td></tr>
 <tr><td>7*7</td><td>49</td></tr>
 <tr><td>7*8</td><td>56</td></tr>
 <tr><td>7*9</td><td>63</td></tr>
 <tr><td>7*10</td><td>70</td></tr>
</table>

Para verificar que o resultado de 7 vezes 6 é 42, use o comando:

verifyTable //table.5.1 42

Essa verificação do exemplo acima, apenas valida o texto. Não garante que realmente o valor da multiplicação está correto. O Selenium não sabe fazer contas matemáticas ehehe, a não ser que você o faça aprender, mas isso é um papo para outro post sobre como extender o Selenium.

Voltando ao tableLocator, o Selenium conta as colunas e linhas a partir de 0 (zero). Logo, se você quer verificar a primeira célula da tabela, ou seja, primeira linha e primeira coluna, concatene “.0.0″ ao locator. Se sua tabela tem um cabeçalho thead, o índice zero começa das linhas e colunas que estão dentro do mesmo.

Há apenas um pequeno problema ao usar esses locators. O botão find da IDE não os localiza na página. Quando se clica no find, você recebe um erro. O problema é que a IDE não consegue distinguir que esses locators são diferentes dos convencionais, e aplica as regras de locator que expliquei no post anterior. Mas enquanto os desenvolvedores da Selenium IDE não corrigem isso, não significa que você não tem que usá-los. Muito pelo contrário. Eles são o tipo de locator que facilita muito quando você tem que verificar o valor de um atributo ou o texto de uma célula, principalmante quando você quer dar match não no texto todo, e sim em parte dele. Em outro post explico como fazer isso.

Bom, é isso galera. Acho que cobri todos os locators do Selenium. Se eu encontrar mais algum é porque ele estava muito escondido na documentação ehehehe ….
Até a próxima.
:)

Encontrando os elementos de uma página com o Selenium

9 de fevereiro de 2009

Como já disse em outro post, um comando do Selenium é composto por uma ação e parâmetros. Na grande maioria dos comandos, o primeiro parâmetro é usado para especificar um locator. O locator é uma forma de selecionar um elemento html da página, por exemplo um botão, uma div, um link ou qualquer outra tag html.

O Selenium disponibiliza diversas formas de selecionar um elemento e para isso, um locator deve ser escrito da seguinte maneira:

tipo=expressao

Usando a própria nomenclatura da documentação, o tipo de um locator pode ser:

  • id
  • name
  • identifier
  • link
  • dom
  • xpath
  • css

Para exemplificar cada locator, vamos tomar como base o seguinte código html:

<html>
<head>
 <title>Locators no Selenium</title>
</head>
<body>
 <div id="menu">
  <ul>
   <li><a href="/">Home</a></li>
   <li><a href="/contato" title="Acesse a pagina de contato">Contato</a></li>
  </ul>
 </div>
 <div id="search">
  <form action="/">
   <input type="text" name="s"/>
  </form>
 </div>
</body>
</html>

O locator id é utilizado apenas para encontrar elementos com o id especificado. No nosso exemplo, para você verificar que a div com id menu existe, você tem que usar o seguinte comando:

verifyElementPresent id=menu

O locator name é parecido com o anterior, porém como o próprio nome diz, é utilizado para selecionar elementos que tenham o atributo name especificado. Por exemplo, digite selenium no elemento com name s:

type name=s selenium

O locator identifier é uma junção entre os dois locators anteriores. O Selenium primeiramente tenta encontrar um elemento pelo id. Se não encontrar ele tenta localizar um elemento pelo atributo name.

verifyElementPresent identifier=menu
verifyElementPresent identifier=s

O locator link é utilizado para selecionar links na página pelo texto de exibição. Geralmente ele é utilizado com o comando click.

click link=Home

Com o locator dom, você seleciona os elementos com expressões Javascript. Você pode tanto acessar o elementos pelo objeto document, como também pode escrever uma função que retorne um elemento.

verifyElementPresent dom=document.forms[0]
verifyElementPresent dom=function getMenu(){ return document.getElementById(‘menu’); } getMenu();

Com o locator xpath, é possível selecionar os elementos via Xpath. Essa forma é muito poderosa pois o Xpath foi criado exatamente para buscar elementos em um documento XML e por isso há diversas funções que facilitam isso. Em outro post vou detalhar mais sobre o que é possível fazer com Xpath. No exemplo abaixo, utilizei a função contains para pegar o link que contenha no title a string “Acesse”:

verifyElementPresent xpath=//a[contains(@title,'Acesse')]

O locator css deve ser usado por quem tem familiaridade com CSS Selectors. Esse tipo de expressão é bem parecida com o Xpath e é tão poderosa quanto. A diferença é que é uma sintaxe mais voltada para um documento HTML.

verifyElementPresent css=#menu

Agora que você aprendeu quais são os tipos de locator que o Selenium interpreta, vou contar uma dica. Os locators dom, xpath e identifier não precisam ser explicitados, ou seja, você pode inserir a sua expressão sem escrever “tipo=” e se ela começar com “document.” será interpretada pelo locator dom. Se começar com “//” será interpretada pelo xpath. E se não começar com nenhum dos dois, será interpretada pelo identifier.

Exemplos:

verifyElementPresent document.getElementById(‘menu’)
verifyElementPresent //div[@id="menu"]
verifyElementPresent menu

Como os locators identifier e xpath são os mais usados, na grande maioria dos testes você não vai precisar explicitar o locator.

Para quem quiser brincar e ver funcionando todos esses locators, eu criei um teste selenese que verifica os elementos da página usando todos os tipos de locators. Baixe-o aqui. O teste vai abrir uma página com o mesmo código html de exemplo no começo do post.

Para facilitar nossa vida, a IDE possui um botão chamado find que ao ser clicado destaca em verde o locator na página. Isso ajuda muito quando se está criando um novo teste, ou até mesmo corrigindo um antigo e você quer identificar se está selecionando o elemento certo.

Bom, é isso aí galera. Qualquer dúvida só perguntar que o seu Enium responde :)