Avançar para a área de conteúdo

Ao clicar em Enviar, você concorda com os termos e condições do developerWorks.

Na primeira vez que você efetua sign in no developerWorks, um perfil é criado para você. Informações selecionadas do seu perfil developerWorks são exibidas ao público, mas você pode editá-las a qualquer momento. Seu primeiro nome, sobrenome (a menos que escolha ocultá-los), e seu nome de exibição acompanharão o conteúdo que postar.

Todas as informações enviadas são seguras.

  • Fechar [x]

Ao se conectar ao developerWorks pela primeira vez, é criado um perfil para você e é necessário selecionar um nome de exibição. O nome de exibição acompanhará o conteúdo que você postar no developerWorks.

Escolha um nome de exibição de 3 - 31 caracteres. Seu nome de exibição deve ser exclusivo na comunidade do developerWorks e não deve ser o seu endereço de email por motivo de privacidade.

Ao clicar em Enviar, você concorda com os termos e condições do developerWorks.

Todas as informações enviadas são seguras.

  • Fechar [x]

Teste eficiente de unidade JavaScript

Automatize o teste de código JavaScript em vários navegadores

Hazem Saleh, Staff Software Engineer, IBM  
Photo of Hazem Saleh
Hazem Saleh tem seis anos de experiência em tecnologias JEE e de código aberto. Ele é comprometido com o Apache MyFaces e o iniciador de muitos componentes nos projetos do MyFaces, como o Tomahawk CAPTCHA, Commons ExportActionListener, Media, PasswordStrength e outros. Ele é o fundador do GMaps4JSF (um projeto de integração do Google Maps com o JavaServer Faces) e Mashups4JSF (um projeto de integração de serviços de mashup com o JavaServer Faces). Ele é o autor do livro "The Definitive Guide to Apache MyFaces and Facelets (Apress)" e muitos artigos sobre JSF, um autor contribuidor do developerworks e um palestrante público sobre JSF. Ele agora trabalha para a IBM Egito como engenheiro contratado. Hazem é reconhecido como Especialista no assunto em tecnologias web 2.0.

Resumo:  O código JavaScript que é executado em um navegador não irá necessariamente funcionar em outros. Sem fazer teste de unidade do código, as organizações gastam dinheiro para testar e retestar aplicativos da Web ao decidir atualizar ou suportar novos navegadores. Neste artigo, saiba como o teste de unidade eficiente do JavaScript pode facilitar o suporte a mais navegadores.

Data:  14/Out/2011
Nível:  Intermediário Também disponível em :   Inglês
Atividade:  1016 visualizações
Comentários:  


Um exemplo de código de Javascript quebrado

Um dos maiores desafios enfrentados pelos aplicativos da Web é o suporte a navegadores da Web com diferentes versões. O código JavaScript que executa no Safari não funciona necessariamente no Windows® Internet Explorer (IE), Firefox ou Google Chrome. Esse desafio é uma herança da falta de testes do código Javascript na camada de apresentação desde o primeiro dia. Sem fazer teste de unidade do código, as organizações podem pagar por testes repetidos de aplicativos da Web ao decidir atualizar ou suportar novos navegadores. Este artigo mostra como usar um teste de unidade eficiente do código JavaScript para reduzir os custos de teste.

Um dos casos de uso comum é ter uma validação JavaScript do formulário de login. Considere o formulário na Listagem 1.


Listagem 1. O formulário de login
<FORM>
	<table>
		<tr>
			<td>Username</td>
			<td><input type="text" id="username"/></td>
			<td><span id="usernameMessage"></span></td>
		</tr>
		<tr>
			<td>Password</td>
			<td><input type="password" id="password"/></td>
			<td><span id="passwordMessage"></span></td>
		</tr>	
		<tr>
			<td><input type="button" onclick="new appnamespace.
			ApplicationUtil().validateLoginForm()" value="Submit"/></td>
		</tr>
	</table>
</FORM>

O formulário é simples. Ele consiste em campos de nome de usuário e de senha. Ao clicar no botão submit, uma validação específica de formulário é realizada por meio de ApplicationUtil. Esse é um objeto JavaScript responsável por validar o formulário HTML. A listagem 2 mostra o código do objeto ApplicationUtil.


Listagem 2. O código quebrado do objeto ApplicationUtil
appnamespace = {};

appnamespace.ApplicationUtil = function() {};

