Posts da categoria ‘testes’

Novos comandos do Selenium para gerar CPF e CNPJ

20 de maio de 2009

Um dos leitores do blog, Maurício Avellar, teve uma iniciativa muito boa.
Ele resolveu compartilhar com todos alguns comandos criados por ele que provavelmente serão úteis para outras pessoas.

Os comandos criados pelo Maurício dão a possibilidade de você inserir um CPF ou um CNPJ válidos em qualquer input na tela.

A sintaxe dos comandos é a seguinte:

| generateCNPJ | locator |
| generateCPF | locator |

O único parâmetro é o locator que deve corresponder ao input que você quer inserir o novo valor.

O arquivo de extensões do Selenium que contém os novos comandos, você pode fazer o download aqui.

Para você usá-los na IDE, siga os seguintes passos:

  1. Abra a Selenium IDE e clique em Options >> Options.
  2. Altere a opção “Selenium Core extensions (user-extensions.js)” para apontar para o arquivo js que você acabou de baixar.
  3. Aperte o botão OK.
  4. Feche a IDE e abre-a novamente para que os comandos novos sejam carregados.

Pronto, você já pode usar os comandos nos seus testes.

Muito obrigado Maurício pela sua colaboração.

Quem quiser compartilhar qualquer outro comando ou experiências só entrar em contato.

:)

Script Greasemonkey para remover Remote Control do Selenium Grid

13 de maio de 2009

O Selenium Grid tem uma tela que você pode visualizar quais servidores remote control estão disponíveis e quais estão em execução.

A tela é essa:

Console do Grid

Para quem usa o Grid, sabe que ele tem alguns problemas. Um deles é que se um RC cai de forma indevida, como por exemplo kill -9, crash na JVM, chutaram a tomada ou qualquer outro motivo, esse RC continua na lista de servidores disponíveis ou em execução.
Existe uma chamada http que remove um servidor dessa listagem, mas não sei o porquê disso não estar disponível na tela.

Fiz um script greasemonkey que adiciona um link com a opção de remover o servidor desejado via ajax.
Quem quiser esse script, é só baixar aqui.

A tela com o script ativo fica assim:

Console do Grind com script greasemonkey

É isso aí. :)

Por que o nome Selenium?

25 de abril de 2009

Estava eu em casa vendo TV, pensando na vida e surgiu a dúvida do porquê o tal do Selenium se chamar selenium.

Googuei.

Selenium é o nome em inglês do elemento químico selênio.
Bom, até aí acho que todo mundo já sabia disso.
O que muitos não sabem é que o selênio é utilizado como antídoto contra os efeitos tóxicos do mercúrio.
E o kiko?

Mercúrio em inglês é mercury.

Mercury é uma empresa que faz software para QA. É a grande líder do mercado, tanto que a HP pagou $4.5 bilhões ao adiquirí-la. Que grana, né? Lógico, os softwares produzidos são pagos, e bem caro$.

Como o Selenium é opensource, ele é o antídoto para quem quer se livrar das garras da Mercury.

Hehe… mas ele não é o único antídoto, nos próximos posts vou tentar falar sobre outras alternativas opensource.

Té mais!!! :)

Teste em paralelo com a nova versão do Junit 4.6

14 de abril de 2009

No post anterior mostrei que é possível paralelizar os testes com TestNG.

Para os que estão mais familiarizados com Junit, o TestNG pode parecer mais difícil, mas não se preocupe.

Hoje foi liberada a versão 4.6 do Junit e com ela você consegue paralelizar os seus testes.

Segue o exemplo no release notes de como rodar em paralelo:

public static class Example {
	@Test public void one() throws InterruptedException {
		Thread.sleep(1000);
	}
	@Test public void two() throws InterruptedException {
		Thread.sleep(1000);
	}
}
 
@Test public void testsRunInParallel() {
	long start= System.currentTimeMillis();
	Result result= JUnitCore.runClasses(ParallelComputer.methods(),
			Example.class);
	assertTrue(result.wasSuccessful());
	long end= System.currentTimeMillis();
	assertThat(end - start, betweenInclusive(1000, 1500));
}

Assim como o TestNG você pode escolher entre paralelizar os métodos ou a classe toda: ParallelComputer.methods() ou ParallelComputer.classes()

