Revista Front-End Magazine - Ed 02
Revista Front-End Magazine - Ed 02
Edição 02 • 2014
dos mesmos links usados na Listagem 1 e adicionar as chamadas • Adicionamos duas novas tags <meta> dentro da tag <head> da
relativas aos diretórios dos mesmos. Para esse tipo de abordagem página que se referem, respectivamente, à definição do encoding
é interessante renomear os arquivos, removendo as versões dos da página para exibição de caracteres especiais (UTF-8), e à defi-
mesmos. Você pode usar essa abordagem quando estiver traba- nição de tamanho que a tela deverá ocupar dentro do dispositivo
lhando em modo offline, ou quando desenvolver uma aplicação que a estiver exibindo;
que não tiver acesso à internet. • A divisão do corpo da página é básica e semelhante à forma
Criemos agora a estrutura básica inicial de diretórios para o como trabalhamos com tabelas (dividida em cabeçalho, corpo e
projeto, sempre dividindo os arquivos em pastas específicas para rodapé). Dessa forma, basta adicionar os elementos data-role às
o mesmo, mantendo, assim, um nível de organização mínima para div’s com seus respectivos valores e a mágica será feito. O jQuery
os projetos (Listagem 2). Mobile irá configurar a página estruturalmente com os elementos
Em seguida, crie a página index.html, tal como demonstrado específicos, bem como aplicará os efeitos e design associados de
na estrutura de diretórios e a preencha com o conteúdo visto na forma automática.
Listagem 1, adicionando também o conteúdo da Listagem 3. Vejamos como a tela ficou no seu browser no final através da
Figura 1.
Listagem 2. Estrutura de diretórios para o projeto
root
js
// Seus arquivos jquery, caso efetue o download dos mesmos
img
css
pages
index.html
<!DOCTYPE html>
<html>
<head>
<title>jQuery Mobile - Front-end Magazine</title>
<meta charset=”UTF-8”>
<meta name=’viewport’ content=’width=device-width, initial-scale=1’>
<link rel=”stylesheet” href=”http://code.jquery.com/mobile/1.4.4/
jquery.mobile-1.4.4.css” />
<script type=”text/javascript” src=”http://code.jquery.com/
jquery-1.11.0.min.js”></script>
<script type=”text/javascript” src=”http://code.jquery.com/mobile/1.4.4/ Figura 1. Tela de Boas Vindas do jQuery Mobile, redimensionada
jquery.mobile-1.4.4.js”></script>
</head>
<body> Nota
<!-- Página Principal -->
<div id=’main’ data-role=’page’> Atente que todos os elementos têm seu data-role específicos, inclusive o elemento página, que será
<div data-role=’header’> referenciado por data-role=”page”.
<h1>Olá, Seja Bem vindo(a)!</h1>
</div>
<div id=’content’ data-role=’content’>
<p>Introdução ao jQuery</p> Note que, conforme discutimos até aqui, o design responsivo
</div> é característica padrão do jQuery Mobile, tanto que você pode
<div data-role=’footer’> efetuar os testes de responsividade no seu próprio browser, re-
<h4>Revista Front-end Magazine</h4>
</div> dimensionando o mesmo. Além disso, é possível ver a aplicação
</div> do estilo padrão do jQuery Mobile, distribuído nas cores, fontes
</body> e tamanhos que o mesmo utiliza.
</html>
Temas
Com o jQuery Mobile, você também tem em mãos a possibilidade
Note que nesta listagem adicionamos algumas coisas novas. de trabalhar com os skins (temas) criados pela comunidade que
Podemos observar algumas mudanças: estão disponíveis para estilizar suas aplicações de outra forma.
• Adicionamos o elemento simples DOCTYPE no início do docu- Por padrão, o jQuery Mobile disponibiliza cinco temas básicos
mento, isso quer dizer que estamos usando HTML5 por padrão chamados de color swatches (amostra de cores), que são nomeados
na página, não somente refletido nesta declaração em específico, das letras a até a e. Por padrão, o esquema d é usado quando criado
mas também nos demais elementos dentro das páginas; uma página. É possível mudar esse tipo de configuração apenas
Página Diálogo
Um página (ou page) no jQuery Mobile é o objeto básico escrito em conjunto com o
container <div data-role=”page”> que será exibido na tela. Você pode embutir vários
Um diálogo é uma página que tem um atributo data-role=”dialog”. Você
controles HTML5 e widgets dentro de uma página. O framework jQuery Mobile
também pode carregar uma página como um diálogo adicionando o atributo
automaticamente calcula e exibe todos estes controles, fazendo deles amigáveis ao
data-rel=”dialog” ao link da página. O diálogo é estilizado de forma diferente
toque para dispositivos como tal. Sua aplicação pode ter um série de arquivos HTML
à forma como a página ganha seu design, e isso ele também aparece no meio
individuais cada um representando uma simples página, ou ele pode ter um simples
da tela abaixo da página. Ademais, o diálogo também provê um botão para
arquivo HTML contendo múltiplas div’s dentro dele. Você pode fornecer também
fechá-lo no seu cabeçalho.
outros links internos para abrir outras páginas usando Ajax em conjunto com o CSS3.
Dessa forma, conforme vimos até então, as demais páginas serão escondidas.
Listagem 6. Página secundária a ser chamada pela principal vel, dada a cada vez maior gama de browsers que aderem aos
padrões atuais.
<div id=’main’ data-role=’page’ data-theme=’a’>
<div data-role=’header’ data-theme=’b’>
• Por outro lado, apenas o primeiro carregamento será mais len-
<h1>Principal</h1> to, depois disso todos os demais serão rápidos, uma vez que as
</div> páginas já estão carregadas.
<div id=’content’ data-role=’content’>
<a href=”#” data-role=”button” data-rel=”back”>< Voltar</a>
</div> Listagem 7. Conteúdo da página inicial de multi template
<div data-role=’footer’ data-theme=’b’>
<h4>Rodapé</h4> <div id=”principal” data-role=”page”>
</div> <div data-role=”header”>
</div> <h1>Cabeçalho da #principal</h1>
</div>
<div data-role=”content”>
<a href=”#pagina2” data-role=”button” data-ajax=”false”>Ir página 2</a>
Se não funcionar, pode ser que tenha algum problema de ver- </div>
são relacionado. Dessa forma, basta adicionar o atributo data- <div data-role=”footer”>
<h4>Rodapé da #principal</h4>
ajax=”false” ao mesmo link e o efeito será aplicado normalmente.
</div>
Note também que usamos na segunda página o atributo “data- </div>
rel” com o valor back para efetuar o redirecionamento para a <div id=”pagina2” data-role=”page” data-title=”Template Multi-Página”>
<div data-role=”header”>
página anterior no histórico do browser. Isso também significa <h1>Cabeçalho da #principal</h1>
que se você tiver ambos href e data-rel no mesmo link, o jQuery </div>
Mobile irá ignorar o href e executar apenas o efeito de voltar para <div data-role=”content”>
<a href=”#” data-role=”button” data-rel=”back”>< Voltar</a>
a página anterior. </div>
Quando se trata de templates para múltiplas páginas, o jQuery <div data-role=’footer’ data-theme=’b’>
Mobile necessitará que o arquivo HTML tenha múltiplas páginas <h4>Rodapé</h4>
</div>
dentro dele mesmo. Cada página é encapsulada dentro de uma </div>
página container como uma <div data-role=”page”>. O ID da pá-
gina é usado para identificar as páginas por linking ou invocando
ações nelas. O id da página deve ser único, assim como os demais Diálogos
id’s para os demais componentes. Quando você executar a apli- Para converter uma página em um diálogo é bem simples, bas-
cação, o jQuery Mobile irá carregar todas as páginas disponíveis ta adicionar o atributo data-rel=”dialog” ao link que chamará a
no DOM e exibe a primeira página que ele encontra no HTML. mesma página. Dessa forma, teremos o modo diálogo selecionado.
A navegação entre as páginas é especificada através do mesmo Faça isso para o mesmo exemplo usando o template multipáginas
uso de âncoras visto anteriormente, e você pode personalizar criado e fazendo a modificação devida. O resultado poderá ser
esses links como botões usando o atributo data-role=”button”. observado na Figura 3.
Ao clicar em qualquer link, a navegação ocorre com as mesmas
transições CSS3, e a nova página é então exibida via Ajax. Vejamos
então como fazer isso.
Crie uma nova página HTML e nomeie-a “multi.html” e adicione
o conteúdo da Listagem 7 nela.
Note que agora adicionamos as duas páginas juntas dentro de
um mesmo arquivo HTML. Depois, mudamos as referências para
que o link apontasse agora para o id da div de página 2, ao invés
da página física como fazíamos antes. Dessa forma, temos uma
implementação mais robusta e livre de erros de Ajax e navegação.
O funcionamento será praticamente o mesmo, porém com essa Figura 3. Tela da listagem transformada em Diálogo
diferença imperceptível aos olhos do usuário final.
Em contrapartida, esse tipo de abordagem deve levar em consi- Também é possível personalizar a forma como o diálogo abre,
deração alguns fatores (dentre os quais alguns negativos): através dos efeitos de transição, comuns à maioria dos componen-
• Um template multipáginas será mais pesado em função do tes desse tipo no jQuery. Tente por exemplo adicionar os atributos
crescimento do DOM (Muitas vezes insignificante diante da a seguir e verificar o comportamento do diálogo após:
diminuição de requisições necessárias);
• A aplicação necessitará suporte JavaScript. Isso irá limitar sua data-transition=”slidedown”
escolha de plataformas alvo e você terá que ignorar algumas data-transition=”flip”
plataformas legadas. Mas isso também é algo pouco preocupá-
Listagem 10. Exemplo de função JavaScript para criar efeito de transição Mobile surjam com novas regras de transição e acabem quebrando
as suas customizadas.
<script type=”text/javascript”>
function transicaoCustomizada(nome, reverso, $para, $de) {
var diferido = new $.Deferred(); Componentes e Widgets
// Define a animação customizada
$para.width(“0”);
$para.height(“0”);
Toolbar
$para.show(); No jQuery Mobile existem duas toolbars (barra de ferramentas)
$de.animate({ width: “0”, height: “0”, opacity: “0” }, básicas, o Header (Cabeçalho) e o Footer (Rodapé). Até agora já
{ duration: 750 },
{ easing: ‘easein’ }
abordamos os dois nos exemplos utilizados, mas onde e para o que
); eles podem ser usados? O que o jQuery consegue abordar a mais
$para.animate({ width: “100%”, height: “100%”, opacity: “1” }, em relação a essas áreas? O header basicamente sempre exibe o
{ duration: 750 },
{ easing: ‘easein’ } nome da página, o título do cabeçalho, mas pode ser usado para
); controlar também a navegação através do navbar. O footer pode
// Padroniza o template do jQuery Mobile ser usado para várias coisas, tais como incluir botões e formulários
classeReversa = reverso ? “ reverso” : “”;
classeView = “ui-mobile-viewport-transitioning viewport-” + nome; de controle e pode ser customizado para as necessidades mais
$para.add($de).removeClass(“out in reverso “ + nome); específicas. Ele pode ser usado como controle de navegação tam-
if ( $de && $de[0] !== $para[0] ) { bém, assim como para exibir informações relacionadas à empresa,
$de.removeClass($.mobile.classePaginaAtiva);
} copyright, etc.
$para.parent().removeClass(classeView); Vejamos o código presente na Listagem 11. Ele exemplifica um
diferido.resolve(nome, reverso, $para, $de);
bom uso da toolbar para controlar a navegação de páginas.
$para.parent().addClass(classeView );
if ($de) {
$de.addClass(nome + “ out” + classeReversa);
} Listagem 11. Exemplo de função JavaScript para criar efeito de transição
$para.addClass($.mobile.classePaginaAtiva + “ “ + nome + “ in” + classeReversa);
return diferido.promise(); <div id=”principal” data-role=”page”>
} <div data-role=”header”>
// Registra a transição customizada <h1>Galeira de Fotos</h1>
$.mobile.transitionHandlers[“slide-sumir”] = transicaoCustomizada; </div>
</script> <div data-role=”content”>
<img src=”../img/logo-devmedia.png” />
<br>DevMedia - Cursos e Treinamentos Online
<br><a href=”#photo” data-role=”button” data-inline=”true”>
Além disso, altere também o atributo data-transition para o View full screen</a>
</div>
novo valor: slide-sumir. Após o teste, você verificará que o efeito <div data-role=”footer”>
mudou para uma mistura de slide para a esquerda/direita com <h4>Rodapé da Galeria</h4>
um efeito de sumiço. Todo esse processo foi possível graças à </div>
</div>
sobrescrita do objeto Deferred, com a configuração da altura <div id=”photo” data-role=”page” data-fullscreen=
e largura do mesmo, possibilitando que as mesmas pudessem ”true” data-add-back-btn=”true”>
ser aplicadas ao efeito de animação em conjunto com a função <div data-role=”header” data-position=”fixed” >
<h1>DevMedia - Cursos e Treinamentos Online</h1>
show() do próprio jQuery. Note que as configurações de duração </div>
das animações são essenciais para definir o escopo do efeito, este <div data-role=”content”>
<img src=”../img/logo-devmedia.png” width=”60%”
que pode ser alterado à vontade pelo desenvolvedor de forma a
style=”padding: 120px; margin: 0 auto;”/>
alcançar maiores níveis de personalização. </div>
Uma vez terminada a transição, o código deve garantir que a <div data-role=”footer” data-position=”fixed”>
Data: 10/10/2010
página correta esteja ativa. Logo após, é necessário chamar a
</div>
função diferido.resolve() e retornar a função promise(). Final- </div>
mente, é importante registrar a transição customizada de forma
a poder associá-la ao atributo jQuery correspondente. A função
transitionHandlers() se encarregará disso. O que fizemos foi basicamente simular uma galeria de fotos, com
Não existe nenhuma regra básica que defina qual das duas uma imagem apenas (verifique os arquivos de download ou use
implementações é melhor, isso vai depender da forma como você qualquer imagem). Criamos uma página simples, com navegação
está trabalhando baseada nos padrões do projeto e/ou restrições multi-página, nenhuma novidade. Detalhes são os novos atributos
de clientes. Usar CSS3 é mais intuitivo e fácil para a maioria usados na página referente à imagem em tamanho aumentado,
dos profissionais que trabalham com web, além de mais fácil de que conta com atributos como data-add-back-btn, que concede à
manter e não requerer conhecimentos de lógica de programação. div a função de controladora de navegação. Além disso, na segun-
Além disso, é provável que no futuro novas versões do jQuery da tela é possível analisar a visualização do rodapé somente no
final da página, conferindo um ar de aplicação mais trabalhada, ao Listagem 12. Footer personalizado para exemplo da Listagem 11
contrário do padrão que é sempre exibir o footer ao final de cada
<div data-role=”footer” data-position=”fixed” class=”ui-bar”>
página e seu respectivo conteúdo. Veja na Figura 5 o resultado
<fieldset class=”ui-grid-a”>
do exemplo da Listagem 11. <div class=”ui-block-a” data-role=”fieldcontain”>
Vários são os tipos de implementação possíveis com a toolbar, <label for=”notaSlider”>Que nota você dá (1-10)?</label>
desde a implementação de tabulação dando efeitos mais divisórios <input type=”range” name=”notaSlider” id=”notaSlider” value=”5”
min=”1” max=”10”/>
às telas, até a criação de cabeçalhos customizados com a inclusão
</div>
de botões de controle, personalização de cores, CSS, imagens, etc. <div class=”ui-block-b”>
E em relação ao rodapé, pode ser customizado de igual forma. <div data-role=”fieldcontain”>
Basta substituir a div de footer da Listagem 11 pelo conteúdo <fieldset data-role=”controlgroup” data-type=”horizontal”>
<legend>Compartilhe:</legend>
ilustrado na Listagem 12 e teremos um rodapé totalmente per-
<input type=”radio” name=”arquivoCompartilhado”
sonalizado. id=”arquivoCompartilhadoNinguem”
Veja o resultado ilustrado na Figura 6. value=”arquivoCompartilhado-1” checked=”checked” data-theme=”c”/>
<label for=”arquivoCompartilhadoNinguem”>Ninguém</label>
<input type=”radio” name=”arquivoCompartilhado”
id=”arquivoCompartilhadoAmigos”
value=”arquivoCompartilhado-2” data-theme=”c”/>
<label for=”arquivoCompartilhadoAmigos”>Amigos</label>
<input type=”radio” name=”arquivoCompartilhado”
id=”arquivoCompartilhadoPublico”
value=”arquivoCompartilhado-3” data-theme=”c”/>
<label for=”arquivoCompartilhadoPublico”>Público</label>
</fieldset>
</div>
</div>
</fieldset>
</div>
Figura 6. Resultado de footer personalizado na primeira coluna tem como classe a ui-block-a que define que
esse conteúdo deve estar posicionado na primeira coluna.
Essa implementação já trouxe mais novidades sobre o uso de Para criar o slider basta criar um input de formulário comum e
toolbar. A classe ui-bar, adicionada à div footer, já nos informa tipá-lo como “range”, informando seus limites nos atributos min
que faremos configurações além das já padrões existentes, possi- e max. Finalmente, para criar os botões de seleção toggle, basta
bilitando a adição de controles à mesma. Em seguida, adicionamos criar um fieldset com o data-role configurado para controlgroup e
a classe ui-grid-a que nos habilita a usar um fieldset com um inputs para cada uma das opções, não esquecendo de referenciá-
layout de duas colunas. A div container com a role fieldcontain las com o mesmo atributo name.
Botões Formulários
Existe uma infinidade de ações que podem ser efetuadas dentro A tag comum da HTML, <form>, usada para lidar com a comuni-
de uma aplicação, assim como a necessidade de se criar os mais cação HTTP da sua aplicação dinâmica é totalmente encapsulada
diversos tipos de botões que atendam a tais comandos. O jQuery pelo jQuery Mobile de forma a torná-la amigável ao toque e execu-
Mobile possibilita o uso dos elementos botões como links, contro- tar em diversos dispositivos de forma responsiva. Um formulário
ladores de navegação, listas, controladores de formulários, dentre pode ter múltiplos controles listados por padrão verticalmente e
outros. Além disso, várias são as formas que podem ser exibidos, você pode agrupá-los usando um fieldset com o data-role setado
dentro dos limites de estilo estipulados pelo framework. para controlgroup, conforme demonstrado anteriormente. Além
Vejamos o exemplo demonstrado na Listagem 13, bem como disso, ainda pode contar com todo o poder do Ajax para fazer
seu resultado na Figura 7. todo o processo de comunicação com o servidor.
Substitua o conteúdo da div content pelo apresentado na Mas talvez uma das funcionalidades mais interessantes desse
Listagem. O data-role=collapsible possibilita facilmente a criação tipo de recurso seja a facilidade de validar formulários usando o
de listas selecionáveis e em efeito sanfona. Ao fazer uso desse re- próprio jQuery Mobile. Em conjunto com a HTML5 ele consegue
curso, os ícones de mais/menos são automaticamente importados se valer de validações padrão de página, assim como criar suas
pelo jQuery. próprias. Dê uma olhada na Listagem 14.
...
<script type=”text/javascript”>
$(document).ready(function() {
$(‘#form’).submit(function() {
var len = $(‘#comentario’).val().length;
if ( len < 10 || len > 100 ) {
$(‘#erro’).text(‘Comentário com tamanho inválido!’).show().fadeOut(5000);
return false;
} else
return true;
});
});
</script>
</head>
<body>
<!-- Página Principal -->
<div id=”principal” data-role=”page”>
<div data-role=”header”>
<h1>Cabeçalho</h1>
</div>
<div data-role=”content”>
<form id=’form’ action=’#’ method=’post’>
<div data-role=’fieldcontain’>
Figura 7. Exemplo de lista em efeito sanfona <label for=’nome’>Nome</label>
<input id=’nome’ name=’nome’ type=’text’ required placeholder=
’Digite seu Nome’ />
Listagem 13. Exemplo de uso de botões como listas de seleção no jQuery Mobile </div>
<div data-role=’fieldcontain’>
<div data-role=”content”> <label for=’email’>Email</label>
<div data-role=”collapsible” data-collapsed=”false” data-theme=”a” <input id=’email’ name=’email’ type=’email’ required placeholder=
data-content-theme=”a”> ’Digite seu Email’ />
<h3>Cabeçalho #1</h3> </div>
Corpo #1 <div data-role=’fieldcontain’>
</div> <label for=’comentario’>Comentários</label>
<div id=”collapser” data-role=”collapsible” data-collapsed=”false” <textarea id=’comentario’ name=’comentario’ required
data-theme=”b” placeholder=’Digite seus comentários <Mínimo 10/Máximo 50>’></textarea>
data-content-theme=”b”> </div>
<h3>Cabeçalho #2</h3> <div id=’erro’ style=’color: #f00’></div>
Corpo #2 <input type=’submit’ data-transition=’pop’ value=’Enviar’/>
</div> </form>
<div id=”collapser” data-role=”collapsible” data-collapsed=”true” data-theme=”e” </div>
data-content-theme=”e”> <div data-role=”footer”>
<h3>Cabeçalho #3</h3> <h4>Rodapé</h4>
Corpo #3 </div>
</div> </div>
</div> </body>
Página de Loading
Por padrão, o jQuery Mobile exibe uma animação com o tema a
sem nenhum texto quando tenta carregar uma página. Se aconte-
cer quaisquer erros no meio do caminho, então a página para de
processar e uma mensagem “Error Loading Page” é exibida com
o tema e. Com o jQuery Mobile, é possível, com poucas linhas
de código, sobrescrever as chamadas padrão, por um conjunto
de status preestabelecidos que podem controlar as mensagens a
serem exibidas no lado cliente. Veja na Listagem 16.
Temas
O framework jQuery Mobile provê um sistema leve para tema-
Figura 9. Página de formulário exemplo com campos selecionados tizar componentes, que suporta muitas propriedades CSS3, como
Links:
Existem muitas outras features acerca do jQuery Mobile que
não serão cobertas aqui, até mesmo para não fugir do foco, que Lista de dispositivos e plataformas suportados pelo jQuery Mobile
é de fato apresentar a tecnologia aos que ainda não conhecem www.jquerymobile.com/gbs/
o poder que ela fornece ao desenvolvimento de aplicações web
Página oficial do Notepad++
mobile. O jQuery Mobile nasceu com o intuito de unir o poder do
www.notepad-plus-plus.org/
já famoso framework JavaScript, o jQuery, ao recente e cada vez
mais requisitado mundo web mobile, de forma a fornecer suporte, Site do ThemeRoller jQuery Mobile.
componentes de fácil uso e modificação, além de uma manutenção www.themeroller.jquerymobile.com/
• Ready for real-time: O Node.js ficou popular graças aos seus ou mesmo por simples chamadas jQuery Ajax. Com o Node.js,
frameworks de interação real-time entre cliente e servidor. O você pode simplesmente expor seus objetos JSON com uma API
SockJS, Socket.IO, Engine.IO são alguns exemplos disso. Eles são REST para o cliente a consumir. Além disso, você não precisa se
compatíveis com o recente protocolo WebSockets e permitem tra- preocupar com a conversão entre JSON e tudo aquilo que for ler
fegar dados através de uma única conexão bidirecional, tratando ou escrever em seu banco de dados (se estiver usando MongoDB).
todas as mensagens através de eventos JavaScript. Em suma, você pode evitar a necessidade de múltiplas conversões
• Big players: LinkedIn, Wallmart, Groupon, Microsoft e Paypal usando um formato de serialização de dados uniforme em todo
são algumas das empresas usando Node.js atualmente, no Brasil o cliente e servidor de banco de dados.
conheço algumas empresas por exemplo: Agendor, Sappos, Ne-
oassist e tem mais um monte de outras empresas e projetos (veja Entradas de Filas
na seção Links). Se você está recebendo uma grande quantidade de dados simul-
tâneos, o banco de dados pode se tornar um gargalo. O Node.js
Onde posso usar o Node.js? pode facilmente lidar com as próprias conexões simultâneas. Mas
porque o acesso a bancos de dados é uma operação bloqueante, nos
Chats depararemos certamente com problemas. A solução é reconhecer
Um chat é o mais típico exemplo de aplicação multi-usuário o comportamento do cliente antes de os dados serem realmente
em tempo real. Desde IRC até muitos protocolos proprietários gravados na base de dados.
e abertos sobre portas não-padrão, até mesmo a habilidade de Com essa abordagem, o sistema mantém a sua capacidade de res-
implementar tudo hoje no Noje.js com websockets rodando sobre posta sob uma carga pesada, o que é particularmente útil quando
a mesma porta padrão 80. o cliente não precisa de confirmação firme de uma gravação de
A aplicação de chat é realmente é um ótimo exemplo de ser dados bem-sucedida. Exemplos típicos incluem: o registro ou gra-
usada com Noje.js: é leve, tem alto tráfico de dados, porém exige vação de dados de rastreamento de usuário, com processamento
pouco processamento/computação e que executa dentre vários em lotes e não utilizados até mais tarde; bem como operações que
dispositivos. Além de tudo, é bem simples, ótimo para os de- não precisam ser refletidas instantaneamente (como a atualização
senvolvedores que estão iniciando o aprendizado na tecnologia, de um count ‘Likes’ no Facebook), onde a consistência eventual
cobrindo a maior parte dos paradigmas usados pela linguagem. (tantas vezes usada no mundo NoSQL) é aceitável.
Basicamente, uma aplicação desse tipo funciona dentro de um Os dados são colocados em fila por algum tipo de cache ou
domínio de website já pronto onde as pessoas podem ir e efetuar enfileiramento de mensagens de infraestrutura (por exemplo,
a troca de mensagens entre si conectados por uma estrutura de RabbitMQ, ZeroMQ) e digerido por um processo de banco de
programação e redes. No lado do servidor, temos uma aplicação dados separado em lotes e escrita, ou computação intensiva de
simples que implementa duas coisas: serviços de processamento de back-end, escrito em uma plata-
• Uma requisição GET que serve a página web contendo ambas forma de melhor desempenho para tais tarefas. Comportamento
mensagem e botão de enviar para inicializar uma nova entrada semelhante pode ser implementado com outras linguagens/
de mensagem; frameworks, mas não no mesmo hardware, com o mesmo alto
• Websockets que escutam por novas mensagens emitidas pelos rendimento mantido.
seus clientes.
Fluxo de Dados
No lado cliente nós temos uma página HTML com uma série de Em plataformas mais tradicionais da web, solicitações e respostas
handlers configurados, um para o botão de Envio, que seleciona HTTP são tratadas como eventos isolados; na verdade, eles são
a mensagem e a envia para o websocket, e outro que escuta por realmente streams. Esta observação pode ser utilizada no Node.
mensagens que estão chegando no cliente. Obviamente, este é um js para construir alguns recursos interessantes. Por exemplo,
modelo simples e básico, mas que baseia os demais em variância é possível processar arquivos enquanto eles ainda estão sendo
às suas complexidades. carregados, uma vez que os dados vêm no meio de um stream
e podemos processá-los de forma online. Isso poderia ser feito
API sobre um objeto DB para áudio em tempo real ou codificação de vídeo e proxy entre
Embora o Node.js realmente brilhe com aplicações em tempo as diferentes fontes de dados.
real, é natural ter que expor os dados a partir de um objeto de ban-
co de dados (MongoDB, por exemplo). Dados JSON armazenados Proxy
permitem que o Node.js funcione sem a diferença de impedância O Node.js é facilmente utilizado como um proxy do lado do servi-
e conversão de dados. Por exemplo, se você estiver usando Rails, dor, onde ele pode lidar com uma grande quantidade de conexões
você deve converter JSON para modelos binários e em seguida, simultâneas de uma maneira non-blocking. É especialmente útil
expô-los de volta como JSON sobre o HTTP quando os dados são para proxys de diferentes serviços com diferentes tempos de res-
consumidos por frameworks como o Backbone.js, Angular.js, etc., posta ou a coleta de dados a partir de vários pontos de origem.
Em sistemas Linux ou MacOS, basta acessar com um editor de • npm remove -g nome-do-modulo: desinstala um módulo global;
texto qualquer e em modo super user (sudo) o arquivo .bash_pro- • npm update nome-do-modulo: atualiza a versão do módulo;
file ou .bashrc e no final do arquivo adicione a seguinte linha • npm update -g nome-do-modulo: atualiza a versão do módulo
de comando: global;
• npm -v: exibe a versão atual do npm;
export NODE_ENV=’development’ • npm adduser nome-do-usuario: cria uma conta no npm através
do site do NPM (ver seção Links);
Clique com botão direito no ícone Meu Computador e selecione • npm whoami: exibe detalhes do seu perfil público npm (é ne-
a opção Propriedades e no lado esquerdo da janela clique no link cessário criar uma conta antes);
Configurações avançadas do sistema. Na janela seguinte, acesse • npm publish: publica um módulo no site do npm (é necessário
a aba Avançado e clique no botão Variáveis de Ambiente…. ter uma conta NPM antes).
Agora no campo Variáveis do sistema clique no botão Novo… e
no campo nome da variável digite NODE_ENV e no campo valor Entendendo o package.json
da variável digite development, tal como demonstrado na Figura 1. Todo projeto Node.js é chamado de módulo, mas o que é um
Após finalizar essa tarefa, reinicie seu computador para carregar módulo? No decorrer da leitura, perceba que vamos discutir muito
essa variável automaticamente no sistema operacional. sobre o termo módulo, biblioteca e framework, e, na prática, eles
possuem o mesmo significado. O termo módulo surgiu do conceito
Rodando o Node.js de que o JavaScript trabalha com uma arquitetura modular. E todo
Para testarmos o ambiente, executaremos o nosso primeiro pro- módulo é acompanhado de um arquivo descritor, conhecido pelo
grama de Hello World. Abra seu terminal ou prompt de comando e nome de package.json.
execute o comando node. Este comando vai acessar o modo REPL Este arquivo é essencial para um projeto Node.js. Um package.
(Read-Eval-Print-Loop) que permite executar códigos JavaScript json mal escrito pode causar bugs ou impedir o funcionamento
diretamente pela tela preta. Agora digite console.log(“Hello World”) correto do seu módulo, pois ele possui alguns atributos chaves
e tecle ENTER para executá-lo na hora (Figura 2). que são compreendidos pelo Node.js e NPM.
Na Listagem 1 temos um package.json que contém os principais
atributos para descrever um módulo.
{
“name”: “meu-primero-node-app”,
“description”: “Meu primeiro app Node.js”,
“author”: “Caio <caio@email.com>”,
“version”: “1.2.3”,
“private”: true,
Figura 2. Hello World em Node.js via terminal “dependencies”: {
“modulo-1”: “1.0.0”,
“modulo-2”: “~1.0.0”,
“modulo-3”: “>=1.0.0”
Gerenciando dependências e módulos usando o NPM },
Assim como o RubyGems do Ruby ou o Maven do Java, o Node “devDependencies”: {
.js também possui seu próprio gerenciador de pacotes, ele se “modulo-4”: “*”
}
chama NPM. Ele se tornou tão popular pela comunidade, que foi }
a partir da versão 0.6.X que foi integrado no instalador do Node
.js, tornando-se o gerenciador padrão desta plataforma. Isto sim-
plificou a vida dos desenvolvedores na época, pois fez com que Com esses atributos, você já descreve o mínimo possível o que
diversos projetos se convergissem para esta plataforma até os dias será sua aplicação. O atributo name é o principal. Com ele, você
de hoje. Utilizar o NPM é muito fácil, então vejamos os comandos descreve o nome do projeto, nome pelo qual seu módulo será
principais para que você tenha noções de como usá-los: chamado via função require(‘meu-primeiro-node-app’). Em
• npm install nome-do-modulo: instala um módulo no projeto; description, descrevemos o que será este módulo. Ele deve ser
• npm install -g nome-do-modulo: instala um módulo global; escrito de forma curta e clara, fornecendo um resumo do mó-
• npm install nome-do-modulo --save: instala o módulo no pro- dulo. O author é um atributo para informar o nome e e-mail do
jeto, atualizando o package.json na lista de dependências; autor. Utilize o formato Nome <email> para que sites como npm
• npm list: lista todos os módulos do projeto; reconheça corretamente esses dados. Outro atributo principal
• npm list -g: lista todos os módulos globais; é o version, com o qual definimos a versão atual do módulo.
• npm remove nome-do-modulo: desinstala um módulo do projeto; É extremamente recomendado que tenha este atributo, se não
Listagem 6. Emulando o comportamento das funções exports usando module. módulos. O text_sync.js, por ser um código síncrono, invocou
exports. chamadas de I/O bloqueantes e gerou o gráfico da Figura 3.
module.exports = function() {
Repare no tempo de execução, o text_sync.js hipoteticamente
return { demorou 1000 milissegundos, isto é, 200 milissegundos para
hello: function(msg) { cada escrita de arquivo. Já em text_async.js foram criados os
console.log(msg);
} arquivos de forma totalmente assíncrona, ou seja, as chamadas
}; de I/O eram não-bloqueantes, e isso permitiu escrever arquivos
}; em paralelo, como na Figura 4.
var fs = require(‘fs’);
var leituraSync = function(arquivo){ Veja a pequena, porém significante, diferença de tempo entre as
console.log(“Fazendo leitura síncrona”); duas funções de leitura realizada na máquina (Figura 5).
var inicio = new Date().getTime();
fs.readFileSync(arquivo);
var fim = new Date().getTime();
console.log(“Bloqueio síncrono: “+(fim - inicio)+ “ms”);
};
module.exports = leituraSync;
Evitando Callbacks Hell seu código. Em resumo Generators é um recurso que permite es-
De fato, vimos o quanto é vantajoso e performático trabalhar de crever funções assíncronas sem callbacks, utilizando uma sintaxe
forma assíncrona, porém, em certos momentos, inevitavelmente de código síncrono, retornando valores da função em um array que
implementaremos diversas funções assíncronas, que serão enca- representa os possíveis parâmetros de uma função callback.
deadas uma na outra através de suas funções callback. No código
da Listagem 12 vemos um exemplo desse caso.
Listagem 13. Minimizando callback hell declarando funções em variáveis.
Evitando Callbacks Hell usando Generators Agora vamos a implementação. A seguir temos dois códigos que
Muitos recursos interessantes estão surgindo para a nova especifi- fazem a mesma tarefa: ambos criam um arquivo de texto, escreve
cação JavaScript conhecida por ECMAScript6 ou ES6, o Generators nele um timestamp e, no fim, excluir o próprio arquivo gerado.
é um deles e seu objetivo principal é minimizar callback hell em O código da Listagem 14 utiliza vários call-backs.
var fs = require(“fs”);
var time = new Date().getTime();
Autor
fs.writeFile(“log.txt”, time, function(err) { Caio Ribeiro Pereira
console.log(“Iniciando log”);
fs.readFile(“log.txt”, function(err, text) {
caio.ribeiro.pereira@gmail.com
console.log(“Timestamp: “ + text); É um Web Developer, com experiência nessa sopa de letrinhas:
fs.unlink(“log.txt”, function() { Node.js, Meteor, JavaScript, CSS, Ruby, Java, MongoDB, Redis,
console.log(“Log finalizado”); LevelDB, Agile, XP e TDD. Bacharel em Sistemas de Informação, mantém
});
ativamente o blog Underground WebDev abordando assuntos sobre Node
});
}); .js, JavaScript, apaixonado por programação, tecnologias e seriados. Moderador do Meteor
Brasil e participante das comunidades NodeBR e DevInSantos. Desde 2011 palestra nos
Listagem 15. Implementando Generators para minimizar callback hell. eventos DevInSantos e Exatec, abordando temas atuais sobre Node.js e JavaScript. Autor
dos livros da Casa do Código: Aplicações web real-time com Node.js e Meteor - Criando
var fs = require(‘fs’);
var suspend = require(‘suspend’);
aplicações web real-time com JavaScript.
var resume = suspend.resume;
var time = new Date().getTime();
suspend(function* (){
yield fs.writeFile(“log.txt”, time, resume()); Links:
console.log(“Iniciando log”);
var text = yield fs.readFile(“log.txt”, resume()); Blog Underground WebDev
console.log(“Timestamp” + text); www.udgwebdev.com/
yield fs.unlink(“log.txt”, resume());
console.log(“Log finalizado”); Ruby EventMachine
})();
www.rubyeventmachine.com/
Python Twisted
Simplesmente o encadeamento de callbacks diminuiu com Gene- www.twistedmatrix.com/
rators, e isso deixou seu código mais limpo e menos complexo.
Google Groups NodeBR
De fato o Node.js é uma excelente opção para desenvolvedores www.groups.google.com/forum/#!forum/nodebr/
front-end conhecerem um pouco sobre back-end sem precisar
aprender uma nova linguagem, afinal esta plataforma o mesmo Ja- Site oficial do Node.js
vaScript client-side, apenas com alguns detalhes diferentes. Outro www.nodejs.org/
detalhe importante é sobre as vantagens das funções assíncronas Wiki de instalação do Node.js
e seu I/O não-bloqueante. Afinal como vimos em um benchmark, www.github.com/joyent/node/wiki/Installing-Node.js-via-package-manager/
testamos uma ação de I/O simples que fazia uma leitura de um
Site oficial do NPM
único arquivo de mais ou menos 7 MB e o tempo de bloqueio foi
www.npmjs.org/
muito menor do que uma leitura bloqueante.
N
o advento das tecnologias front-end e da utili- tecnologias front-end, aliado aos processos e boas práticas que cada
zação de novos padrões de desenvolvimento, vez mais se fazem necessários de serem aplicados a esse meio, trazem
como a HTML5, novas fórmulas e conceitos à tona a real necessidade de unir ambos universos: testes de unidade
foram criados de forma a suprir a cada vez maior ne- ao desenvolvimento client side.
cessidade de atender a todos os diversos cenários de Este artigo explicita isso trazendo a primeira de duas partes sobre
software. o desenvolvimento de testes unitários usando JavaScript. Veremos
O uso de testes unitários para verificar se um módulo todos os conceitos, práticas e metodologias que norteiam o que há
ou unidade do código está funcionando corretamente de mais recente no assunto, assim como modelos básicos de como
como esperado já não constitui nenhuma novidade. eles se aplicam ao uso do JavaScript e seus frameworks.
Afinal, tal conceito foi outrora introduzido na comu-
nidade de desenvolvedores por Kent Beck, através de
linguagens mais antigas como Smalltalk, C, C++ e até mais famosos dos testes, desde os conceitos, teorias e boas práticas,
mesmo no Java. Porém, se analisarmos bem o termo é até a escolha das ferramentas adequadas para tal.
sempre extremamente associado às linguagens que se
constituem “linguagens server side”, isto é, executam Testes unitários
apenas do lado do servidor, muitas com processos bem Antes de entender quais divisões ou aplicações de testes diversas
definidos de compilação, interpretação, plataforma existem no universo de programação, é importante antes entender
integrada ou multiplataforma, etc. Até mesmo uma o que é, de fato, um teste unitário. O próprio nome já consegue
rápida busca na web pelo termo irá remeter em inúme- nos dizer muito acerca desse procedimento: um teste ou mais
ras bibliografias, blogs e sites sobre o assunto com foco testes que verificam unidades de composição de, no nosso caso,
voltado para esse tipo de linguagem. sistemas diversificados.
É interessante notar que até mesmo o conceito foi Se procurarmos mais formalmente, veremos algumas definições
desenvolvido e evoluído sobre esse tipo de linguagem. mais elaboradas: “Em programação de computadores, teste unitá-
Diante disso, este artigo visa construir uma ideia adap- rio ou teste de unidade constitui um método de teste de software
tada dos testes unitários para o universo front-end, pelo qual unidades individuais de código fonte, configuradas com
especificamente focado no uso e construção dos exem- um ou mais módulos de programas de computador juntos com
plos em cima da linguagem de script mais famosa do dados de controle associados são testados para determinar se eles
mercado: JavaScript. Logo, aqui abordaremos os tópicos estão aptos para o uso final.”
e está conforme. Existem vários outros tipos de integrações que dada a necessidade do outro ambiente para tal teste. Além disso,
podem ser verificadas via testes de integração, tais como código vale frisar a importância do teste bem feito, o que quase sempre
que se comunica com web services, que efetuam operações de significará ter testes para ambas as situações onde o teste funciona
escrita e leitura sobre arquivos, que verificam a comunicação e quebra.
assíncrona da implementação de filas e JMS, ou até mesmo que
verificam o funcionamento de mensagens enviadas via sockets, Tipos de processos
por protocolos HTTP, etc. Além de analisar os tipos de testes que existem, é importante
• O teste de sistema é uma expressão usada para designar se o também saber a diferença entre estes e os diferentes tipos de
funcionamento do sistema como um todo está procedendo. O foco, processos de teste que existem e que envolvem todo esse ciclo.
portanto, deixar de ser a unidade (teste unitário) assim como a Essas famosas “práticas de desenvolvimento” se dividem em
integração (teste de integração) e passa agora a focar na junção três nomes tão famosos quanto: TDD - Test-Driven Development,
de todas as pequenas partes do sistema constituindo o conjunto BDD - Behavior-driven Design e DDD - Domain-driven Design
completo de tarefas a serem executadas pelo sistema. Também (Figura 1).
chamado de “teste de caixa preta”, esse tipo de teste lida com a
averiguação de tudo, desde o banco de dados, métodos e classes
até as integrações. Para algumas vertentes, os testes de aceitação,
que ficaram famosos com o advento do desenvolvimento ágil e
são caracterizados pela aceitação ou não do time ágil, são no final
testes de sistema.
Agora se executarmos os testes, poderemos ver que todos eles • Análises do tipo up-front, design e planejamento têm um retorno
passarão com sucesso. Isso é como o TDD funciona. cada vez menor.
Ao utilizar esse tipo de processo, alguns benefícios se tornam
claros logo já, como o baixo acoplamento com uma série de testes O primeiro princípio base está solidificado sobre a user story,
que comprovam o seu comportamento. Um dos resultados mais escrita conforme mostramos acima, de uma maneira não-técnica.
visíveis do TDD é que os testes desenvolvidos sobre o mesmo Essa noção de linguagem natural segue muitos frameworks BDD,
fornecem uma espécie de documentação informal do sistema, mesmo em um nível de código. O segundo princípio base de adi-
conforme falamos anteriormente, ditando não só o que o sistema cionar valor de negócio pode ser visto na história como a parte
pode fazer mas também o que não deve fazer (e é aí onde entram “Que então [beneficia]”.
os testes falhos). Além disso, pelo simples fato de tudo isso estar O terceiro princípio tem o mesmo significado do processo TDD.
integrado ao software, podemos dizer que o produto teste nunca Um design upfront é feito da forma mais pequena o possível, mesmo
ficará ultrapassado, o que difere das atividades de escrita de que o design esteja indo por além do teste e refactoring.
documentação e/ou comentar código. Juntos os princípios ajudam os desenvolvedores a mitigar os riscos
Alguns outros prós se fazem mais sutis, porém importantes, no de criar recursos extra ou de criar funcionalidades de forma errada.
ciclo de vida do software bem como na adesão de produtividade Até hoje, o BDD não tem recebido tanta atenção na comunidade de
ao projeto, tais como a diminuição do tempo usado para depurar pesquisas, mas isso provavelmente tenha relação com a sua idade
código, o que implicará no lucro de tempo e, consequentemente, e sua origem de método de pesquisa, o TDD, que ainda é alvo de
dinheiro. Tudo isso é possível pelo simples fato de o TDD informar muito contradição.
a quem o usa sempre que um erro ocorrer no sistema, diminuindo Ok, podemos dizer que entendemos o que é BDD. Mas, é ainda
o tempo de depuração e deixando-a menos custosa. brota algumas clássicas e famosas confusões. Alguns dizem que
o BDD é similar ao TDD (fato que justifica ainda mais o porquê
BDD de uma ter surgido a partir da outra), alguns outros irão dizer
O BDD foi primeiramente introduzido por Dan North no seu que é o mesmo que TDD porém com alguns guidelines melho-
artigo “Instrução ao BDD” e é uma metodologia que evoluiu res, ou ainda que são abordagens totalmente diferentes para o
das práticas de TDD. BDD é uma técnica de design sobre user desenvolvimento.
stories, que deve ser escrita em uma linguagem inteligível por Independente da definição, isso não importa muito. A principal
não-programadores. Isso possibilita que todos os envolvidos no coisa a se saber é que o “BDD é feito para eliminar problemas que
projeto, executivos, testers, usuários e outros funcionários a se o TDD venha a causar”.
tornarem mais ativos no desenvolvimento. As user stories são Em contraste ao TDD, o BDD consiste em escrever comportamen-
centradas na seguinte sintaxe: to e especificação que então dirija o desenvolvimento do nosso
software. Comportamento e especificação devem ser vistos como
Título (uma linha descrevendo a história) similares para testes mas a diferença é deveras importante.
Narrativa: Vejamos, então, novamente o problema descrito na seção anterior,
Como um(a) [regra] quando falávamos sobre TDD, sobre escrever uma função para
Eu quero [funcionalidade] calcular o valor fatorial de um número (Listagem 4).
Que então [beneficia] A principal diferença é somente a escrita. O BDD usa um estilo
mais verboso então isso pode ser lido quase como uma sentença.
Critério de aceitação: (apresentado como cenários) Isso é o mesmo que dizer que o BDD elimina problemas que o
TDD venha a causar. A habilidade de ler seus testes como uma
Cenário 1: Título sentença é uma maneira mais cognitiva de como podemos pensar
Dado um [contexto] e [mais alguns contextos]... acerca dos mesmos testes. O argumento atua no “se você pode ler
Quando [evento] seus testes fluidamente, você naturalmente irá escrevê-los de uma
Então [saída] e [outras saídas]... forma melhor e mais compreensiva”.
Apesar de esse exemplo ser muito simples e não ilustrar totalmente
Como ocorre com o TDD, BDD é uma técnica de design outside- isso, os testes BDD devem estar focados nas funcionalidades, e
in. No BDD as histórias são escritas primeiro, então verificadas e não nos resultados (essa também é uma das principais diferenças
priorizadas pelos usuários e envolvidos não-técnicos. O progra- entre os dois). Frequentemente, você ouvirá que o BDD existe para
mador então cria o código para atender às histórias descritas. Em ajudar no design do software, e não testá-lo como o TDD é suposto
BDD, existem três princípios-base: de fazer.
• Negócio e tecnologia devem referenciar o mesmo sistema da
mesma forma; BDD
• Qualquer sistema deve ter um valor identificado e variável DDD, ou Domain-Driven Development, é um conjunto de padrões
para o negócio; e métodos que focam na elaboração de aplicações que se caracte-
É comum, por exemplo, que desenvolvedores façam os seus C# ou PHP, sendo considerada referência como linguagem, o
testes à medida que se vai desenvolvendo o código, à medida que JavaScript ainda tem muito a evoluir junto a suas companheiras
todos as “unidades” requeridas para implementar o caso de uso de lado (client side).
são feitas. Ao mesmo tempo, você estará constantemente mudan- É muito fácil, e comum, ignorar testes unitários quando se em-
do funções sobre esse código, refatorando e abstraindo também barca em um projeto de grande escala que faz uso de JavaScript.
algumas partes, e tentando se antecipar ao que possivelmente irá Muitas vezes motivados pelo grande costume de desenvolver
causar perda de tempo durante esse processo. testes apenas no lado do servidor, uma vez que muitas das
Consideremos o seguinte cenário: “como um usuário, ao logar regras de validação são sempre duplicadas em ambos os lados
na aplicação você será levado para uma tela de menu principal”. cliente e servidor. Porém, a necessidade de construir testes de
Como podemos quebrar essa operação genérica em unidades? unidade para JavaScript é tão real quanto com quaisquer outras
Imediatamente podemos selecionar o “login de formulário” linguagens. As ferramentas e procedimentos de testes unitários,
como uma implementação desse caso de uso que pode ser por sua vez, não são tão claros para JavaScript quanto para as
testada, e iremos adicionar algumas linhas de código de teste demais linguagens, o que acaba por construir uma imagem
requeridas para implementar essa funcionalidade corretamente mais defensiva dos programadores para com o teste usando a
(Listagem 5). linguagem de script.
O JavaScript vem de uma longa caminhada contra muitos con-
Listagem 5. Exemplo de divisão dos passos para realizar o teste unitário ceitos, e anticonceitos. Houve um tempo onde ele era facilmente
descartado, talvez adequado para validações não-críticas, mas
describe(‘login usuário’, function() {
// crítico
não mais que isso. Ao longo dos anos, o pior obstáculo que pro-
it(‘garanta que os endereços de email inválidos serão pegos’, function() {}); gramas feitos em JavaScript enfrentavam era sempre escrever
it(‘garanta que os endereços de email válidos irão passar da validação’, aplicações em larga escala, ou ao menos mitigáveis. Com o tempo,
function() {});
it(‘garanta que o formulário de submissão modifique o caminho padrão’,
os dialetos JavaScript foram ficando mais consistentes entre os
function() { }); browsers do que eram antes, e ferramentas como o jQuery podem
ajudar a deixar essas diferenças (que ainda existem) ainda mais
// é bom ter...
it(‘garanta que o helper client-side helper seja exibido para campos vazios’, leves aos olhos dos desenvolvedores. Os debuggers finalmente
function() { }); alcançaram melhores patamares de qualidade, jamais vistos
it(‘garanta que ao pressionar enter no campo de senha envie o formulário’, antes (sim, debugar JavaScript era terrível), atraindo, assim, o
function() { });
}); que antes afastava.
Nota
Dependendo das restrições implementadas, você deve decidir
O debug se tornou melhor ao longo do tempo, mas ainda depende do browser usado, pois cada
se deve ou não pular alguns passos, mas felizmente é possível
fabricante define suas próprias ferramentas de depuração.
ver com facilidade o quão crítico são cada um deles, isto é, que se
eles falharem podem bloquear o uso da aplicação.
Um outro exemplo clássico alusivo é o da construção de um Para todos os casos, com o advento da HTML5 e das plataformas
carro. Para construir um carro do início ao fim, cada parte que mobile, o JavaScript está se tornando cada vez menos ignorável.
faz a motor, o chassi, os pneus, devem ser verificados individu- Aplicações front-end inteiras estão sendo desenvolvidas em
almente para estar em ordem antes que elas possam de fato ser JavaScript, e enquanto a ferramenta suporta defasagens antes
atreladas ao carro. escondidas em linguagens como Java e C#, isso significa que
Se o tempo for dito insuficiente para averiguar todas estas temos evoluído.
peculiaridades, então possivelmente peças importantes serão E dentro desse escopo, uma área que permanece particularmente
despriorizadas e poderão não estar funcionando corretamente. mudando, e que irá começar a ficar incrivelmente importante nos
Por exemplo, os pneus podem acabar não sendo verificados em projetos JavaScript de escopo crescente são os testes unitários.
relação à pressão, a costura interior pode não ser verificada contra Para ilustrar uma situação mais próxima da programação, ve-
danos. Isso pode resultar em um carro falho, mas isso não seria seu jamos um exemplo de função básica em JavaScript, conforme o
problema, aparentemente. Apenas uma dica: verifique com cautela código a seguir:
o que pode ou não ser deixado de lado no momento de testar.
function addQuatroAoNumero(num){
Teste Unitário em JavaScript return num + 4;
Essa é uma história de controvérsias e recente. Apesar de }
JavaScript já ocupar espaço considerável na comunidade de
desenvolvimento front-end, inclusive até quando comparada a A mesma função basicamente adiciona o valor 4, como um nú-
outras linguagens de programação mais famosas como o Java, mero, à variável passada por parâmetro. Na Listagem 6 podemos
Escolhendo um Framework
Se você desenvolve com Java, você provavelmente não perde qUnit
muito tempo decidindo que framework de teste unitário irá O qUnit é um ótimo candidato para começar. Antes de tudo,
usar. O mais famoso deles, o jUnit, é sempre a opção preferida ele é consideravelmente fácil de aprender. De início pode ser um
da maioria dos desenvolvedores por razões óbvias de quali- pouco complicado para entender alguns comportamentos que
dade. O panorama do JavaScript não é tão resolvido assim, e
são menos intuitivos, mas assim que se entende os problemas design. O JavaScript tem, como melhor, começado a desenvolver
por trás destes comportamentos tudo começa a fluir mais rapi- essa disciplina, e algumas das funcionalidades da linguagem
damente. Ele possibilita interação com o DOM; você pode, por que empurram os desenvolvedores Java na direção certa (como
exemplo, identificar uma DIV na sua página de teste para ser encapsulamento) não gozam do mesmo nível de suporte nativo
resetada para seu estado original entre os testes, promovendo no JavaScript.
assim atomicidade aos testes. Além disso, ele também provê su- Existem alguns frameworks que podem ajudar na escrita de
porte a “testes assíncronos”, o que constitui uma funcionalidade testes unitários. O ExtJS, por exemplo, põe um sistema de classes
vital para suas aplicações. no topo do modelo de objetos do JavaScript. Ferramentas como
essa podem ajudar se você as permitir, porém como elas não fa-
js-test-driver zem parte da linguagem, você pode sempre escolher ir contra as
O js-test-driver foca no teste paralelo em múltiplos browsers. mesmas. Escrever JavaScript testável é, e para o futuro continuará
Ele tem sua própria linguagem de casos de teste e assertions, sendo, uma arte a ser modelada de acordo com a prática.
distinta do qUnit. Existem projetos que possibilitam ambos Não é algo simples manter sempre o foco na testabilidade.
de serem usados juntos, apesar de não existir um que suporte Mesmo que você programa todas as linhas do seu código com os
todas as capacidades de ambos frameworks. Diferente do qUnit, olhos voltados para a testabilidade do mesmo, sempre aparecerão
ele não usa partes do DOM para relatar resultados e reinicia o determinados comportamentos no código que fugirão à regra,
DOM inteiro entre um teste e outro. Isso impõe uma restrição como ubiquidade ou comportamentos assíncronos. Todo motor
a ser testada. JavaScript é single-threaded, mesmo que algumas tarefas simples
como requisitar um dado do servidor (usando Ajax, por exemplo),
Ambiente de Execução dos Testes respondendo à chamada UI, ou explicitamente retardando uma
Essa é outra questão que parece muito mais complicada com atividade (através de um setTimeout ou setInterval), são todas
JavaScript do que com Java: em qual ambiente devo executar feitas assincronamente.
meus testes? Então, o que um executor de testes deve fazer? Você é chamado
Você deve sempre querer que o seu ambiente de teste seja com- a agrupar o código que está testando.
patível com o ambiente de produção o mais próximo possível. 1. O framework é configurado para executar os testes;
Mas para muitas aplicações JavaScript, um pedaço crítico desse 2. O código de teste configura pré-condições e faz uma chamada
ambiente, o browser com seu respectivo motor JavaScript, é esco- para o código a ser testado;
lhido pelo usuário. Mesmo se os problemas cross-browser (vários 3. O código de teste checa os assertions;
browsers) não forem tão ruins quanto eles eram antes, ainda é 4. O framework reporta os resultados e vai para o próximo tes-
muito imaturo dizer que um teste feito em um browser terá um te.
resultado consistente por além dos demais.
Ao mesmo tempo, testar em todos os diferentes browsers traz Mas e se o código a ser testado faz alguma coisa de forma
mais desafios quando você começar a pensar em testes automa- assíncrona? Então, podemos verificar alguns outros passos
tizados e CI. Esse é o grande desafio que o js-test-driver é desig- específicos:
nado a resolver. Se você quer uma solução puramente qUnit, você 1. O framework é configurado para executar os testes;
provavelmente irá encontrar por si só escrevendo seus próprios 2. O código de teste configura pré-condições e faz uma chamada
scripts ou fazendo sem automação. para o código a ser testado;
Existem vários ambientes de execução JavaScript com suporte 3. O código a ser testado inicia algo, e então ele chama alguma
fácil a scripts, como o NodeJE, por exemplo, que será muito útil função para finalizar a tarefa;
para alguns testes automatizados de alto nível. Porém, eles terão 4. O framework reporta (imprecisamente) os resultados e vai para
suas próprias limitações (NodeJS não tem suporte a DOM nativo, o próximo teste;
apesar dos add-ons existirem) e em todo caso não conseguirá 5. Outras funções de fila devem executar;
simular o comportamento do browser. 6. A parte em fila do código a ser testada recebe sua vez de exe-
Uma abordagem multicamada deveria se aplicar melhor às suas cutar, e finaliza a coisa toda que foi iniciada no passo 3;
necessidades. Você poderia criar alguns scripts de teste para 7. O código de teste verifica os assertions.
executar no NodeJS por CI, e então rodar periodicamente uma
suíte de testes em cada browser alvo. Alguns bugs deverão não Dessa forma você consegue uma porção de testes falhando por
ser pegos como seriam se usasse uma CI completa. uma razão não muito boa.
O qUnit endereça isso com a função asyncronousTest(). Isso
Estrutura do Código funciona apenas como a função regular test(), exceto pelo fato
Nos primórdios do jUnit, não era incomum encontrar código Java do framework não assumir que o teste está finalizado quando o
que não se dirigisse diretamente aos testes unitários. Ao longo dos código de teste retorna. Você deve informar a ela quando o teste
anos, isso passou a ser visto como um teste de qualidade de um está finalizado chamando a função start().