Selenium Tutorial: Testes funcionais em aplicações Web
Selenium - Um framework para Testes funcionais em aplicações Web
Este artigo apresenta a ferramenta Selenium-IDE no contexto de desenvolvimento baseado em testes.
Artigos .NET Selenium - Um framework para Testes funcionais em aplicações Web
Com o passar dos anos, as técnicas e ferramentas para desenvolvimento de software vêm sendo aprimoradas e cada vez mais utilizadas em diferentes aplicações. Uma das maiores preocupações do desenvolvimento de software está relacionada à qualidade dos sistemas desenvolvidos e, conseqüentemente, com a sua estabilidade no ambiente de produção.
Uma falha em um sistema pode ocasionar vários problemas, desde prejuízos financeiros, comprometimento de cronogramas e até perda de vida humana, dependendo do sistema desenvolvido. Existem vários acidentes causados por falhas de software que ficaram famosos, desde falhas em aviões, foguetes e equipamentos.
Criação dos testes
Um exemplo onde houve perda de vidas humanas foi a falha do sistema em um equipamento de radioterapia chamado Therac-25. Este equipamento era controlado por computador, muito moderno para sua época, e permitia a utilização do mesmo equipamento para a aplicação de diversas intensidades de radiação nos pacientes. Houve uma série de seis acidentes relatados entre 1985 e 1987, nos quais os pacientes receberam overdose de radiação.
Pelo menos cinco mortes aconteceram devido aos acidentes, causados por falhas no software que controlava a máquina. Problemas deste tipo denotam a importância da utilização de um processo de desenvolvimento de software formal e, principalmente a utilização de alguma abordagem baseada em testes para aferição do sistema desenvolvido.
Atualmente há uma forte tendência de utilização de sistemas baseados na plataforma Web. As vantagens são muitas, desde a alta disponibilidade até a não necessidade de configuração máquina a máquina para instalação e configuração de sistemas. No entanto, diante dessa forte tendência e com a facilidade das linguagens de programação Web, está havendo um crescimento deste setor e, em sua grande maioria, sem a devida preocupação com a qualidade dos sistemas desenvolvidos.
A prática de teste manual de aplicações não garante a execução de todas as funcionalidades de um sistema. Sabe-se também que é impossível garantir que todos os defeitos de um sistema sejam eliminados, uma vez que os testes necessários para essa avaliação são normalmente em quantidade extremamente elevada, inviabilizando a sua aplicação de forma manual. O objetivo sempre é minimizar as falhas de um sistema e, para isso, torna-se imprescindível a utilização de um ambiente de testes automatizados, como o apresentado neste artigo.
Existem diversos tipos de testes e um deles é o teste funcional. Esse tipo de teste é baseado nas técnicas de caixa-preta, isso é, verificar o sistema e seus processos internos através de suas interfaces e da análise de suas saídas ou resultados.
Assim, a Selenium apresenta-se como uma ferramenta que possibilita essa interação com as interfaces de aplicações Web, para execução de testes funcionais definidos em seu IDE. Este artigo apresenta a ferramenta Selenium-IDE no contexto de desenvolvimento baseado em testes.
A Selenium-IDE é uma ferramenta de testes funcionais para aplicações Web que implementa o JSFTR (JavaScript Functional Test Runner), que é um framework que executa na página a ser testada, a fim de automatizar essa tarefa.
A ferramenta se apresenta como uma extensão do Firefox e depende do navegador para funcionar. Também é disponibilizado o núcleo da Selenium para ser executado independentemente de plataforma e do Firefox e, nesse caso, não é disponibilizada uma interface para configuração e execução dos testes, somente o JSFTR.
Tendo o Firefox instalado, o primeiro passo é fazer download da Selenium-IDE. Após, basta executar o arquivo baixado e será iniciada a instalação da extensão no Firefox (baixe no site oficial).
Depois de instalado como extensão, é disponibilizada no menu Ferramentas a opção Selenium IDE, como pode ser observado na Figura 1. Ao acionar essa opção, é visualizada a interface de configuração dos testes da Selenium-IDE, como apresentado na Figura 2.
Figura 1. Menu Ferramentas do Firefox
Figura 2. Selenium-IDE
Buscando exemplificar o uso da ferramenta Selenium-IDE, é proposto um estudo de caso utilizando o ambiente de desenvolvimento do Visual Studio 2005. Ele define um aplicativo Web ASP .NET C# que faz uso de um servidor IIS (Internet Information Services).
Para isso é definido no Visual Studio 2005 um projeto Web com o nome de TesteFuncionalWeb (namespace TesteFuncionalWeb), onde é apresentada uma classe chamada Aluno, com os atributos matricula, nome, nota1, nota2, notafinal e frequência.
Essa classe possui as respectivas propriedades dos atributos, mantendo assim o encapsulamento e emulando os métodos get e set, além do calcularAprovacao, responsável por verificar se o aluno foi aprovado ou não, de acordo com a sua frequência e notas. Essa classe foi definida no diretório Classes do projeto.
A Listagem 1 apresenta o código-fonte da classe, exibindo sua definição e implementação dos métodos. O calcularAprovacao verifica inicialmente se a freqüência do aluno é menor que 75%. Caso seja, o aluno é reprovado de imediato, fazendo com que a função retorne falso.
Caso contrário é verificado a média da nota1 com a nota2. Caso essa média for menor que 3, o aluno também é reprovado. Caso contrário, se a média for maior ou igual a 7, o aluno é aprovado. Se a média for maior ou igual a 3 e menor que 7, o aluno estará em prova final e será aprovado caso o valor da média de sua nota de prova final com a média anterior for superior ou igual a 5. Caso contrário, ele será reprovado.
Listagem 1. Definição da classe Aluno
namespace TesteFuncionalWeb.Classes
private double nota1, nota2, provafinal;
private int frequencia;
public Aluno(int pMatricula, String pNome,
double pNota1, double pNota2, double pProvaFinal,
int pFrequencia)
this.matricula = pMatricula;
this.nota1 = pNota1;
this.nota2 = pNota2;
this.provafinal = pProvaFinal;
this.frequencia = pFrequencia;
set { this.nome = value; }
public double Nota1
get { return this.nota1; }
set { this.nota1 = value; }
public double Nota2
get { return this.nota2; }
set { this.nota2 = value; }
public double ProvaFinal
get { return this.provafinal; }
set { this.provafinal = value; }
public int Frequencia
get { return this.frequencia; }
set { this.frequencia = value; }
public Boolean calcularAprovacao()
double vMedia = 0;
if (this.frequencia < 75)
vMedia = ((this.nota1 + this.nota2) / 2);
if (vMedia < 3)
if (vMedia > 7)
if (((vMedia + this.provafinal) / 2) < 5)
A classe Aluno representa então a classe de domínio do sistema. As interfaces são representadas pelas páginas Default.aspx e actionVerificaAluno.aspx. A Default.aspx apresenta um formulário para definição dos atributos do aluno e a actionVerificaAluno.aspx trata as requisições feitas pela Default.aspx.
Ao submeter o formulário ao actionVerificaAluno.aspx, o mesmo faz acesso à classe de domínio populando os atributos do objeto e invocando o método para cálculo de aprovação. Após esse processamento, é então exibida uma página com o resultado. A Figura 3 apresenta um diagrama representando o fluxo entre as entidades definidas.
Figura 3. Fluxos entre as entidades
O actionVerificaAluno.aspx trata as requisições do formulário da Default.aspx, e faz acessos ao modelo, representado pela classe Aluno. A Listagem 2 apresenta a página actionVerificaAluno.aspx e a Listagem 3 exibe o código-fonte do (Code-Behind) actionVerificaAluno.aspx.cs.
Listagem 2. Definição da página actionVerificaAluno.aspx
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="actionVerificaAluno.aspx.cs"
Inherits="TesteFuncionalWeb.actionVerificaAluno" %>
<title>Avaliar Aluno :: Aplicação Teste Funcional
Matrícula: <asp:Label ID="lblMatricula"
runat="server" Text=""></asp:Label><br/>
Nome: <asp:Label ID="lblNome" runat="server"
Text=""></asp:Label><br/>
Nota1: <asp:Label ID="lblNota1" runat="server"
Nota2: <asp:Label ID="lblNota2" runat="server"
Nota Final: <asp:Label ID="lblNotaFinal"
Freqüência: <asp:Label ID="lblFrequencia"
<b>Resultado:</b> <asp:Label ID="lblResultado"
<a href="Default.aspx">Voltar</a>
Listagem 3. Código-fonte do actionVerificaAluno.aspx.cs
using TesteFuncionalWeb.Classes;
namespace TesteFuncionalWeb
public partial class actionVerificaAluno : System.Web.UI.Page
int vMatricula = Convert.ToInt32(
Request.Form["vMatricula"]);
String vNome = Request.Form["vNome"];
double vNota1 = Convert.ToDouble(
Request.Form["vNota1"]);
double vNota2 = Convert.ToDouble(
Request.Form["vNota2"]);
double vNotaFinal = Convert.ToDouble(
Request.Form["vNotaFinal"]);
int vFrequencia = Convert.ToInt16(
Request.Form["vFrequencia"]);
Aluno objAluno = new Aluno(vMatricula, vNome,
vNota1, vNota2, vNotaFinal, vFrequencia);
if (objAluno.calcularAprovacao())
this.lblResultado.Text = "O Aluno " +
objAluno.Nome + " foi Aprovado!";
objAluno.Nome + " foi Reprovado!";
this.lblMatricula.Text = Convert.ToString(
objAluno.Matricula);
this.lblNome.Text = objAluno.Nome;
this.lblNota1.Text = Convert.ToString(
objAluno.Nota1);
this.lblNota2.Text = Convert.ToString(
objAluno.Nota2);
this.lblNotaFinal.Text = Convert.ToString(
objAluno.ProvaFinal);
this.lblFrequencia.Text = Convert.ToString(
objAluno.Frequencia);
catch (Exception vErro)
this.lblResultado.Text = "Erro: " +
vErro.ToString();
Na Listagem 2 é apresentada a página responsável por controlar e tratar as requisições do formulário presente na Default.aspx. Essa página exibe os atributos do aluno definido (matricula, nome, nota1, nota2, notafinal e frequência) e logo abaixo é reservado um local para apresentação do resultado, ou seja, se o aluno em questão foi aprovado ou não.
Observe que são definidos alguns controles ASP do tipo Label na página. Um para cada atributo ou variável da interface. Cada controle desse é manipulado no actionVerificaAluno.aspx.cs como uma variável para exibição da informação correspondente.
Já na Listagem 3 é definida a classe actionVerificaAluno.aspx.cs, codebehind da actionVerificaAluno.aspx. Essa é uma classe parcial e herda de System.Web.UI.Page. Inicialmente, importamos as classes e bibliotecas necessárias, com atenção especial à importação do diretório Classes (TesteFuncionalWeb.Classes).
Somente dessa forma é possível instanciar e manipular objetos da classe Aluno. Com isso, é possível então tratar o Page_Load que é iniciado antes do carregamento da actionVerificaAluno.aspx. Após, é realizado o processo de captura das variáveis definidas no formulário para utilizá-las na definição do objeto Aluno. A seguir, é invocado o calcularAprovacao, para verificar o estado do aluno em questão. Essa função retorna verdadeiro quando aprovado e falso quando reprovado. Realizamos um teste com esse retorno para atribuir à variável e controle ASP da interface a resposta desse processamento, informando o nome do aluno e o seu estado (aprovado ou reprovado).
Atribuímos valores às variáveis e controles ASP da interface de acordo com as propriedades do objeto Aluno instanciado. Esses valores serão exibidos ao finalizar o carregamento da actionVerificaAluno.aspx. Por fim, caso exista algum erro que fora capturado pela estrutura try...catch, é atribuída à variável de resultado uma mensagem de erro.
Com o modelo e actionVerificaAluno definidos, é possível definir o formulário presente na Default.aspx. A Figura 4 exibe a interface do Default.aspx e a Listagem 4 seu código-fonte. Para essa página não foi alterado o seu respectivo Code Behind, logo o mesmo não é apresentado no artigo.
Figura 4. Página Default.aspx
Listagem 4. Código da página Default.aspx
Inherits="TesteFuncionalWeb._Default" %>
<h1>Verificar Aprovação de Aluno</h1>
<form name="frmCadastroAluno"
action="actionVerificaAluno.aspx" method="post"
id="frmCadastroAluno">
Matricula:</td>
<input type="text" name="vMatricula"
<input type="text" name="vNome" size="40"/>
Nota 1:</td>
<input type="text" name="vNota1" size="40"/>
Nota 2:</td>
<input type="text" name="vNota2" size="40"/>
Nota Final:</td>
<input type="text" name="vNotaFinal"
Freqüencia:</td>
<input type="text" name="vFrequencia"
<input type="submit" name="Enviar"
value="Enviar"/>
Na Listagem 4 é possível observar a definição de um formulário de nome frmCadastroAluno, tendo o action a actionVerificaAluno.aspx. Esse formulário apresenta em forma de campos todos os atributos da classe Aluno: matrícula, nome, nota1, nota2, nota final e frequência. Dessa forma é possível digitar os dados do aluno com o intuito de verificar o seu estado (aprovado ou reprovado).
Com o estudo de caso desenvolvido e funcional, é possível executá-lo para então criar os testes. Nesse sentido, a Selenium-IDE fornece uma interface para configuração dos testes e sua execução. É possível criar os testes de forma manual ou então utilizar o recurso de gravação de testes. Esse recurso permite gravar toda a interação realizada com a página a ser testada de forma automatizada.
Com a página Default.aspx iniciada, já é possível iniciar a gravação do teste, opção automatizada que é disponibilizada no ambiente da ferramenta. Inicialmente, é necessário acionar a opção clique para gravar (Click to Record), como pode ser visualizado na Figura 5.
Figura 5. Menu do Selenium-IDE
Essa opção é o primeiro ícone da direita para esquerda. Dessa forma, qualquer interação com a página será adicionada na interface da Selenium-IDE de forma automática e dinâmica. Deve-se então preencher o formulário com os dados de um aluno.
O primeiro caso de teste a ser criado representa um aluno que foi aprovado na prova final, tendo nota1 igual a 3, nota2 igual a 3, notafinal igual a 7 e frequencia em 75%. O seu nome é Paulo da Silva e matrícula 2002102013. Depois de preenchidos os dados, deve-se submeter o formulário, acionando o botão Enviar da página.
Após o processamento, é apresentada a actionVerificaAluno.aspx, com a mensagem se o aluno foi ou não aprovado. Para esse caso, o esperado é que o aluno tenha sido aprovado e por isso deve-se configurar o teste para verificar se esse processo foi definido corretamente. Para isso, seleciona-se a palavra Aprovado e clica-se com o botão direito. São então apresentadas algumas opções da Selenium-IDE, como pode ser visualizado na Figura 6.
Figura 6. Opções do botão direito da Selenium-IDE
Nesse caso, deve-se acionar a opção para verificar a presença do texto Aprovado na página, com o comando assertTextPresent Aprovado. Esse comando é responsável por definir o valor esperado do teste para comparação com o valor obtido na sua execução.
Ao final desses passos, está criado o primeiro caso de teste. Com isso, a interface do Selenium-IDE deve estar configurada de acordo com a Figura 7.
Figura 7. Caso de teste configurado no Selenium-IDE
Com o teste criado, é possível então salvá-lo. Cada caso de teste deve ser salvo em um arquivo independente, no formado HTML e no mesmo diretório, para posterior execução. Para este exemplo, foi criado o diretório C:\testes, onde os arquivos HTML com os casos de teste serão salvos.
Esse primeiro caso de teste foi chamado de teste1.html e foi salvo no diretório especificado. O conteúdo desse arquivo pode ser observado na Listagem 5.
Listagem 5. Código HTML gerado pelo Selenium-IDE para o caso de teste
<title>teste1</title>
<tr><td rowspan="1" colspan="3">teste1</td></tr>
<td>/Default.aspx</td>
<td>vMatricula</td>
<td>2002102013</td>
<td>vNome</td>
<td>Paulo da Silva</td>
<td>vNota1</td>
<td>vNota2</td>
<td>vNotaFinal</td>
<td>vFrequencia</td>
<td>Enviar</td>
<td>Aprovado</td>
Com isso é possível criar os demais casos de teste. Para este exemplo, são criados cinco casos de teste para cobrir as opções de processamento. Para definição dos próximos casos de testes, pode-se ou executar todo esse procedimento de gravação novamente ou então editar os valores das variáveis na Selenium-IDE no arquivo HTML gerado, gerando cinco arquivos diferentes.
O segundo caso de teste irá cobrir a opção do aluno ser reprovado por freqüência. Para isso, é definida a variável frequencia para 74%. Os demais valores são definidos com "0", já que o aluno é reprovado de imediato. Para esse caso de teste, o valor esperado é Reprovado.
O terceiro caso de teste apresenta um aluno com 75% de freqüência, primeira nota com valor 3, segunda nota com 2,9 e prova final com 0, pois não importa o seu valor nessa situação. Para esse caso é esperado o valor Reprovado.
Para o quarto caso de teste é configurado o aluno com 75% de freqüência, primeira e segunda notas com valor 3 e prova final com valor 6,9. Espera-se o valor Reprovado como retorno. Por fim, o quinto e último caso de teste, o aluno é definido com 75% de freqüência e notas com valores iguais a 7 para a primeira e segunda notas. A nota final foi definida com 0. O valor esperado de retorno para esse caso de teste é Aprovado. Observe nesse caso que a média é igual a 7.
Existem duas formas para executar os testes. A primeira é executar teste a teste na própria interface do Selenium-IDE. Para isso são disponibilizadas três formas de execução. A primeira chamada Executar, que executa de forma rápida, sem a possibilidade de acompanhar a execução do teste, a segunda chamada Caminhar, que executa o teste de forma lenta, com a possibilidade de visualização do teste em execução.
A terceira chamada Iterar, sendo necessária a intervenção do usuário para a execução dos testes passo a passo. Para essa forma, são disponibilizados na interface os botões Iniciar teste, Pausar e Iterar, com o objetivo de manipular a execução dos testes. Essas opções estão disponíveis na interface da Selenium-IDE, como pode ser visualizado da esquerda para a direita na Figura 5.
A outra forma para executar os testes é utilizar o TestRunner da Selenium-IDE. Esse, quando configurado com uma gama de testes, faz as execuções de forma automática de todos os testes quantas vezes forem necessárias. Para isso, é necessário criar um novo arquivo HTML com o nome TestSuite.html.
Para este exemplo, são definidos nesse arquivo os caminhos para os seis casos de teste apresentados. Esse arquivo deve ser salvo no mesmo local que os casos de teste estão, ou seja, no diretório C:\testes.
A Listagem 6, apresenta o conteúdo desse arquivo. O código HTML apresenta uma tabela com um link para cada caso de teste definido. O target de cada link é o frame testFrame, que, posteriormente, é interpretado pelo TestRunner.
Listagem 6. Código HTML do arquivo TestSuite.html
<td>Teste Selenium - WebMobile</td>
<a target="testFrame" href="teste1.html">
Teste 1</a></td>
<a target="testFrame" href="teste2.html">
Teste 2</a></td>
<a target="testFrame" href="teste3.html">
Teste 3</a></td>
<a target="testFrame" href="teste4.html">
Teste 4</a></td>
<a target="testFrame" href="teste5.html">
Teste 5</a></td>
O próximo passo é acessar a URL do TestRunner pelo Firefox, configurando o local do arquivo TestSuite.html. Neste exemplo, a URL acessada é: chrome://selenium-ide/content/selenium/TestRunner.html?baseURL=http://localhost:55335/&test=file://C:\testes\TestSuite.html.
Observe que na URL é definido o caminho do teste &test=file://C:\testes\TestSuite.html e o local da página http://localhost:55335. De acordo com o site e local salvo em disco do TestSuite.html, esses valores devem ser alterados.
Ao entrar na URL, é apresentada a interface do TestRunner para execução dos testes. Ao executar todos os testes é possível observar o resultado, conforme apresentado na Figura 8.
Figura 8. Resultado dos testes no TestRunner
Pode-se observar que o quinto caso de teste falhou. Isso se deve ao fato que se esperaria que alunos com média 7 fossem aprovados e, na realidade, estão sendo reprovados. De acordo com o calcularAprovacao, quem possuir média entre 3 e 7 (inclusive) deve fazer prova final.
Como esse aluno possui valor 0 na sua prova final, o mesmo foi reprovado, falhando assim o caso de teste. Com isso foi possível identificar uma falha no código-fonte, uma vez que o aluno com média 7 deveria ser aprovado.
Deve-se então fazer uma alteração no calcularAprovacao para que sejam aprovados os alunos com média superior ou igual a 7. A alteração deve ser realizada na linha referente à verificação da média ser maior que 7, devendo ser modificada para if (vMedia >= 7).
A Figura 9 apresenta a interface do TestRunner com os resultados sem falhas após a alteração proposta. Essa situação caracteriza um defeito no sistema que foi encontrado através de um caso de teste bem planejado, testando os valores limites das condições que, muitas vezes, apresentam problemas.
Figura 9. Resultado dos testes no TestRunner após alteração no calcularAprovacao
Foi apresentada neste artigo a ferramenta Selenium-IDE para criação e execução de testes funcionais de forma automatizada. A utilização dessa abordagem é extremamente importante para minimizar a quantidade de defeitos nos sistemas desenvolvidos. A utilização conjunta de outras técnicas baseadas em testes, como testes unitários, de cobertura, testes de regressão, integração, entre outros, busca melhorar ainda mais este índice de confiança na aplicação desenvolvida.
Essa abordagem de desenvolvimento baseado em testes é um dos principais conceitos dos métodos de desenvolvimento ágil. A abordagem de testes é inclusive um dos temas do documento chamado manifesto ágil, onde vários autores propõem as características, conceitos e princípios da metodologia de desenvolvimento.
Um exemplo de método ágil é o XP (eXtreme Programming). Além disso, modelos que definem padrões de maturidade para o desenvolvimento de software também apresentam a abordagem de testes, sendo o caso do CMMI (Capability Maturity Model Integration) e do MPS.BR (Melhoria de Processos do Software Brasileiro) onde, para ambos, a utilização de testes é um item essencial em seus níveis iniciais.
O teste funcional deve ser tratado como um teste de caixa preta. Devem-se testar as interfaces e os resultados de processamento causados pelos dados inseridos no sistema. A Selenium-IDE auxilia na criação dos testes, contando com uma interface fácil e intuitiva e com recursos de gravação de testes.
Neste sentido, a Selenium-IDE é uma ferramenta de testes funcionais para o ambiente Web, que busca automatizar o processo de testes, tornando possível a implantação de uma política de testes.