appnamespace.ApplicationUtil.prototype.validateLoginForm =  function(){
	var error = true;
	document.getElementById("usernameMessage").innerText = "";
	document.getElementById("passwordMessage").innerText = "";	

	if (!document.getElementById("username").value) {
		document.getElementById("usernameMessage").innerText = 
		"This field is required";
		error = false;
	}
	
	if (!document.getElementById("password").value) {
		document.getElementById("passwordMessage").innerText = 
		"This field is required";
		error = false;
	}		

	return error;		
};

Na Listagem 2, o objeto ApplicationUtil fornece uma validação simples. Ele verifica se os campos de nome de usuário e senha foram preenchidos. Se um campo estiver vazio, uma mensagem de erro dizendo This field is required aparece.

Embora o código anterior funcione no Internet Explorer 8 e Safari 5.1, ele não funciona no Firefox 3.6, pois a propriedade innerText não é suportada pelo Firefox. Geralmente, o maior problema (no código anterior e em código JavaScript semelhante) é que não é fácil detectar se o código JavaScript escrito é compatível com diferentes navegadores.

Uma solução para esse problema é ter um teste de unidade automatizado que verifica se o código está correto em vários navegadores.


JsTestDriver

Uma das melhores estruturas de teste de unidade JavaScript é a biblioteca JsTestDriver, que fornece teste para código JavaScript em vários navegadores. A Figura 1 mostra a arquitetura do JsTestDriver.


Figura 1. Arquitetura do JsTestDriver

jsTestDriver é software livre

jsTestDriver é um projeto de software livre com a licença Apache 2.0, hospedado no Google Code, um repositório de projetos semelhante ao SourceForge. Desenvolvedores podem criar e gerenciar projetos públicos nesse repositório, desde que usem uma das licenças aprovadas pela Open Source Initiative.

Muitas outras ferramentas de teste de unidade JavaScript estão disponíveis. Consulte a seção recursos abaixo para referência a outras ferramentas, como Dojo Objective Harness (DOH).

O servidor é responsável por carregar o código executador dos casos de teste de JavaScript nos diferentes navegadores após serem capturados. O navegador pode ser capturado pela linha de comando ou apontando o navegador para a URL do servidor. Quando o navegador é capturado, ele é chamado de navegador escravo. O servidor carrega o código JavaScript, executa as etapas de teste em cada navegador e retorna os resultados ao cliente.

O cliente (linha de comando) precisa de dois itens principais:

  1. Arquivos JavaScript — arquivos de origem e arquivos de teste, e
  2. Arquivo de configuração — para organizar o carregamento de arquivos de origem e dos arquivos de teste.

Essa arquitetura é flexível, permitindo que um único servidor capture qualquer número de navegadores de outras máquinas na rede. Por exemplo, pode ser útil se o seu código estiver sendo executado no Linux, mas você deseja executar as etapas de teste no Microsoft Internet Explorer em outra máquina Windows.

Para começar a trabalhar com a biblioteca JsTestDriver, faça o download da versão mais recente do JsTestDriver 1.3.2.


Escrever o código do teste de unidade

Agora, vamos escrever as etapas de teste JavaScript. Visando a simplicidade, eu irei testar os seguintes casos:

  • Um valor vazio para nome de usuário e um valor vazio para senha.
  • Um valor vazio para nome de usuário e um valor não vazio para senha.
  • Um valor não vazio para nome de usuário e um valor vazio para senha.

A Listagem 3 mostra parte do código do objeto ApplicationUtilTest que representa o objeto TestCase.


Listagem 3. Parte do código do objeto ApplicationUtilTest
ApplicationUtilTest = TestCase("ApplicationUtilTest");

ApplicationUtilTest.prototype.setUp = function () {
/*:DOC += <FORM action=""><table><tr><td>Username</td><td>
<input type="text" id="username"/></td><td><span id="usernameMessage">
</span></td></tr><tr><td>Password</td><td>
<input type="password" id="password"/></td><td><span id="passwordMessage"
></span></td></tr></table></FORM>*/
};

ApplicationUtilTest.prototype.testValidateLoginFormBothEmpty = function () {
	var applicationUtil = new appnamespace.ApplicationUtil();
	
	/* Simulate empty user name and password */
	document.getElementById("username").value = "";
	document.getElementById("password").value = "";	
	
	applicationUtil.validateLoginForm();
	
	assertEquals("Username is not validated correctly!", "This field is required", 
	document.getElementById("usernameMessage").innerHTML);
	assertEquals("Password is not validated correctly!", "This field is required", 
	document.getElementById("passwordMessage").innerHTML);	
};

O objeto ApplicationUtilTest é criado por meio do objeto TestCase do JsTestDriver. Se você estiver familiarizado com a estrutura JUnit, também conhecerá os métodos setUp e testXXX. O método setUp é usado para inicializar as etapas de teste. Neste exemplo, eu o usei para declarar o fragmento HTML que será usado pelos demais métodos de etapas de teste.