Para quem usa maven, a integração nativa da versão 4.6 do Junit com o Surefire Plugin funciona somente para testes sequenciais. Se você quiser paralelizar vai ter que seguir o exemplo acima do release notes.
Mas acredito que logo mais sairá uma versão do maven-surefire-plugin em que você apenas terá que colocar na configuração se você quer paralelizar, assim como ocorre com o TestNG, com o config no pom.xml:

<parallel>tests|methods</parallel>

Qualquer outra novidade volto a postar… :)

Inserido em 02/12/2009
*A versão do junit 4.6 estava bugada. Use uma mais recente, 4.7 ou 4.8.

Testes em paralelo com Selenium Grid, Maven e TestNG

5 de abril de 2009

O Selenium se provou ser uma ótima ferramenta para auxiliar os testes em sistemas web. O desenvolvedor ganha mais confiança ao realizar alterações no sistema, os webmasters também e se preocupam cada vez mais em deixar as telas mais fáceis para automatizar e dar manutenção.
Mas à medida que o número de testes aumenta, o tempo total de execução também aumenta, e muito. A maneira de conseguir diminuir esse tempo é usando o Selenium Grid.

O Selenium Grid atua como um proxy entre as requisições dos clientes e um pool de servidores Remote Control. Com isso, o grid consegue gerenciar ao mesmo tempo todos os RCs que estão conectados. O benefício disso tudo é que você pode paralelizar a execução dos seus testes e consequentemente o tempo de execução dos seus testes diminui.

E como você consegue fazer isso?

Primeiro você tem que baixar o Selenium Grid em http://selenium-grid.seleniumhq.org/download.html. A última versão é a 1.0.3.
Descompacte o arquivo baixado em algum lugar de sua preferência.

Você também vai ter que ter o ant instalado em sua máquina. Baixe-o aqui.

Entre no diretório do Selenium Grid e rode o comando para subir o servidor principal, o hub.

ant launch-hub

O hub vai subir na porta 4444 e é onde o seu teste tem que se conectar.

Agora suba dois servidores do Selenium RC com o browser Firefox:

ant -Dport=5556 -Denvironment=*chrome launch-remote-control
ant -Dport=5557 -Denvironment=*chrome launch-remote-control

Acesse agora http://localhost:4444/console e você verá uma tela contendo os servidores disponíveis.

Pronto, você já tem a estrutura de servidores para que seus testes rodem paralelamente.

Agora vamos criar um projeto Maven para que tudo fique organizado e seja fácil disparar os testes (ao fim do post tem um link para fazer download do projeto com o exemplo). Para baixar o Maven acesse aqui.

Rode o seguinte comando para criar um novo projeto de nome “testes-em-paralelo”:

mvn archetype:create -DgroupId=br.com.seuenium -DartifactId=testes-em-paralelo

Esse comando cria uma estrutura básica de diretórios para um projeto Java. Um desses diretórios criados é o src/test/java onde o Maven por convenção vai chamar todos os seus testes que estiverem localizados nessa pasta. Essa convenção é definida pelo plugin maven-surefire-plugin.
Esse plugin consegue rodar tanto testes em Junit como em TestNG.
Para quem não conhece, o TestNG é um framework de testes praticamente igual ao Junit, porém com algumas funcionalidades a mais. Uma dessas funcionalidades é a possibilidade de rodar os seus testes em paralelo.

Para habilitar o TestNG, apenas inclua a dependência da lib do TestNG no seu pom.xml. Vai ficar assim:

<dependency>
	<groupId>org.testng</groupId>
	<artifactId>testng</artifactId>
	<version>5.8</version>
	<scope>test</scope>
	<classifier>jdk15</classifier>
</dependency>

Você também tem que adicionar a dependência da api cliente do Selenium:

<dependency>
	<groupId>org.seleniumhq.selenium.client-drivers</groupId>
	<artifactId>selenium-java-client-driver</artifactId>
	<version>1.0-beta-2</version>
</dependency>

Outra configuração que você precisa fazer, é dizer ao TestNG que seus testes devem rodar em paralelo. Para isso você tem que configurar o maven-surefire-plugin.
Vai ficar assim:

<plugin>
	<groupId>org.apache.maven.plugins</groupId>
	<artifactId>maven-surefire-plugin</artifactId>
	<configuration>
		<parallel>tests</parallel>
		<threadCount>2</threadCount>
	</configuration>
</plugin>

Você tem dois possíveis valores para a configuração “parallel”: tests ou methods.

