Selenium é uma ferramenta de apoio às necessidades de testes em aplicações web. Altamente flexível, permite muitas opções para a localização de elementos de interface no navegador e simular comportamentos reais de um usuário. A versão 2.0 tem como funcionalidade primária a integração da API WebDriver. Projetado para fornecer uma interface ainda mais simples, concisa e orientada a objeto, o que melhora de forma significativa o suporte aos problemas complexos que são enfrentados ao testar uma aplicação web.
Essa API pode ser chamada através de diversas linguagem de programação, porém, em nosso exemplo, iremos utilizar o NodeJS (JavaScript), que pode ser baixado no site oficial e que possui um gerenciador de pacotes (Node Package Manager – NPM), o qual permite a interação com um repositório online via linha de comando, facilitando a instalação de várias outras ferramentas.
Nesse exemplo, será utilizado uma ferramenta chamada Vows, gerenciada e instalada pelo NPM, que ajuda no desenvolvimento orientado a comportamento assíncrono. Usar testes assíncronos no NodeJS tem dois motivos. Primeiro (e talvez óbvio), é que o NodeJS é assíncrono e por isso os testes também deveriam ser. Segundo, é fazer com que os testes, os quais lidam com entrada e saída de dados, rodem mais rápido.
Breve resumo dos conceitos do Vows. Suite: um objeto que contêm um ou mais batches, e pode ser executado ou exportado. Batch: uma estrutura de contextos. Context: um objeto que pode conter um topic(opcional), nenhum ou mais vows, nenhum ou mais sub-contexts. Topic: pode ser tanto um valor ou uma função de código assíncrono. Vow: é uma função que recebe o _topic_ como um argumento e roda assertivas no topic.
O teste que será feito possui quatro passos: _(i) abrir o navegador, (ii) acessar uma página de teste, (iii) verificar o título da página e (iv)_ fechar o navegador. Algo bem simples. Suficiente para experimentar a versão 2.0 do Selenium.
As dependências necessárias podem ser instaladas usando o NPM, digitando o seguinte _script_ no terminal:
npm install -g phantomjs vows
npm install chai wd vows
Há duas maneiras de instalar dependências no NodeJS: globalmente ou localmente. Quando uma dependência é global, os arquivos são executáveis, tornando possível a utilização de uma dependência através da linha de comando. Quanto às dependências locais, estas são instaladas no diretório corrente, dentro de um diretório chamado _nodemodules.
O primeiro script, utilizando o parâmetro -g, instala duas dependências globais: phantomjs e vows.PhantomsJS é um headless WebKit, feito totalmente em javascript e possui suporte rápido e nativo para vários padrões web como manipulação de DOM, seletores CSS, JSON, Canvas e SVG.
Já o segundo script, instala três dependências locais: chai, wd e vows. Chai é uma biblioteca de assertivas BDD/TDD para NodeJS e navegadores, a qual pode ser ‘graciosamente’ utilizada com qualquer framework de teste JS. WD é um cliente em NodeJS para facilitar o acesso à API do Selenium 2, a qual suporta métodos como: fazer requisições GET e POST, clicar no botão VOLTAR do navegador, fazer refresh no navegador, pegar um printscreen da tela corrente, redimensionar e mover a janela do navegador, submeter formulário, digitar texto, usar cookies, selecionar um elemento DOM, clicar e mover um elemento DOM selecionado, etc.
Após a instalação de todas as dependências necessárias, vamos criar dois arquivos: _configuracao-webdriver-usando-phantom.js com as informações de configurações do webdriver e apenas-um-exemplo.js_ com os passos-a-passos simulando o comportamento real de um usuário.
configuracao-webdriver-usando-phantom.js
var exports = module.exports = {}, webdriver = require('wd'), browser = exports.browser = webdriver.remote({ hostname: "localhost", port: 8910 }); /** Vows Errored » callback not fired https://birkett.no/blog/2013/05/01/vows-errored-callback-not-fired/ */ process.on( 'uncaughtException', function(err) { console.error('Caught exception: ' + err.stack ); });
apenas-um-exemplo.js
var vows = require('vows'), expect = require('chai').expect, browser = require('./configuracao-webdriver-usando-phantom.js').browser; vows.describe('Apenas um exemplo') .addBatch({ 'Criando uma nova sessão no WebDriver': { topic: function() { var callback = this.callback; browser.init( {}, function(err, sessionID, capabilities) { callback( err ); }); }, 'Sessão criada': function() { /**...*/ } } }) .addBatch({ 'Acessando a página de teste do SauceLabs': { topic: function() { var callback = this.callback; browser.get( 'https://saucelabs.com/test/guinea-pig', function(err) { callback( err ); }); }, 'Página de teste aberta': function() { /**...*/ } } }) .addBatch({ 'Verificando o título da página': { topic: function() { var callback = this.callback; browser.title( function(err, title) { callback( err, title ); }); }, "O título da página deve conter 'Sauce Labs'": function(title) { expect(title).to.contain('Sauce Labs'); }, "O título da página deve conter 'page title'": function(title) { expect(title).to.contain('page title'); }, "O título da página deve conter 'I am a'": function(title) { expect(title).to.contain('I am a'); } } }) .addBatch({ 'Fechando o navegador': { topic: function() { var callback = this.callback; browser.quit( function(err){ callback( err ); }); }, 'Fim': function() { /**...*/ } } }).export(module);
Criado esses dois arquivos, é preciso, em um outro terminal, rodar o PhantomJS em modo WebDriver, digitando o seguinte comando:
phantomjs --webdriver=localhost:8910
Uma vez o PhantomJS rodando em segundo plano, basta rodar o vows, o parâmetro –spec serve apenas para ter um diferente tipo de ‘reporter’, segue o comando e uma ilustração do resultado obtido:
vows apenas-um-exemplo.js --spec
Esse exemplo contempla de forma bem simples a utilização da API do WebDriver/Selenium 2. Essa abordagem também pode ser feita em diferentes tipos de navegadores. Como é sempre melhor começarmos aos poucos, aplicando pequenos passos de cada vez, isso ficará para uma próxima discussão. Para quem se interessar, todo código está disponível em um gist. Muito obrigado.