A anotação DOC é uma convenção JsTestDriver usada facilmente para declarar um fragmento HTML.

No método testValidateLoginFormBothEmpty, um objeto ApplicationUtil é criado para uso dentro do método de etapas de teste. O código em seguida simula a inserção de um nome de usuário e senha vazios, recuperando seus elementos DOM e configurando seus valores para valores vazios. O método validateLoginForm é chamado para realizar a real validação do formulário. Finalmente, assertEquals é solicitado para garantir que a mensagem nos elementos de período usernameMessage e passwordMessage estejam corretos, ou seja: This field is required.

No JsTestDriver, é possível usar estas construções:

  • fail("msg") - indica que o teste deve falhar e que o parâmetro de mensagem será exibido como uma mensagem de erro.
  • assertTrue("msg", actual) — declara que o parâmetro real é verdadeiro. Se não, o parâmetro de mensagem será exibido como uma mensagem de erro.
  • assertFalse("msg", actual) — declara que o parâmetro real é falso. Se não, o parâmetro de mensagem será exibido como uma mensagem de erro.
  • assertSame("msg", expected, actual) — declara que o parâmetro real é o mesmo que o parâmetro esperado. Se não, o parâmetro de mensagem será exibido como uma mensagem de erro.
  • assertNotSame("msg", expected, actual) — declara que o parâmetro real não é o mesmo que o parâmetro esperado. Se não, o parâmetro de mensagem será exibido como uma mensagem de erro.
  • assertNull("msg", actual) — declara que o parâmetro real é nulo. Se não, o parâmetro de mensagem será exibido como uma mensagem de erro.
  • assertNotNull("msg", actual) — declara que o parâmetro real não é nulo. Se não, o parâmetro de mensagem será exibido como uma mensagem de erro.

O código dos outros métodos inclui as outras etapas de teste. A Listagem 4 mostra o código completo do objeto de etapas de teste.


Listagem 4. O código completo do objeto ApplicationUtil
ApplicationUtilTest = TestCase("ApplicationUtilTest");

ApplicationUtilTest.prototype.setUp = function () {
/*:DOC += <FORM action=""><table><tr><td>Username</td><td>
<input type="text" id="username"/></td><td><span id="usernameMessage">
</span></td></tr><tr><td>Password</td><td>
<input type="password" id="password"/></td><td><span id="passwordMessage"
></span></td></tr></table></FORM>*/
};

ApplicationUtilTest.prototype.testValidateLoginFormBothEmpty = function () {
	var applicationUtil = new appnamespace.ApplicationUtil();
	
	/* Simulate empty user name and password */
	document.getElementById("username").value = "";
	document.getElementById("password").value = "";	
	
	applicationUtil.validateLoginForm();
	
	assertEquals("Username is not validated correctly!", "This field is required", 
	document.getElementById("usernameMessage").innerHTML);
	assertEquals("Password is not validated correctly!", "This field is required", 
	document.getElementById("passwordMessage").innerHTML);	
};

ApplicationUtilTest.prototype.testValidateLoginFormWithEmptyUserName = function () {
	var applicationUtil = new appnamespace.ApplicationUtil();
	
	/* Simulate empty user name and password */
	document.getElementById("username").value = "";
	document.getElementById("password").value = "anyPassword";	
	
	applicationUtil.validateLoginForm();
	
	assertEquals("Username is not validated correctly!", 
	"This field is required", document.getElementById("usernameMessage").innerHTML);
	assertEquals("Password is not validated correctly!", 
	"", document.getElementById("passwordMessage").innerHTML);	
};

ApplicationUtilTest.prototype.testValidateLoginFormWithEmptyPassword = function () {
	var applicationUtil = new appnamespace.ApplicationUtil();
	
	document.getElementById("username").value = "anyUserName";
	document.getElementById("password").value = "";	
	
	applicationUtil.validateLoginForm();
	
	assertEquals("Username is not validated correctly!", 
	"", document.getElementById("usernameMessage").innerHTML);
	assertEquals("Password is not validated correctly!", 
	"This field is required", document.getElementById("passwordMessage").
	innerHTML);	
};


Configurar os diferentes navegadores com os testes

Uma das práticas recomendadas ao testar o código JavaScript é colocar o código de origem JavaScript em uma pasta diferente do código de teste. Para o exemplo mostrado na Figura 2, eu nomeei a pasta de origem JavaScript de "js-src", e a pasta de teste JavaScript de "js-test", na pasta-pai "js".