A threadCount equivale a quantos testes vão rodar ao mesmo tempo. No nosso caso vamos usar 2 pois só subimos duas instâncias de servidores Remote Control.

Após você já ter essa estrutura do Maven criada, vamos criar os testes em Java.

Para facilitar o exemplo, criei uma tela para podermos testar tudo isso. Essa tela é uma página de busca, com um input text para você digitar um termo e o botão buscar. Ao clicar no botão o resultado da busca aparece em uma tabela. Se não há resultado aparece uma mensagem informando que não encontrou.

Vamos criar então dois testes para essa tela:

  • Busca com resultado
  • Busca sem resultado

Abra então a Ide do Selenium no Firefox e grave o primeiro teste. Para isso digite o termo “Selenium” e mande buscar. Faça também um verificação de sucesso. Em seguida exporte-o para Java e salve no diretório testes-em-paralelo/src/test/java/br/com/seuenium/ com o nome TesteBuscaComResultado.java.

Faça o mesmo para o segundo teste, porém usando o termo “Seuenium” e salvando o arquivo como TesteBuscaSemResultado.java.

Temos agora duas classes Java que são dois TestCases. Quando se exporta para Java, a IDE cria uma classe de teste que extende um TestCase padrão do Selenium, a SeleneseTestCase. No nosso caso, vamos alterar isso. Vamos criar o nosso TestCase padrão, uma classe abstrata, onde as outras classes de teste irão extender esse cara.
O TestCase abstrato fica mais ou menos assim:

package br.com.seuenium;
 
import org.testng.annotations.AfterTest;
import org.testng.annotations.BeforeTest;
import com.thoughtworks.selenium.DefaultSelenium;
 
public abstract class AbstractTestCase {
 
	protected DefaultSelenium selenium;
 
	@BeforeTest(alwaysRun=true)
	public void startSelenium() {
		selenium = new DefaultSelenium("localhost", 4444, 
				"*chrome", "http://seuenium.com.br");
		selenium.start();
	}
 
	@AfterTest(alwaysRun=true)
	public void stopSelenium() {
		selenium.stop();
	}
}

Temos o método startSelenium() que inicializa uma sessão com o Selenium, que no nosso caso é o hub do grid. Temos também o comando stopSelenium() que fecha a sessão com o servidor do Selenium.
Colocando as anotações do TestNG @BeforeTest e @AfterTest, sempre que um teste for executado, ele primeiro vai executar o startSelenium(), em seguida vai rodar o teste e ao fim vai chamar o stopSelenium(). O parâmetro alwaysRun=true garante que mesmo que uma exceção ocorra, esses métodos serão executados.

Agora vamos para os nossos TestCases exportados pela IDE. Primeiro alteramos ele para extender a classe abstrata que acabamos de criar. Em seguida, vamos colocar a anotação @Test na própria classe, dando um valor para o parâmetro chamado “testName”. Você também precisa colocar a anotação @Test no método que contém as chamadas na api do Selenium.
O classe TesteBuscaComResultado então vai ficar assim:

package br.com.seuenium;
 
import static org.testng.Assert.*;
 
import org.testng.annotations.Test;
 
@Test(testName="Teste com resultado")
public class TesteBuscaComResultado extends AbstractTestCase {
 
	@Test
	public void testNew() throws Exception {
		selenium.open("/testes/4/buscar.php");
		selenium.type("q", "Selenium");
		selenium.click("//input[@value='Buscar']");
		selenium.waitForPageToLoad("30000");
		assertTrue(selenium.isTextPresent("2 resultados encontrados com a palavra Selenium"));
	}
}

Faça o mesmo com a outra classe TesteBuscaSemResultado .

Mas por que eu tenho que colocar a anotação @Test na classe e ainda por cima configurar o parâmetro testName?
Bom, isso eu demorei pra entender. Eu estava mais familiarizado com o Junit, onde um teste corresponde a um método anotado com @Test. Para o TestNG um teste corresponde a uma ou mais classes e o que define esse teste é o seu nome. Você até pode ter mais de um teste por classe, mas eles nunca rodarão em paralelo entre si, ou seja, todos os métodos com @Test da mesma classe rodarão sequencialmente.

Agora vamos rodar os testes em paralelo.
Na linha de comando, dentro do projeto testes-em-parelelo, digite:

mvn clean install