Figura 2. A estrutura de pasta de teste JavaScript

Após estruturar as pastas de origem e de teste, é preciso fornecer o arquivo de configuração. Por padrão, o executador JsTestDriver procura um arquivo de configuração chamado jsTestDriver.conf. O nome do arquivo de configuração pode ser alterado na linha de comando. A Listagem 5 mostra o conteúdo do arquivo de configuração JsTestDriver.


Listagem 5. O conteúdo do arquivo de configuração JsTestDriver

server: http://localhost:9876

load:
  - js-src/*.js
  - js-test/*.js

O arquivo de configuração está escrito no formato YAML. A diretiva server especifica o endereço do servidor de teste, enquanto a diretiva load indica quais arquivos JavaScript deverão ser carregados nos navegadores, e em qual ordem.

Agora, vamos executar a classe de etapas de teste nos navegadores IE, Firefox e Safari.

Para executar as classes de etapas de teste, é preciso iniciar o servidor. O servidor JsTestDriver pode ser iniciado usando a seguinte linha de comando:

java -jar JsTestDriver-1.3.2.jar --port 9876 --browser "[Firefox Path]",
          "[IE Path]","[Safari Path]"

Ao usar essa linha de comando, o servidor será iniciado na Porta 9876 e irá capturar os navegadores Firefox, IE e Safari na máquina.

Após iniciar e capturar os navegadores, use a seguinte linha de comando para executar as classes de etapas de teste:

java -jar JsTestDriver-1.3.2.jar --tests all

Após executar o comando, você verá os resultados da primeira execução, como mostra a Listagem 6.


Listagem 6. Os resultados da primeira execução
Total 9 tests (Passed: 6; Fails: 3; Errors: 0) (16.00 ms)
  Firefox 3.6.18 Windows: Run 3 tests (Passed: 0; Fails: 3; Errors 0) (8.00 ms)
    ApplicationUtilTest.testValidateLoginFormBothEmpty failed (3.00 ms): 
	AssertError: Username is not validated correctly! expected "This field 
	is required" but was "" Error("Username is not validated correctly! 
	expected \"This field is required\" but was \"\"")@:0()@http://localhost
	:9876/test/js-test/TestApplicationUtil.js:16

    ApplicationUtilTest.testValidateLoginFormWithEmptyUserName failed (3.00 ms): 
	AssertError: Username is not validated correctly! expected "This field is 
	required" but was "" Error("Username is not validated correctly! expected 
	\"This field is required\" but was \"\"")@:0()@http://localhost:9876/test
	/js-test/TestApplicationUtil.js:29

    ApplicationUtilTest.testValidateLoginFormWithEmptyPassword failed (2.00 ms): 
	AssertError: Password is not validated correctly! expected "This field is 
	required" but was "" Error("Password is not validated correctly! expected 
	\"This field is required\" but was \"\"")@:0()@http://localhost:9876/test/
	js-test/TestApplicationUtil.js:42
	
  Safari 534.50 Windows: Run 3 tests (Passed: 3; Fails: 0; Errors 0) (2.00 ms)
  Microsoft Internet Explorer 8.0 Windows: Run 3 tests (Passed: 3; Fails: 0; 
  Errors 0) (16.00 ms)
Tests failed: Tests failed. See log for details.

Observe na Listagem 6 que o principal problema é com o Firefox. Os testes são executados com sucesso no Internet Explorer e no Safari.


Corrigir o código JavaScript e executar novamente as etapas de teste

Vamos corrigir o código JavaScript quebrado. Usaremos innerHTML ao invés de innerText. A Listagem 7 mostra o código corrigido do objeto ApplicationUtil.


Listagem 7. O código corrigido do objeto ApplicationUtil

appnamespace = {};

appnamespace.ApplicationUtil = function() {};

appnamespace.ApplicationUtil.prototype.validateLoginForm =  function(){
	var error = true;
	document.getElementById("usernameMessage").innerHTML = "";
	document.getElementById("passwordMessage").innerHTML = "";	

	if (!document.getElementById("username").value) {
		document.getElementById("usernameMessage").innerHTML = 
		"This field is required";
		error = false;
	}
	
	if (!document.getElementById("password").value) {
		document.getElementById("passwordMessage").innerHTML = 
		"This field is required";
		error = false;
	}		

	return error;		
};

Execute novamente o objeto de etapas de teste usando o argumento de linha de comando --test all. A Listagem 8 mostra os resultados da segunda execução.


Listagem 8. Os resultados da segunda execução
Total 9 tests (Passed: 9; Fails: 0; Errors: 0) (9.00 ms)
  Firefox 3.6.18 Windows: Run 3 tests (Passed: 3; Fails: 0; Errors 0) (9.00 ms)
  Safari 534.50 Windows: Run 3 tests (Passed: 3; Fails: 0; Errors 0) (5.00 ms)
  Microsoft Internet Explorer 8.0 Windows: Run 3 tests (Passed: 3; Fails: 0; Errors 0) 
  (0.00 ms)

Como mostra a Listagem 8, o código JavaScript agora está funcionando direito no IE, Firefox e Safari.


Conclusão

Neste artigo, você aprendeu a testar o código de um aplicativo JavaScript em diferentes navegadores usando uma das mais poderosas ferramentas de teste de unidade do JavaScript (JsTestDriver). Você sabe o que é o JsTestDriver, como configurá-lo e como usá-lo dentro de um aplicativo da Web para garantir a qualidade e robustez do código JavaScript do seu aplicativo.



Download

DescriçãoNomeTamanhoMétodo de download
The source codesimple.zip3.35MBHTTP

Informações sobre métodos de download


Recursos

Aprender

Obter produtos e tecnologias

Discutir

Sobre o autor

Photo of Hazem Saleh

Hazem Saleh tem seis anos de experiência em tecnologias JEE e de código aberto. Ele é comprometido com o Apache MyFaces e o iniciador de muitos componentes nos projetos do MyFaces, como o Tomahawk CAPTCHA, Commons ExportActionListener, Media, PasswordStrength e outros. Ele é o fundador do GMaps4JSF (um projeto de integração do Google Maps com o JavaServer Faces) e Mashups4JSF (um projeto de integração de serviços de mashup com o JavaServer Faces). Ele é o autor do livro "The Definitive Guide to Apache MyFaces and Facelets (Apress)" e muitos artigos sobre JSF, um autor contribuidor do developerworks e um palestrante público sobre JSF. Ele agora trabalha para a IBM Egito como engenheiro contratado. Hazem é reconhecido como Especialista no assunto em tecnologias web 2.0.

Ajuda para Relatar Abuso

Relatar abuso

Obrigado. Esta entrada foi sinalizada para atenção do moderador.


Ajuda para Relatar Abuso

Relatar abuso

Falha no envio do Relatório de abuso. Tente novamente mais tarde.


developerWorks: Registre-se


Precisa de um ID IBM?
Esqueceu seu ID IBM?


Esqueceu sua senha?
Alterar sua senha

Ao clicar em Enviar, você concorda com os termos de uso do developerWorks.

 


Na primeira vez que você efetua sign in no developerWorks, um perfil é criado para você. Informações selecionadas do seu perfil developerWorks são exibidas ao público, mas você pode editá-las a qualquer momento. Seu primeiro nome, sobrenome (a menos que escolha ocultá-los), e seu nome de exibição acompanharão o conteúdo que postar.

Selecione seu nome de exibição

Ao se conectar ao developerWorks pela primeira vez, é criado um perfil para você e é necessário selecionar um nome de exibição. O nome de exibição acompanhará o conteúdo que você postar no developerWorks.

Escolha um nome de exibição de 3 - 31 caracteres. Seu nome de exibição deve ser exclusivo na comunidade do developerWorks e não deve ser o seu endereço de email por motivo de privacidade.

(Deve possuir de 3 a 31 caracteres.)


Ao clicar em Enviar, você concorda com os termos de uso do developerWorks.

 


Classificar este artigo

Comentários

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=80
Zone=Software livre, Tecnologia Java
ArticleID=765347
ArticleTitle=Teste eficiente de unidade JavaScript
publish-date=10142011

Conheça a IBM da sua cidade

Virtual Branch Office Brasil

A IBM está mais perto do que você imagina!


Tags

Help
Use o campo de pesquisa para encontrar todos os tipos de conteúdo no My developerWorks com essa tag.

Use a barra de rolagem para ver mais ou menos tags.

Tags populares mostra as principais tags para esta zona de conteúdo em particular (por exemplo, Java technology, Linux, WebSphere).

Minhas tags mostra suas tags para esta zona de conteúdo em particular (por exemplo, Java technology, Linux, WebSphere).

Use o campo de pesquisa para localizar todos os tipos de conteúdo no Meu developerWorks com essa tag. Tags populares mostra as tags principais para essa zona de conteúdo particular (por exemplo, tecnologia Java, Linux, WebSphere). My tags shows your tags for this particular content zone (for example, Java technology, Linux, WebSphere). Minhas tags mostra as suas tags para essa zona de conteúdo em particular (por exemplo, tecnologia Java, Linux, WebSphere).