Com esse comando, o maven vai compilar as suas classes e vai chamar todos os seus testes.
O resultado esperado disso tem que ser um “BUILD SUCCESSFUL”.
Mas fique atento a parte com os prints dos seus testes. Você vai ver algo parecido com:

-------------------------------------------------------
 T E S T S
-------------------------------------------------------
Running TestSuite
Tests run: 2, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 10.557 sec
 
Results :
 
Tests run: 2, Failures: 0, Errors: 0, Skipped: 0

Note que 2 testes foram executados e demoraram 10.557 segundos.

Só para ter garantia de que você teve um ganho no tempo de execução dos seus testes, altere no pom.xml o threadCount para 1, para que seu teste rode sequencialmente. Você vai ter um resultado parecido como esse:

Tests run: 2, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 19.402 sec

Praticamente o dobro do tempo demorou.

Bom, vimos que é possível paralelizar os testes e ganhar tempo na execução. Há também um outro carinha que paraleliza testes em Java, é o Parallel Junit, mas eu não encontrei uma integração desse cara com o maven.
Mas e se meus testes não estão escritos em Java? Há frameworks que fazem isso para outras linguagens. Em Ruby por exemplo você tem o DeepTest. Para mais informações dê uma olhada no faq do Selenium Grid, clique aqui.

O projeto Maven completo com todas as classes e tudo configurado, pronto pra rodar, você pode baixar AQUI.

Bom, é isso. Qualquer dúvida só perguntar. :)

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 :)

Como rodar os testes do Selenium no IE ou em outro browser?

20 de janeiro de 2009

Até agora falei mais sobre os comandos do Selenium, e os exemplos que dei eram pra ser testados pela IDE. Como a IDE ainda só existe para o Firefox, os testes até então eram pra ser executados somente no Firefox. Mas e se você quiser testar no Internet Explorer 6? ou no 7? Ou no Safari? Ou até mesmo no browser mais recente do Google?

Aí que entra o servidor do Selenium. Você sobe um e escolhe em qual browser quer testar.

No site e na documentação do Selenium, o servidor é chamado de Selenium Remote Control, ou para os mais íntimos somente RC. Para baixar o servidor acesse http://seleniumhq.org/download. A última versão disponível é a 1.0 beta 2. Dentro do arquivo zipado, você vai encontrar uma pasta com o nome selenium-server que corresponde ao próprio servidor do selenium. As outras pastas com o nome client-driver correspondem às bibliotecas de cada linguagem disponível para comunicar com o servidor, que são:

  • Java
  • Ruby
  • Python
  • Php
  • Perl
  • .Net

Não vou me aprofundar muito sobre essas bibliotecas, mas gerar um teste em uma determinada linguagem é algo relativamente simples. A IDE tem uma opção de exportar os testes. Basta abrir um teste, clicar em file, export test case as, e escolher a linguagem desejada.

Mas não se assuste, você pode rodar o seu teste em outro browser sem a necessidade de exportá-lo para uma linguagem.

O pré-requisito para isso é ter o Java instalado na sua máquina.

O primeiro passo então é salvar o seu teste da IDE em uma determinada pasta. Só por curiosidade, na documentação do Selenium, um teste salvo pela IDE está no formato selenese. Após isso, entre no console (shell, cygwin, DOS) e vá até a pasta onde encontra-se o servidor do Selenium. Você vai ter que executar o seguinte comando:

java -jar selenium-server.jar -htmlSuite <browser> <startURL> <suiteFile> <resultFile>

Vou explicar os parâmetros desse comando de trás pra frente.

O parâmetro resultFile indica o arquivo em que será gerado o relatório do teste.

O suiteFile indica o seu arquivo selenese gerado pela IDE. O único problema é que ele tem que ser um suite e não um test case.

O parâmetro startURL indica a url do site a ser testado.

E por último nessa lista, mas o primeiro parâmetro do comando, está o browser. O valor que você tem que colocar nesse parâmetro, pode ser:

  • *firefox
  • *chrome
  • *iexplore
  • *iehta
  • *safari
  • *opera
  • *googlechrome

Detalhe é que o asterisco faz parte dos valores. O valor *chrome chama o próprio Firefox enquanto que o *iehta chama o IE. Mas há uma leve diferença entre eles. O *chrome e o *iehta são cross-domain, o que faz com que o Selenium não tenha problemas caso o fluxo do seu teste seja redirecionado para outro domínio. Eles também dão mais poder para o Selenium não se esbarrar em problemas de segurança dos browsers.

Na próxima versão do Selenium, *firefox será sinônimo para *chrome e assim o mesmo para *iexplore. Portanto, dê preferência para utilizar *chrome e *iehta.

Ao passar uma dessas strings para o servidor do Selenium, ele irá em busca do executável do browser procurando pelo path default de instalação. No Windows XP, por exemplo, passando como parâmetro o valor *chrome, o Selenium vai procurar por “C:\Program Files\Mozilla Firefox\firefox.exe”.

Mas e se você instalou o Firefox em outro path, sem ser o default? É simples, basta indicar a string do browser seguida do path completo para o executável, por exemplo “*chrome c:\firefox\firefox.exe”. As aspas duplas aqui não estão por acaso, você vai ter que colocá-las quando quiser especificar o path. Esse esquema de passar onde browser está instalado é muito útil quando você tem mais de uma versão do mesmo browser instalada na máquina.

A lista dos browsers suportados você pode encontrar aqui.

Caso você queira testar em um browser não suportado, o Selenium aceita a string “*custom” que funciona como um coringa.

Criei um arquivo de teste para que você possa comprovar que tudo isso funciona, ehehe. Você vai precisar baixar dois arquivos: o suite e o test-case. Salve-os no C: e depois rode o seguinte comando:

java -jar selenium-server.jar -htmlSuite *iehta http://www.seuenium.com.br c:\teste-suite.html c:\result.html

Depois abra o arquivo result.html para conferir o resultado da execução:

Bom, é isso aí galera… Qualquer dúvida só perguntar.
:)

AJAX e Selenium

20 de dezembro de 2008

A pessoa que quer criar um bom teste com o Selenium, precisa ter alguns conhecimentos sólidos em:

  1. Html
  2. Xpath
  3. Ajax
  4. Sistema como um todo

Neste post, vou me aprofundar apenas com o conhecimento de AJAX. Isso mesmo, apenas conhecimento, já que o testador não precisa saber nada de implementação de AJAX.

AJAX é uma forma de fazer uma requisição ao servidor sem que seja necessário dar um reload completo na página. Essa requisição assíncrona, na grande maioria das vezes, manipula o html que está sendo exibido para o usuário. O testador primeiramente precisa identificar essa requisição AJAX e para isso, a forma mais fácil é instalar a extensão do Firebug no Firefox e identificar as requisições através da aba console. Após essa identificação, o testador precisa entender o que foi alterado no Html, para depois inserir alguns novos comandos no Selenium.

Para deixar essa explicação mais fácil de entender, resolvi criar uma página que faz AJAX. Clique aqui para visualizá-la.

Na tela é preciso selecionar um estado e uma cidade, e em seguida clicar no botão salvar que redirecionará para uma tela de sucesso. Caso nenhuma cidade for selecionada, aparecerá uma mensagem de erro.

Se você abrir a IDE e sair navegando pela tela, clicando em SP, São Paulo e depois em salvar, você verá a tela de sucesso. Os comandos criados pela IDE foram:

Apenas o último comando não foi criado automaticamente pela IDE. Eu coloquei o comando verifyText para validar que a mensagem de sucesso está aparecendo com a cidade que foi selecionada.

Até aí tudo bem. Mas se você quiser rodar o teste novamente, ele falhará:

Link do teste

Apareceu a mensagem de que nenhuma cidade foi selecionada porque o Selenium rodou tão rápido que clicou no botão salvar antes que as cidades do estado selecionado fossem carregadas via AJAX.

O que tem que ser feito para corrigir esse problema?

Como disse anteriormente, é preciso identificar o que foi alterado no html com a requisição AJAX. Nesse exemplo, há uma div com id div_cidades que no momento em que a página é carregada ela fica vazia. Ao selecionar um estado, o AJAX é acionado e preenche essa div com uma tag select contedos as.

Depois dessa identificação, vamos então acrescentar o comando do Selenium para corrigir isso. O comando waitForElementPresent é o ideal para esses casos. Ele fala pro Selenium esperar para executar o próximo passo até encontrar um determinado elemento na página. No nosso caso, é falar pro Selenium esperar a tag select que está abaixo da div com id div_cidades.

O teste corrigido fica assim:

Link do teste

Existem outros comandos de wait. Todos começam com o prefixo waitFor. Dê uma olhada na documentação ou na própria IDE, já que se você digitar waitFor, vai vir a lista de todos os comandos que começam com esse prefixo.

Esse mesmo tratamento com os comandos waitFor também podem ser aplicados se há uma chamada Javascript demorada, mesmo que ela não faça uma requisição AJAX.

Ok, mas o que acontece se o elemento esperado não aparecer?

O Selenium tem uma configuração que é o tempo máximo que ele fica esperando. Se esse tempo for excedido o Selenium retorna um erro de timeout. O padrão são 30 segundos, mas você pode alterar isso na IDE, “options > options > Default timeout value of recorded command”. Se você não está usando a IDE e está subindo um selenium server, há também uma configuração para setar o timeout.

Bom galera, é isso aí. Qualquer dúvida ou sugestão é só comentar no blog.

Valeuuuuu!!!!

:)

Primeiro Post, Primeiro Teste com a Selenium IDE

15 de dezembro de 2008

Esse é o meu primeiro post nesse blog, e como é a primeira vez, estou me familiarizando com a ferramenta wordpress.

Esse também é o primeiro passo que você deve fazer para conhecer o Selenium. Familiarize-se com os seus recursos. Instale a IDE no Firefox e brinque de criar testes bobos, só para aprender os principais comandos.

O Selenium é uma ferramenta para criar e executar testes automatizados em websites. A pessoa que quer criar um teste pode apenas abrir a IDE, sair navegando pelo site e salvar um arquivo, sem se preocupar com quais comandos foram criados.

Mas aí que está o problema. Se você não se preocupar com os comandos que a IDE gera, você nunca vai entender o Selenium corretamente e seu teste criado pode:

  1. Retornar resultado falso-positivo
  2. Quebrar na próxima execução
  3. Ser muito sensível a qualquer alteração de template
  4. Ser difícil de corrigir

No caso 1, o Selenium retorna que tudo executou com sucesso (tudo verdinho), porém o seu teste não fez o que tinha que fazer. Por exemplo, imagine que você tem que testar um formulário de cadastro de usuário. Você preenche tudo no formulário e em seguida clica no botão salvar e é redirecionado para uma tela de sucesso. Mas você não notou que o campo não obrigatório “complemento do endereço” que você preencheu, não foi salvo. Somente validar que foi redirecionado para tela de sucesso não é suficiente. Você tem que validar que todos os dados preenchidos no formulário foram cadastrados corretamente e os não preenchidos continuam não preenchidos.

No caso 2, imagine que você tem um campo que não pode repetir, por exemplo, login do usuário, e o seu teste é para validar a criacão de um usuário com sucesso. Se você rodar o teste novamente, vai dar erro informando que o login já existe. Há três formas de lidar com isso. A primeira é resetar o banco na hora do teste. A outra é remover o usuário após o teste. E a última é utilizar um valor randômico para concatenar com o login do usuário. Eu acho que essa última é a mais simples, já que dá para fazer alguns truques com o comando storeExpression.
Há um outro caso em que um teste pode não rodar numa segunda vez. Isso ocorre quando há uma requisição AJAX. A IDE não reconhece essa requisição e para isso você tem que usar alguns comandos de wait. Isso é bastante importante e depois vou dedicar um post somente sobre isso.

O caso 3 acontece quando a IDE salva os comandos utilizando a árvore DOM, ou seja, ela identifica os elementos do html pela sua estrutura a partir da raiz, por exemplo, /html/body/div/h1. O ideal é o Selenium utilizar os atributos name e id. Issso porque se futuramente você quiser mudar o layout da sua página e tiver que colocar uma segunda div no path anterior, o seu teste vai quebrar já que ele está baseado no DOM. Às vezes vale a pena você alterar o seu html apenas para acrescentar um id para facilitar o seu teste. Com isso você garante uma vida mais longa para esse teste não quebrar.

No caso 4, como a IDE grava tudo o que você faz e você não dá atenção para isso, quando mais frente seu teste estiver quebrando (vermelhinho), você perderá muito tempo só para entender o que exatamente está quebrando. Por isso comente o que você está fazendo. Há uma opção na IDE para fazer isso. Botão direito em cima de um comando e “Insert new Comment”. Vai ficar algo assim:

screenshot-selenium-ide

Bom, acho que é isso aí. Algumas dicas sempre são boas.

Continuarei postando sobre testes automatizados, integração contínua e n outras coisas. Até lá.