Vous êtes sur la page 1sur 52

Assine agora e tenha acesso a

todo o contedo da DevMedia:


www.devmedia.com.br/mvp
Edio 07 2015

EXPEDIENTE
Editor
Diogo Souza (diogosouzac@gmail.com)
Consultor Tcnico
Daniella Costa (daniella.devmedia@gmail.com)

Produo
Jornalista Responsvel Kaline Dolabella - JP24185
Capa e Diagramao Romulo Araujo

Atendimento ao leitor
A DevMedia possui uma Central de Atendimento on-line, onde voc
pode tirar suas dvidas sobre servios, enviar crticas e sugestes e
falar com um de nossos atendentes. Atravs da nossa central tambm
possvel alterar dados cadastrais, consultar o status de assinaturas
e conferir a data de envio de suas revistas. Acesse www.devmedia.
com.br/central, ou se preferir entre em contato conosco atravs do
telefone 21 3382-5038.

Publicidade
publicidade@devmedia.com.br 21 3382-5038
Anncios Anunciando nas publicaes e nos sites do Grupo DevMedia,
voc divulga sua marca ou produto para mais de 100 mil desenvolvedores
de todo o Brasil, em mais de 200 cidades. Solicite nossos Media Kits, com
detalhes sobre preos e formatos de anncios.

Contedo sobre Boas Prticas

04 Google Charts: Criando Grficos dinmicos com JavaScript


[ Jlio Sampaio ]

Artigo no estilo Soluo Completa

17 Meteor.js: Construindo aplicaes web com Node.js e MongoDB


[ Jorge Rodrigues ]

Contedo sobre Boas Prticas, Contedo sobre Novidades

29 Primeiros passos com a Google Dart


[ Julio Sampaio ]

Contedo sobre Boas Prticas

41 Testes automatizados com o Framework Selenium


[ Sueila Sousa ]

Fale com o Editor!


muito importante para a equipe saber o que voc est achando da revista:
que tipo de artigo voc gostaria de ler, que artigo voc mais gostou e qual
artigo voc menos gostou. Fique a vontade para entrar em contato com os
editores e dar a sua sugesto!
Se voc estiver interessado em publicar um artigo na revista ou no site Java
Magazine, entre em contato com o editor, informando o ttulo e mini-resumo
do tema que voc gostaria de publicar:

Diogo Souza
diogosouzac@gmail.com
Analista de Sistemas Java na Indra Company
e j trabalhou em empresas como Instituto
Atlntico e Ebix L.A. instrutor Android,
palestrante em eventos sobre Java e o mundo
mobile e consultor DevMedia. Conhecimentos
e experincias em diversas linguagens e ferramentas de programao e manipulao de
dados, bem como metodologias teis no desenvolvimento de Sistemas diversificados.

Sumrio

Google Charts: Criando


Grficos dinmicos com
JavaScript
Veja como incorporar todo o potencial da API de
grficos do Google nas suas aplicaes web

or muito tempo a utilizao de grficos dinmicos,


muitas vezes gerados a partir de extensas fontes
de dados com inmeros cruzamentos de nvel
relacional nas bases de dados das aplicaes, era uma
tarefa reclusa somente aos ambientes de desenvolvimento
server side ou desktop, que, por sua vez, faziam uso de
linguagens de programao fortemente tipadas como o
Java ou C#. Alm disso, eles no podiam existir sozinhos,
mas sim pertencer a alguma estrutura de relatrio, com
gerao sempre feita em arquivos PDFs. Para se atingir
tal objetivo, principalmente em aplicaes web cross
platform que tm uma camada de apresentao baseada
em um browser, os passos so sempre os mesmos:
1. Primeiro desenvolve-se um layout, um template, atravs de uma ferramenta de desenho adaptada para aquela
tecnologia de relatrios e que gere um cdigo XML no
fim, como o iReport para relatrios em Java, e o Crystal
Reports para relatrios em .NET, por exemplo.
2. Uma vez criado o esqueleto com os devidos campos
em branco e variveis de referncia apontando para
cada um, que servem como lacunas a serem preenchidas
pela linguagem dinamicamente, hora de gerar toda a
lgica e reunir os dados para enviar ao mesmo layout,
via cdigo ou acesso direto a um banco de dados.
3. Finalmente, se a aplicao necessitar imprimir o relatrio em uma tela no navegador, serializamos todos
os bytes do relatrio e os enviamos em vrios pacotes
(processo esse que abstrado pela tecnologia server side
utilizada) via HTTP. O browser, ao receber tais pacotes,
ir processar o MIME type (vide BOX 1) do arquivo
final e executar a ao padro para o mesmo (fazer o
download do arquivo, abri-lo numa ferramenta desktop
padro, abri-lo num plugin do prprio browser, etc.).

4 Front-end Magazine Edio 04

Fique por dentro


Desenvolver grficos uma tarefa obrigatria em inmeras aplicaes corporativas e a maioria das empresas j no adotam mais solues baseadas no back-end. Frameworks JavaScript como o Google
Charts oferecem poderosos recursos para construir grficos de todo
tipo e de forma rpida, produtiva e performtica, tudo usando apenas JavaScript, CSS e HTML5. Alm de ser multiplataforma, o Google
Charts ainda se integra facilmente com Web Services e servios de
frameworks como AngularJS, jQuery, Polymer, dentre outros.
Neste artigo exploraremos os mais diversos recursos dessa biblioteca, expondo situaes do cotidiano, alm de entender qual grfico
atende melhor a cada situao. Mostraremos como modificar estilo,
propores, estrutura, bem como adaptar os layouts ao novo conceito
de design do Google: O Material Design.

BOX 1. MIME type


MIME type quer dizer Internet Media Type, ou Tipo de Mdia de Internet, e serve para identificar
o tipo de dado que um determinado arquivo contm. Os usos mais comuns so para softwares
clientes de e-mail, navegadores web e mecanismos de buscas. Geralmente eles so divididos em
tipos e subtipos. Por exemplo, usamos os MIME types para designar nomes de arquivos quando os
importamos em uma pgina HTML, como os arquivos de CSS (text/css) e JavaScript (text/javascript).
Neste caso, o text o tipo e css-javascript so os subtipos.

So muitos passos para se atingir um objetivo deveras simples,


isso sem falar da sobrecarga gerada na aplicao ao trafegar
informaes de download (e downloads no so a especialidade
do HTTP) sempre que o usurio solicitar uma nova impresso.
Alguns desenvolvedores optaram ento pelo uso da tecnologia
Ajax no client side para aumentar a performance das requisies,
uma vez que elas sero feitas de forma assncrona.

Copyright - Proibido copiar ou distribuir. Todos os direitos reservados para DevMedia

Alguns frameworks como o JSF ou ASP.NET do suporte a esse


tipo de funcionalidade, porm, isso s mascara o problema, pois
os bytes continuaro sendo trafegados.
A soluo encontrada pela maioria das empresas para diminuir
esse gargalo do server side foi focar no que h de mais crucial para
as aplicaes: os dados, e deixar todo o resto com o JavaScript (que
tambm muito leve). Representar dados em aplicaes front-end
muito simples e leve, basta usar objetos JSON ou XML para fazer
a transio e o efeito altamente performtico.
Inmeros so os plug-ins e bibliotecas JavaScript que fornecem
recursos como esse, dentre os quais destacam-se uma gama de plugins do jQuery (como o HighCharts), o Flotr2 e o Google Charts.
O maior desafio de uma empresa que lana uma ferramenta
desse tipo a qualidade (visual e do cdigo) e a quantidade de
grficos disponveis, uma vez que os usurios se tornam cada
vez mais exigentes e as informaes crescem exponencialmente
em nmero e complexidade dependendo da rea de negcio trabalhada. O Google Charts atende muito bem a essas exigncias,
principalmente por englobar em sua criao a realidade de uma
das empresas que mais usam grficos: o prprio Google.
A ferramenta do Google Charts prov uma srie de recursos
para construir grficos de forma fcil e adicion-los s suas pginas web de forma responsiva, adaptando o design realidade
das mesmas. Existem basicamente dois tipos de grficos que
podem ser trabalhados: os estticos e os interativos. A principal
diferena est na forma como voc deseja que seu grfico interaja
com o usurio, pois os grficos estticos fornecero apenas uma
imagem dos dados dinmicos recebidos, ao passo que os interativos disponibilizaro eventos JavaScript (como click, focus,
mouseover/out/in, etc.) para efetuar aes via cdigo quando os
mesmos forem disparados.
Neste artigo trataremos de explorar os recursos mais importantes do Google Charts, desenvolvendo ambos os tipos de relatrio
citados em diversos formatos (grficos de linha, barras, pizza,
geogrficos, etc.), bem como a adaptao dos mesmos ao novo
conceito de design do Google: o Material Design.

Primeiros grficos
O Google Chart fornece duas formas de gerao de grficos: via
URL e via cdigo JavaScript. O primeiro tipo fornece uma URL
universal que, via mtodo GET HTTP, retorna uma imagem esttica do grfico gerada em detrimento dos parmetros passados
pela mesma URL, que constituem a prpria fonte de dados. Essa
opo, por sua vez, permite somente a gerao de grficos simples,
que no envolvem tomadas de deciso ou estruturas condicionais.
J a segunda opo se d atravs da importao das bibliotecas
da API, sobrescrita das funes ncleo e fornecimento dos dados
via mocks ou servios remotos.
Vejamos a URL de exemplo representada a seguir, cujo grfico
gerado ilustrado pela Figura 1:
http://chart.apis.google.com/chart?cht=p3&chs=550x300&chd=t:5,4,3,6&chl=PCs|
Geladeiras|TVs|Outros&chtt=%C3%9AltimasVendas&chco=8cc53e

Figura 1. Grfico de exemplo gerado via URL


Vejamos alguns detalhes:
Esse recurso est hospedado por padro no site oficial do
Google Charts (vide seo Links), portanto a primeira parte da
URL referente ao domnio representa o mesmo site. Por ser um
servio que executa em GET no HTTP, a performance em si
aumentada;
O primeiro parmetro (cht, de chart type), definido aps o sinal
de interrogao, referente ao tipo do grfico (neste caso, pizza
em 3D = p3). Voc pode encontrar uma lista dos tipos disponveis
tambm no site oficial;
O parmetro chs (de chart size) define as dimenses (largura
x altura) do grfico, sempre em pixels;
O parmetro chd (de chart data) define os valores para cada
pedao do grfico. Esses valores devem sempre ser particionados em forma percentual, uma vez que a API somar tudo e
definir o percentual de cada parte no todo;
O parmetro chl (de chart labels) se encarrega de receber o vetor
com as legendas que sero exibidas para cada item do grfico.
importante que os valores estejam em mesmo nmero e ordem
que os definidos no parmetro chd, seno voc receber um erro
na impresso do grfico;
O parmetro chtt (de chart title) recebe o valor do ttulo do
grfico;
Por fim, o parmetro chco (de chart color) recebe a cor em hexadecimal (sem o sinal de #) que ser exibida no grfico. O valor
8cc53e referente cor padro da logo da DevMedia. Note que
a mesma cor distribuda em tons mais claros e escuros para
diferenciar as partes do grfico. Esse tipo de comportamento
padro no Google Charts, mas se voc desejar atrelar uma cor
diferente a cada pedao, basta configurar o parmetro com os
valores em forma de vetor, por exemplo: chco=8cc53e|ff0000|1
12233|123456.
Nota
Todos os grficos gerados pelo Google Charts so renderizados usando SVG (Scalable Vector
Graphics) ou VML (Vector Markup Language), que so linguagens de marcao baseadas em vetores
usadas para representar grficos bidimensionais em pginas web. O Google vem trabalhando para
incluir tambm o Canvas da HTML5.

Copyright - Proibido copiar ou distribuir. Todos os direitos reservados para DevMedia

Edio 04 Front-end Magazine

Google Charts: Criando Grficos dinmicos com JavaScript

Essa opo, apesar das limitaes, bem flexvel e simples, o que


permite que qualquer usurio, inclusive os que no tm conhecimentos de programao, possa us-la. E esse foi o objetivo do Google ao disponibiliz-la. Se voc desejar dinamizar o contedo, basta
efetuar chamadas seguidas mesma URL modificando apenas os
parmetros, lembrando que essa URL precisa estar sempre dentro
do atributo src da tag img na sua pgina HTML, o que te permite
inclusive modificar seu contedo via JavaScript, jQuery, etc.
O Google tambm oferece uma pgina onde voc pode desenhar os grficos online enquanto ela mesma gera a URL com as
respectivas opes, trata-se do Google Live Chart Playground
(vide seo Links).
J em relao ao uso da segunda opo, via cdigo JavaScript,
antes de iniciar as implementaes de fato, precisamos configurar
o ambiente, bem como a estrutura de diretrios que usaremos para
padronizar o acesso aos caminhos relativos de dentro das pginas
HTML. Para isso, crie uma estrutura semelhante ilustrada pela
Listagem 1 na sua mquina.
Listagem 1. Estrutura de diretrios padro do projeto.
google-charts-devmedia
|----css
|----index.css
|----js
|----index.js
|----img
|----index.html

Note que os trs arquivos HTML, CSS e JS devem ser criados tambm para conter o cdigo que vamos desenvolver inicialmente.
Feito isso, existem trs passos bsicos para se configurar qualquer grfico com o Google Charts, a saber:
1. A API Google JSAPI: Essa API comporta todas as funes Ajax
e JavaScript necessrias para carregar os grficos, bem como a
lgica para montar, distribuir e dinamizar os dados. Para inclu-la
na sua aplicao basta inserir o trecho de importao de script a
seguir na sua pgina HTML:
<!-- Carrega a AJAX API -->
<script type=text/javascript src=https://www.google.com/jsapi > </script>

2. A biblioteca Google Visualization: Essa biblioteca define as


classes e funes de ncleo e utilitrias da API. Temos, por exemplo, as classes DataTable para lidar com os dados em forma de
tabela, e Query para busca de dados nos provedores, alm de
error handlers para ajudar a identificar e exibir erros nas pginas.
A forma de importao da mesma, entretanto, se d de forma diferente das demais: em vez de importar um arquivo diretamente
dos servidores do Google, precisamos carregar um mdulo (visualization, para ser mais especfico) via JavaScript, informando
a verso e a lista de pacotes que queremos importar:
<script type=text/javascript>
google.load( visualization, 1.0, { packages :[ <lista_dos_nomes_pacotes>] });</script>

6 Front-end Magazine Edio 04

3. O cdigo para o grfico em si: Tambm preciso definir o


cdigo de criao do grfico propriamente dito, atravs do uso de
classes como PieChart, BarChart, etc. Para isso preciso sobrescrever o mtodo setOnLoadCallback() com a funo que dever
ser chamada para construir o grfico em si. Veja o cdigo que voc
precisa usar para isso:
<script type=text/javascript >
google.setOnLoadCallback( desenharGrafico );
</script>

Nota
O leitor precisar ter obrigatoriamente uma conexo com a internet para testar os exemplos, visto
que os arquivos JavaScript, de CSS e imagens sero carregados diretamente dos servidores Google.

No passo 2 vimos que o Google Charts se utiliza do arquivo


JavaScript importado no passo 1 para carregar os mdulos que
precisamos para os grficos. Esse tipo de recurso modularizado j
comum em inmeros frameworks JavaScript, como o Grunt, CoffeeScript, etc. pois aumenta a performance da aplicao ao carregar
somente o que necessrio naquele momento. Em outras palavras,
imagine que voc tem um arquivo JS de 2 MB de tamanho final, que
contempla todo o cdigo para criar qualquer sorte de grfico:
A vantagem que esse arquivo ser carregado apenas uma vez,
logo no precisaremos efetuar mais chamadas ao servidor quando
precisarmos acessar um mdulo X, Y ou Z;
A desvantagem que ele muito pesado e isso gera sobrecarga,
deixando a aplicao mais lenta e menos visvel s ferramentas
de busca.
Para solucionar isso, a API divide o arquivo em vrios menores e, quando um determinado grfico precisa ser usado (pizza,
linhas, colunas, etc.), basta importar o mdulo correspondente
ao mesmo. No nosso exemplo, cada mdulo teria o equivalente a
15 KB, caracterizando assim um ganho enorme para a aplicao.
Vejamos ento a implementao necessria para criar um grfico
de colunas via JavaScript. Na Listagem 2 temos o cdigo de um
grfico onde cruzamos a mdia salarial entre vrias profisses
de TI, que ser refletido na Figura 2.
A figura est dividida em duas partes: a primeira representa
o grfico normal, e a segunda o grfico com a coluna destacada
ao pr o mouse sobre a mesma. Vejamos alguns detalhes da
implementao:
Nas linhas 8, 11 e 14 vemos a implementao obrigatria dos
trs passos vistos, respectivamente.
Na linha 17 temos a funo criarGrafico() que conter o cdigo
para criao do objeto de grfico (neste caso um objeto DataTable,
linha 19), bem como criao das colunas e dados.
Nas linhas 22 e 23 temos a criao das colunas com dois parmetros: o tipo de dado (string, number, char, boolean, etc.) e a
descrio das mesmas. Esta ltima s ser usada se voc explicitar
alguma ao interativa nos eventos JavaScript.

Copyright - Proibido copiar ou distribuir. Todos os direitos reservados para DevMedia

Listagem 2. Cdigo para criao de grfico de colunas.


01 <!DOCTYPE>
02 <html>
03 <head>
04
<title>Google Charts - DevMedia</title>
05
<meta charset=utf-8>
06
07
<!-- Carrega a AJAX API -->
08
<script type=text/javascript src=https://www.google.com/jsapi> </script>
09
<script type=text/javascript>
10
// Carrega a API da biblioteca Visualization e add os nomes dos pacotes.
11
google.load(visualization, 1, {packages: [columnchart]});
12
13
// seta a funo de callback
14
google.setOnLoadCallback (criarGrafico);
15
16
// funo de callback
17
function criarGrafico() {
18
// cria o objeto DataTable que falamos antes
19
var dataTable = new google.visualization.DataTable();
20
21
// Define as colunas
22
dataTable.addColumn(string, Profissionais TI 2015);
23
dataTable.addColumn(number, Salrios);
24

Na linha 26 onde criamos os dados


fixos para teste do grfico. O mtodo
addRows() recebe sempre um vetor com
os valores na ordem e quantidade das
colunas previamente definidas.
Na linha 29 criamos um novo objeto do
tipo ColumnChart que representa o objeto
de grfico em si, passando como parmetro a div HTML que criamos na linha 43.
dentro dela que o Google Charts ir
enxertar todo a HTML do grfico.
Na linha 32 definimos o objeto options.
Este objeto opcional e serve para configurar as propriedades de estrutura e estilo do
grfico, como dimenses, ttulo, etc.
Por fim, na linha 35, chamamos o mtodo
draw() que se encarregar de fazer todo o
trabalho de desenho, passando o objeto de
dados dataTable e o objeto de options.
Note que na linha 11, onde definimos o
tipo do grfico que queremos desenhar,
voc pode substituir o valor da propriedade
packages por outro tipo, como o grfico em
barras. Veja como ficaria a implementao:
google.load(visualization, 1, {packages: [corechart]});

Agora s salvar o arquivo e reexecutar


a pgina no browser. O resultado dever
ser igual ao da Figura 3.

25
26
27
28
29
30
31
32

// Define os dados a serem exibidos


dataTable.addRows([[Designer, 1500], [Programador, 2500],
[Arquiteto de Software, 4750], [Gerente de Projetos, 7500]]);
// Instancia o nosso objeto chart
var chart = new google.visualization.ColumnChart
(document.getElementById(chart));
// Define as opes para visualizao
var options = {width: 600, height: 350, is3D: true,
title: Mdia de Salrios em TI};

33
34
// desenha o nosso grfico de fato
35
chart.draw(dataTable, options);
36
}
37
</script>
38
39 </head>
40
41 <body>
42
<!-- Div para o nosso grafico -->
43
<div id=chart></div>
44 </body>
45 </html>

Figura 2. Grfico de colunas de exemplo gerado via JavaScript

Figura 3. Grfico de barras de exemplo gerado via JavaScript


Perceba como uma pequena alterao
no cdigo traz um resultado enorme para
o visual do grfico. O valor corechart
usado para associar o estilo ao novo
padro do Google: o Material Design
(vamos explor-lo mais frente). Alm

disso, agora temos a exibio da descrio em um balo suspenso para cada


barra do grfico com o respectivo valor.
O leitor pode testar outros valores e ver
como a API se comporta, mas lembre-se
que os grficos precisam ter a mesma

Copyright - Proibido copiar ou distribuir. Todos os direitos reservados para DevMedia

Edio 04 Front-end Magazine

Google Charts: Criando Grficos dinmicos com JavaScript

estrutura de cruzamento dos dados, neste caso dados representados pelos eixos x e y do plano cartesiano.
Alm de textos e nmeros, tambm possvel criar grficos
mltiplos, manipular outros tipos de dados como datas e valores
percentuais, definir posies diferentes para legendas e subttulos,
dentre outros. Suponha que, no mesmo exemplo, voc deseja criar
uma coluna ou barra dupla para representar as mdias mnima e
mxima de salrios. Esses grficos so chamados de Dual-Y charts,
justamente pela dualidade de colunas no eixo Y. Crie ento uma
nova pgina HTML e adicione o contedo da Listagem 3 mesma.

Figura 4. Grfico de barras duplas gerado via JavaScript

O resultado pode ser verificado na Figura 4.


Perceba que a estrutura base do grfico a mesma, porm fizemos vrias alteraes, a saber:
Na linha 22 adicionamos uma nova coluna ao objeto grfico.
Sempre que for necessrio fazer isso, a ordem de tipo do dado e
descrio deve ser respeitada.
A partir da linha 24 estamos populando o nosso vetor de
linhas com as mesmas labels de profissionais, porm os valores
agora esto com uma notao diferente. A variveis v e f descrevem o valor numrico e a descrio que dever aparecer no
grfico, respectivamente. Esse recurso funciona
de forma semelhante aos alias de bancos de dados,
onde em vez de exibirmos o nome da prpria coluna (que geralmente mais tcnico que apresentvel) criamos um valor mascarado que ser exibido
no lugar. Atravs dessa mscara, voc consegue
incutir qualquer texto pr-formatado e o resultado
fica bem mais elegante, conforme demonstrado no
balo descritivo do grfico final.
A partir da linha 31 definimos o objeto options,
dessa vez com algumas configuraes novas:
- A propriedade position definida no atributo legend da linha 34 modifica a posio das caixas de
legendas no grfico. Os valores possveis so top,
bottom, left ou right. J maxLines, na mesma linha,
define o nmero mximo de linhas que a legenda
dever ocupar na impresso.

Listagem 3. Criando grfico duplo.


01 <!DOCTYPE>
02 <html>
03 <head>
04
<title>Google Charts - DevMedia</title>
05
<meta charset=utf-8>
06
07
<!-- Carrega a AJAX API -->
08
<script type=text/javascript src=https://www.google.com/jsapi> </script>
09
<script type=text/javascript>
10
// Carrega a API da biblioteca Visualization e add os nomes dos pacotes.
11
google.load(visualization, 1, {packages: [corechart]});
12
13
// seta a funo de callback
14
google.setOnLoadCallback (criarGrafico);
15
16
// funo de callback
17
function criarGrafico() {
18
var dataTable = new google.visualization.DataTable();
19
20
dataTable.addColumn(string, Profissionais TI 2015);
21
dataTable.addColumn(number, Mdia Mnima);
22
dataTable.addColumn(number, Mdia Mxima);
23
24
dataTable.addRows([
25
[Designer, {v: 1500, f: R$ 1500,00}, {v: 2000, f: R$ 2000,00}],
26
[Programador, {v: 2500, f: R$ 2500,00}, {v: 3500, f: R$ 3500,00}],
27
[Arquiteto de Software, {v: 4750, f: R$ 4750,00},
{v: 5680, f: R$ 5680,00}],
28
[Gerente de Projetos, {v: 7500, f: R$ 7500,00}, {v: 9600, f: R$ 9600,00}],
29
]);

8 Front-end Magazine Edio 04

30
31
var options = {
32
width: 1000,
33
height: 500,
34
legend: {position: top, maxLines: 3},
35
title: Mdia de Salrios em TI/Aprovao,
36
hAxis: {
37
title: Profissional
38
},
39
vAxis: {
40
title: Salrios
41
},
42
bar: { groupWidth: 50% }
43
};
44
45
var chart = new google.visualization.ColumnChart(
46
document.getElementById(chart));
47
48
chart.draw(dataTable, options);
49
}
50
</script>
51
52 </head>
53
54 <body>
55
<!-- Div para o nosso grafico -->
56
<div id=chart></div>
57 </body>
58 </html>

Copyright - Proibido copiar ou distribuir. Todos os direitos reservados para DevMedia

- Os atributos hAxis e vAxis, servem para configurar propriedades especficas dos valores exibidos nos eixos horizontal e vertical, respectivamente, tais como formatao, ttulos,
valores mximos e mnimos, etc. Neles, definimos os ttulos
dos dois eixos: Salrios e Profissional, conforme observado no grfico final.
- O atributo bar da linha 42 exclusivo para grficos em
barras e serve para definir o tamanho mximo das barras,
atravs da propriedade groupWidth. Note como as barras
esto 50% menores em relao ao exemplo anterior.

as datas devem ser definidas sempre em forma de vetor com trs


valores: hora, minuto e segundo, respectivamente.
No objeto options, configuramos o eixo horizontal (hAxis) na
linha 41 com dois novos atributos:
- format: define a regra de formatao da data, que ser sempre
hora:minuto.
- viewWindow: define os valores mnimo e mximo para a
representao das horas no eixo horizontal.
Existe ainda uma segunda forma de se implementar os mesmos
grficos, atravs da funo arrayToDataTable() do Google Charts.
Atravs dela podemos reduzir a quantidade de cdigo por meio
das roles (papis) que incutem formatao no momento de criao

Assimilado esse conhecimento, muito fcil criar estruturas


novas. Por exemplo, agora voc precisa gerar um grfico com o
nmero de atividades entregues e pendentes em um determinado projeto de
TI, fazendo um rastreio ao longo do dia
til de trabalho. Vejamos a implementao da Listagem 4 (apenas com o cdigo
JavaScript, a HTML permanece igual).
O resultado dessa implementao
pode ser observado na Figura 5. Vejamos algumas observaes:
Na linha 11 temos a adio de um
novo tipo de dado: timeofday, que funciona como o Date do JavaScript.
A maior mudana acontece na linha
15, onde estamos definindo os objetos
de data/hora, e nmero de atividades.
Note que aqui tambm usamos as variveis v e f para criar os alias porm, Figura 5. Grfico de barras usando rastreio de horas
Listagem 4. Exemplo de grfico em barras usando rastreio de horas.
01 <script type=text/javascript>
02 // Carrega a API da biblioteca Visualization e add os nomes dos pacotes.
03 google.load(visualization, 1, {packages: [corechart]});
04
05 // seta a funo de callback
06 google.setOnLoadCallback (criarGrafico);
07
08 // funo de callback
09 function criarGrafico() {
10
var dataTable = new google.visualization.DataTable();
11
dataTable.addColumn(timeofday, Dia);
12
dataTable.addColumn(number, Atividades Completas);
13
dataTable.addColumn(number, Atividades Pendentes);
14
15
dataTable.addRows([
16
[{v: [8, 0, 0], f: 8 AM}, 2, 8.75],
17
[{v: [9, 0, 0], f: 9 AM}, 2.5, 7.5],
18
[{v: [10, 0, 0], f:10 AM}, 3.9, 6.3],
19
[{v: [11, 0, 0], f: 11 AM}, 4, 5.25],
20
[{v: [12, 0, 0], f: 12 PM}, 6, 4.25],
21
[{v: [13, 0, 0], f: 1 PM}, 6, 3],
22
[{v: [14, 0, 0], f: 2 PM}, 7, 2],
23
[{v: [15, 0, 0], f: 3 PM}, 7.89, 1.25],
24
[{v: [16, 0, 0], f: 4 PM}, 9.1, 0.5],
25
[{v: [17, 0, 0], f: 5 PM}, 10, 0.25],
26
[{v: [18, 0, 0], f: 5 PM}, 10, 0],

27
]);
28
29
var options = {
30
width: 1000,
31
height: 500,
32
title: Balano de Atividades Entregues/Dia,
33
hAxis: {
34
title: Dia,
35
format: h:mm a,
36
viewWindow: {
37
min: [7, 30, 0],
38
max: [18, 0, 0]
39
}
40
},
41
vAxis: {
42
title: Atividades
43
}
44
};
45
46
var chart = new google.visualization.ColumnChart(
47
document.getElementById(chart));
48
49
chart.draw(dataTable, options);
50 }
51 </script>

Copyright - Proibido copiar ou distribuir. Todos os direitos reservados para DevMedia

Edio 04 Front-end Magazine

Google Charts: Criando Grficos dinmicos com JavaScript

dos dados, assim podemos associar um design diferente para cada


barra, por exemplo. Veja como ficaria nosso mtodo criarGrafico()
ao fazer uso dessa funo (Listagem 5).
O resultado pode ser visualizado na Figura 6. Vamos aos
detalhes:
Na linha 2 vemos a utilizao da funo arrayToDataTable()
para efetuar a converso do vetor de dados passado como parmetro para um objeto do tipo DataTable.
Listagem 5. Refatorando funo criarGrafico().
01 function criarGrafico() {
02
var data = google.visualization.arrayToDataTable([
03
[Dia, Atividades Completas, Atividades Pendentes, { role: style },
{ role: annotation } ],
04
[{v: [8, 0, 0], f: 8 AM}, 2, 8.75, color: red, 8 AM],
05
[{v: [9, 0, 0], f: 9 AM}, 2.5, 7.5, color: blue, 2.5],
06
[{v: [10, 0, 0], f:10 AM}, 3.9, 6.3, opacity: 0.2, Pendentes: 6.3],
07
[{v: [11, 0, 0], f: 11 AM}, 4, 5.25, stroke-color: black; stroke-width: 1;
fill-color: yellow, 11 AM],
08
[{v: [12, 0, 0], f: 12 PM}, 6, 4.25, stroke-color: pink; stroke-opacity: 0.6;
stroke-width: 1; fill-color: green; fill-opacity: 0.2, ?]
09
]);
10
11
var options = {
12
width: 1500,
13
height: 500,
14
title: Balano de Atividades Entregues/Dia,
15
hAxis: {
16
title: Dia,
17
format: h:mm a,
18
viewWindow: {
19
min: [7, 30, 0],
20
max: [12, 0, 0]
21
}
22
},
23
vAxis: {
24
title: Atividades
25
}
26 };
27
28 var chart = new google.visualization.ColumnChart(
29
document.getElementById(chart));
30
31 chart.draw(data, options);
32 }

Na linha 3 configuramos as duas roles que atuaro diretamente


no estilo (style) e nas anotaes dentro de cada barra (annotation),
respectivamente. Isso far com que, aliada aos valores configurados para essas propriedades at a linha 8, cada barra tenha estilo
prprio e texto exibido sem que tenhamos de passar o mouse
sobre a mesma.
Esse exemplo reduziu a quantidade de horas para apenas 12hs,
mas se o leitor desejar usar o dia inteiro, pode configurar a propriedade bar que vimos para aumentar o tamanho das barras.
Ainda sobre grficos de barras e colunas, podemos criar um subtipo
desse grfico, o grfico em pilha. Esse tipo de grfico funciona colocando os valores um acima do outro, em forma de pilha. Se existir
qualquer valor negativo, ele ser posicionado de igual forma abaixo
do eixo X um sob o outro. Para adaptar ao nosso modelo de negcio,
suponha que queremos criar um grfico que exiba a mesma mdia
salarial, s que por ano. Cada pedao da barra ser uma profisso
com o respectivo valor de cada salrio. Vejamos a Listagem 6.
O resultado pode ser visualizado na Figura 7. Vejamos os detalhes:
Na linha 3 temos a mesma implementao da funo de converso de vetor para DataTable. A diferena est na ordem dos
dados no vetor. Agora temos as descries dos profissionais como
primeiro dado, como se estivssemos preenchendo uma tabela no
Excel. Note que o cabealho dessa tabela tambm deve existir, no
caso a label Profissional.
A partir da linha 5 injetamos cada um dos valores que devem
sempre comear com o ano seguido das variaes salariais.
Na linha 16 temos o atributo novo isStacked, que foi configurado
com true para dizer que nosso grfico de colunas ser exibido em
forma de pilha.

Material Design
Em 2014, o Google anunciou orientaes destinadas a apoiar uma
aparncia comum em todas as suas propriedades e aplicativos
(como os apps Android) que so executados em plataformas do

Figura 6. Grfico de barras usando formataes diferentes.

10 Front-end Magazine Edio 04

10

Copyright - Proibido copiar ou distribuir. Todos os direitos reservados para DevMedia

Figura 7. Grfico em pilha usando mesmo exemplo de profissionais


prprio Google. A esse novo conceito foi dado o nome de Material
Design (Design de Materiais).
Para criar um grfico de colunas Material basta carregar a API
de visualizao do Google (agora com o pacote bar em vez do
corechart que estvamos usando), definir a sua tabela de dados,
e em seguida, criar o objeto de gerenciamento do grfico (por
intermdio da classe google.charts.Bar).
A principal vantagem ao usar esse novo conceito, alm de um
design mais elegante, poder mudar facilmente a orientao do grfico, sem perder em responsividade. Tomando como base o exemplo
anterior, a nossa listagem ficaria semelhante Listagem 7.
Listagem 6. Exemplo de grfico em pilha.
01 // funo de callback
02 function criarGrafico() {
03 var data = google.visualization.arrayToDataTable([
04
[Profissional, Designer, Programador, Arquiteto de Software,
Gerente de Projetos],
05
[2010, 1000, 2000, 4000, 5500],
06
[2011, 1500, 2500, 4350, 6000],
07
[2012, 1800, 2700, 4750, 6500],
08
[2013, 2500, 3500, 5250, 7500]
09 ]);
10
11 var options = {
12
width: 1500,
13
height: 500,
14
legend: { position: top, maxLines: 3 },
15
bar: { groupWidth: 75% },
16
isStacked: true,
17
hAxis: {
18
title: Ano
19
},
20
vAxis: {
21
title: Salrios
22 }
23 };
24
25 var chart = new google.visualization.ColumnChart(
26
document.getElementById(chart));
27
28 chart.draw(data, options);
29 }

Listagem 7. Exemplo de grfico usando o conceito do Material Design.


01 <script type=text/javascript>
02 /// Carrega a API da biblioteca Visualization e add os nomes dos pacotes.
03 google.load(visualization, 1.1, {packages: [bar]});
04
05 // seta a funo de callback
06 google.setOnLoadCallback (criarGrafico);
07
08 // funo de callback
09 function criarGrafico() {
10
var data = google.visualization.arrayToDataTable([
11
[Ano, Designer, Programador, Arquiteto de Software,
Gerente de Projetos],
12
[2010, 1000, 2000, 4000, 5500],
13
[2011, 1500, 2500, 4350, 6000],
14
[2012, 1800, 2700, 4750, 6500],
15
[2013, 2500, 3500, 5250, 7500]
16
]);
17
18
var options = {
19
chart: {
20
title: Distribuio de profissionais/salrios,
21
subtitle: Sales, Expenses, and Profit: 2014-2017
22
},
23
series: {
24
0: { axis: distance } // Vincula a srie de 0 a um eixo chamado distance.
25
},
26
width: 800,
27
height: 400,
28
legend: { position: top},
29
bar: { groupWidth: 75% },
30
axes: {
31
y: {
32
distance: {label: Salrios}
33
}
34
}
35
};
36
37
var chart = new google.charts.Bar(document.getElementById(chart));
38
chart.draw(data, options);
39 }
40 </script>

Copyright - Proibido copiar ou distribuir. Todos os direitos reservados para DevMedia

11 11

Edio 04 Front-end Magazine

Google Charts: Criando Grficos dinmicos com JavaScript

Vamos aos detalhes:


Na linha 3 mudamos o valor da verso
do pacote para 1.1, em vista desse tipo de
recurso ser recente e s estar contido neste
mdulo. Alm disso, mudamos tambm o
package para bar.
Na linha 11 mudamos o valor inicial
de Profissional para Ano, uma vez
que o Material Design no considera o
preenchimento em forma de tabela e sim
de barras.
Na linha 18 temos algumas mudanas
quanto propriedade options:
- O ttulo e subttulo agora precisam estar dentro de um outro atributo: chart.
Perceba que quando se muda o mdulo
utilizado todo o cdigo importado tambm muda, logo precisamos adaptar
aos padres.

- O atributo series da linha 23 cria o


elemento que se encarregar de configurar os subatributos dos eixos X e
Y no plano.
- Na linha 30, o atributo axes se encarrega de configurar o eixo Y atravs
do subatributo y. As labels agora so
definidas dentro desse atributo.
A execuo desse arquivo resultar nas
Figuras 8 e 9. Veja como o design agora
est mais leve. A primeira figura exibe o
resultado de quando pomos o mouse em
um dos elementos da legenda. Note que
todos que pertencem quele grupo ficam
destacados com uma opacidade mais
escura. A segunda imagem traz o balo
de detalhes de cada barra, ao colocar o
mouse em cima.

Figura 8. Grfico em colunas usando Material Design com grupo selecionado

Nota
O Material Design no ir funcionar em verses antigas do
Internet Explorer. Do IE8 para trs ele tambm no suporta o
SVG, que requerido pelo Google Charts.

Outros grficos
O Google Charts prov uma gama de
outros grficos que podem facilmente se
adaptar realidade dos nossos exemplos.
Vejamos alguns exemplos deles.

Grfico de Linhas
O grfico de linhas bem semelhante
ao de colunas no que confere o cruzamento das informaes, porm em vez
de barras ele usa linhas para marcar os
pontos. Suponha que no nosso exemplo
queremos criar um grfico cruzando o
desempenho dos profissionais da empresa em detrimento de um intervalo
de dias. O cdigo para isso se encontra
na Listagem 8.
Vejamos algumas observaes:
Na linha 2 temos a mudana do package
para o valor line. Veja que tambm estamos usando a verso 1.1, esta que caracteriza sempre o uso do Material Design.
Na linha 6 voltamos a criar o objeto
DataTable. Isso porque esse grfico exige
que as linhas sejam adicionadas em forma
de tabela, diferente de como fizemos com
o preenchimento do de barras.
Na linha 14 populamos o vetor de dados,
porm com o primeiro valor como string.
Se voc precisar usar o dado numrico
para manipular algo no JavaScript pode
usar as variveis v e f que vimos, ou concatenar os valores na mo mesmo.
Na linha 32 configuramos os ttulos. Veja
que estamos considerando os valores em
DPUs, que uma unidade muito comum
para medir atividades e desempenho.
Na linha 40 mudamos o tipo do objeto
instanciado para google.charts.Line().
O resultado da execuo pode ser visualizado na Figura 10.

Grficos geogrficos

Figura 9. Grfico em colunas usando Material Design com barra selecionada

12 Front-end Magazine Edio 04

12

Um geochart nada mais que um mapa


de um pas, um continente ou uma regio
com reas identificadas de trs modos:

Copyright - Proibido copiar ou distribuir. Todos os direitos reservados para DevMedia

Listagem 8. Exemplo de grfico de linhas usando o Material Design.


01 <script type=text/javascript>
02 google.load(visualization, 1.1, {packages: [line]});
03 google.setOnLoadCallback(drawChart);
04
05 function drawChart() {
06 var data = new google.visualization.DataTable();
07
08 data.addColumn(string, Dia);
09 data.addColumn(number, Designer);
10 data.addColumn(number, Programador);
11 data.addColumn(number, Arquiteto de Software);
12 data.addColumn(number, Gerente de Projetos);
13
14 data.addRows([
15
[Dia 1 , 35.8, 80.8, 41.8, 55.5],
16
[Dia 2 , 29.9, 49.5, 32.4, 55.5],
17
[Dia 3 , 24.4, 57, 25.7, 55.5],
18
[Dia 4 , 10.7, 18.8, 10.5, 55.5],
19
[Dia 5 , 10.9, 17.6, 10.4, 50.5],
20
[Dia 6 , 7.8, 13.6, 7.7, 55.5],
21
[Dia 7 , 6.6, 12.3, 9.6, 55.5],
22
[Dia 8 , 11.3, 19.2, 10.6, 15.5],

23
[Dia 9 , 15.9, 42.9, 14.8, 55.5],
24
[Dia 10, 11.8, 10.9, 11.6, 55.5],
25
[Dia 11, 4.3, 7.9, 4.7, 55.5],
26
[Dia 12, 5.6, 8.4, 5.2, 55.5],
27
[Dia 13, 3.8, 6.3, 3.6, 55.5],
28
[Dia 14, 4.2, 6.2, 3.4, 55.5]
29 ]);
30
31 var options = {
32
chart: {
33
title: Desempenho profissionais/Dia,
34
subtitle: em DPUs
35
},
36
width: 800,
37
height: 450
38 };
39
40 var chart = new google.charts.Line(document.getElementById(chart));
41
42 chart.draw(data, options);
43 }
44 </script>

O modo region (regio): onde temos regies delimitadas por cores, como pases,
provncias, estados, etc.
O modo markers (marcadores): onde
usamos crculos para designar regies
que so dimensionados de acordo com um
valor que voc especificar.
O modo text (texto): onde rotulamos as
regies com identificadores em texto (por
exemplo, Brasil ou Amrica do Sul).
Suponha que agora voc precisa gerar
um grfico do Brasil cruzando a quantidade de profissionais por estado do pas. Veja
o cdigo da Listagem 9 para isso.
Vejamos os detalhes da listagem:
Na linha 2 fizemos a substituio do packaFigura 10. Grfico em linhas usando Material Design com linha selecionada
ge para geochart, e a verso para 1 (ainda no
temos geocharts com Material Design).
Na linha 7 convertemos o vetor para DataTable, passando
Na linha 21 temos a mudana para a instanciao do objeto de
como valores os nomes das cidades. Esses nomes precisam estar
tipo google.visualization.GeoChart().
corretos, pois o geochart ir checar na base de dados do Google
Maps se eles existem.
O resultado pode ser verificado na Figura 11.
Na linha 14, no objeto options, temos definidos dois novos
Note que a barra de propores exibida na parte inferior
atributos:
esquerda do grfico se auto ajustar medida que os valores
- region: dever sempre ser preenchido com a abreviao da
aumentarem ou diminurem.
regio ou o nmero referente s coordenadas geogrficas (Por
Essa no a nica forma de distribuir os estados. Tambm
podemos dividir o mapa por todos os estados e fazer a seleo
ex: BR para Brasil, US para Estados Unidos, 002 para frica.
Voc encontrar uma lista completa dos cdigos na pgina do
por fronteiras. A nica alterao necessria modificar o valor
Google Charts).
do displayMode para region e incluir o seguinte atributo ao
- displayMode: serve para definir um dos trs tipos de grfico
objeto options:
possvel. Os valores validos so: markers, text e region (este
ltimo o valor default caso nenhum seja informado).
resolution: provinces,

Copyright - Proibido copiar ou distribuir. Todos os direitos reservados para DevMedia

13 13

Edio 04 Front-end Magazine

Google Charts: Criando Grficos dinmicos com JavaScript

Listagem 9. Cdigo para geochart que cruza quantidade de profissionais por


estado.
01 <script type=text/javascript>
02 google.load(visualization, 1, {packages:[geochart]});
03 google.setOnLoadCallback(desenharMapaRegioes);
04
05 function desenharMapaRegioes () {
06
07 var data = google.visualization.arrayToDataTable([
08 [Cidade, N. Profissionais],
09 [So Paulo, 122000],
10 [Rio de Janeiro, 85000],
11 [Pernambuco, 60000]
12 ]);
13
14 var options = {
15
region: BR,
16
width: 800,
17
displayMode: markers,
18
height: 450
19 };
20
21 var chart = new google.visualization.GeoChart(document.getElementById(chart));
22
23 chart.draw(data, options);
24 }
25 </script>

Figura 11. Geochart com distribuio de profissionais por estado

Figura 12. Geochart com distribuio de profissionais via region

14 Front-end Magazine Edio 04

14

O Google Charts entende que estados so provncias e, portanto,


se faz necessrio a incluso da palavra-chave. Veja na Figura 12 o
resultado dessa alterao.

Grficos de timeline
O conceito de timeline ficou famoso aps o advento das redes
sociais. Aplicativos como Facebook, Instagram, etc. tem como
principal recurso a exibio das postagens, por exemplo, em
uma timeline. O conceito est totalmente relacionado ao tempo:
traa-se uma linha do tempo (em anos, meses, etc.) e os eventos
so impressos nela.
No nosso exemplo, imagine que queiramos rastrear o tempo que
os funcionrios de uma empresa esto trabalhando, desde a sua
contratao at as demisses. Vejamos o cdigo da Listagem 10.
Listagem 10. Cdigo para criar timeline de tempo de trabalho dos funcionrios.
01 <script type=text/javascript>
02 google.load(visualization, 1.1, {packages:[timeline]});
03 google.setOnLoadCallback(desenharGrafico);
04
05 function desenharGrafico () {
06 var container = document.getElementById(chart);
07 var chart = new google.visualization.Timeline(container);
08 var dataTable = new google.visualization.DataTable();
09
10 dataTable.addColumn({ type: string, id: Id });
11 dataTable.addColumn({ type: string, id: Nome });
12 dataTable.addColumn({ type: date, id: Incio });
13 dataTable.addColumn({ type: date, id: Fim });
14 dataTable.addRows([
15 [Perodo, Designer: Joo Pereira, new Date(2010, 1, 15),
new Date(2011, 3, 14) ],
16 [Perodo, Arquiteto: Maria Beltro, new Date(2011, 2, 3),
new Date(2013, 1, 23) ],
17 [Perodo, Gerente: Souza Rodrigues, new Date(2010, 5, 30),
new Date(2015, 2, 3) ]]);
18
19 var options = {
20
avoidOverlappingGridLines: false,
21
width: 1000,
22
height: 450
23 };
24
25 chart.draw(dataTable, options);
26 }
27 </script>

Vejamos os detalhes:
Na linha 2 configuramos o package para timeline e a verso
para 1.1 para o Material Design.
Para criar uma timeline precisaremos tanto do objeto DataTable
quanto de um objeto do tipo google.visualization.Timeline (linha 7),
no qual setaremos os dados e o objeto options.
Na linha 10 temos a adio das colunas. Note que a primeira o identificador do perodo que dever ser obrigatoriamente uma string.
Na linha 14 preenchemos as linhas da tabela. Observe que estamos passando agora como parmetro objetos Date do JavaScript,
com o ano, ms e dia passados por parmetro, respectivamente
(padro americano).

Copyright - Proibido copiar ou distribuir. Todos os direitos reservados para DevMedia

Listagem 11. Migrando grfico de linhas para de rea.


01 <script type=text/javascript>
02 google.load(visualization, 1.1, {packages: [corechart]});
03 google.setOnLoadCallback(drawChart);
04
05 function drawChart() {
06 var data = new google.visualization.DataTable();
07
08 data.addColumn(string, Dia);
09 data.addColumn(number, Designer);
10 data.addColumn(number, Programador);
11 data.addColumn(number, Arquiteto de Software);
12 data.addColumn(number, Gerente de Projetos);
13
14 data.addRows([
15
[Dia 1 , 35.8, 80.8, 41.8, 55.5],
16
[Dia 2 , 29.9, 49.5, 32.4, 55.5],
17
[Dia 3 , 24.4, 57, 25.7, 55.5],
18
[Dia 4 , 10.7, 18.8, 10.5, 55.5],
19
[Dia 5 , 10.9, 17.6, 10.4, 50.5],
20
[Dia 6 , 7.8, 13.6, 7.7, 55.5],
21
[Dia 7 , 6.6, 12.3, 9.6, 55.5],
22
[Dia 8 , 11.3, 19.2, 10.6, 15.5],
23
[Dia 9 , 15.9, 42.9, 14.8, 55.5],

24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40

[Dia 10, 11.8, 10.9, 11.6, 55.5],


[Dia 11, 4.3, 7.9, 4.7, 55.5],
[Dia 12, 5.6, 8.4, 5.2, 55.5],
[Dia 13, 3.8, 6.3, 3.6, 55.5],
[Dia 14, 4.2, 6.2, 3.4, 55.5]
]);
var options = {
title: Desempenho profissionais/Dia,
legend: {position: bottom},
width: 800,
height: 450,
hAxis: {title: Dias, titleTextStyle: {color: black}},
vAxis: {title: PDUs, minValue: 0}
};
var chart = new google.visualization.AreaChart
(document.getElementById(chart));

41
42 chart.draw(data, options);
43 }
44 </script>

Figura 13. Grfico em formato timeline


Na linha 20, dentro do objeto options, configuramos o atributo
avoidOverlappingGridLines como false, que evitar a sobreposio das linhas da grid, ou seja, todas devem ser exibidas uma
abaixo da outra.
O resultado pode ser verificado na Figura 13.

Grficos de rea

Na linha 33 mudamos a posio da legenda para voc ver como


a API se comporta exibindo-a na parte inferior do grfico.
Os ttulos para os eixos X e Y devem vir dentro dos objetos hAxis
e vAxis, respectivamente (linhas 36 e 37).
Na linha 40 instanciamos um novo objeto do tipo google.visualization.AreaChart() para representar o grfico de rea.
O resultado da execuo pode ser observado na Figura 14.

Os grficos de rea so muito semelhantes aos de linha, exceto


pelo preenchimento completo da rea com a cor da legenda que
temos no primeiro tipo. Reaproveitando o exemplo do grfico de
linhas da Listagem 8, veja como fica o cdigo para mudar para o
de rea na Listagem 11.
Vejamos as mudanas efetuadas:
Na linha 2 mudamos o valor do package para corechart, uma
vez que os grficos de rea pertencem ao ncleo do Google
Charts.
Na linha 14 os dados devem continuar cruzados com exceo
da label de Dia que agora deve estar como obrigatria na primeira
posio do vetor. Esse valor deve ser sempre string, mas voc pode
usar as variveis v e f para mudar o texto que ser exibido.
Na linha 32, note que o ttulo agora deve estar fora do objeto
chart, o mesmo vale para o subttulo.

Figura 14. Grfico de rea usando exemplo do de linha

Copyright - Proibido copiar ou distribuir. Todos os direitos reservados para DevMedia

15 15

Edio 04 Front-end Magazine

Google Charts: Criando Grficos dinmicos com JavaScript

Perceba que o Google Charts gera uma paginao para a legenda


quando ele no consegue exibir todos os itens ao mesmo tempo.
A propriedade maxLines pode ser configurada para permitir
que as legendas ocupem mais que uma linha quando necessrio.
Alm disso, se voc passar o mouse sobre cada um dos itens
da legenda ver que a rea correspondente se destaca em cor e
sombra mais escuras.
Existem muitos outros grficos que o Google Charts disponibiliza, tais como grficos em pizza (2D e 3D), grficos de disperso,
combos, grficos em bolha, tabelas, candlesticks, dentre outros.
O importante sempre focar na diviso da implementao entre
grficos que usam o Material Design, e os que no usam, setando
sempre a verso correta para cada caso.
possvel ainda conectar os seus grficos a fontes de dados
remotas, como Web Services, arquivos CSV ou planilhas Excel
convertidas em JSON no Google Drive. Para essa finalidade,
frameworks como o jQuery, que disponibilizam funes Ajax
de requisio assncrona, ou o AngularJS que prov inmeros
servios no front-end, podem te ajudar bastante. Agora com
voc e a sua criatividade. Bons estudos!

16 Front-end Magazine Edio 04

16

Autor
Jlio Sampaio
analista de sistema e entusiasta da rea de Tecnologia da
Informao. Atualmente consultor na empresa Visagio,
trabalhando em projetos de desenvolvimento de sistemas estratgicos, tambm instrutor JAVA. Possui conhecimentos e experincia
em reas como Engenharia de Software e Gerenciamento de Projetos,
tem tambm interesse por tecnologias relacionadas ao front-end web.
Links:
Pgina oficial do Google Charts.
http://chart.apis.google.com/
Pgina do Google Live Charts Playground.
https://developers.google.com/chart/image/docs/chart_playground

Copyright - Proibido copiar ou distribuir. Todos os direitos reservados para DevMedia

Meteor.js: Construindo
aplicaes web com
Node.js e MongoDB
Saiba como integrar um quiz com o servidor

rototipagem uma prtica que permite que as


aplicaes sejam estruturadas conforme modelos
de cdigo ou via estruturas de marcao (XML,
HTML, etc.), possibilitando assim que os dados sejam
customizados em detrimento da fonte de dados. O
Meteor, ou MeteorJS, um framework web JavaScript
open-source escrito em Node.js. Ele foi inicialmente
introduzido comunidade em dezembro de 2011 com
o nome de Skybreak e foi adquirido pelo Meteor Development Group da startup Y Combinator em 2014 com o
objetivo de expandir o suporte (j fornecido) a banco
de dados.
Atravs dele conseguimos desenvolver rapidamente
cdigo de prottipos para aplicaes tanto web rodando
em browsers, quanto para dispositivos mveis (Android,
iOS, Windows Phone, etc.). Com ele, podemos tambm
facilmente integrar a aplicao com o MongoDB (Banco
de dados NoSQL baseado em documentos JSON) e usar
o protocolo DDP (Distributed Data Protocol) para propagar as mudanas nos dados para todos os clientes do
servio em tempo real sem requerer qualquer cdigo
de sincronizao especfico.
Neste artigo trataremos de esclarecer os principais
tpicos que envolvem esse framework por meio da
construo de um aplicativo de quiz de perguntas: o
usurio ter acesso a uma tela de cadastro de perguntas
e respectivas opes, assim como a lista de perguntas
j criadas ir aparecer abaixo do formulrio. O usurio
tambm ter uma pr-lista de perguntas criada quando
ele acessar a aplicao a primeira vez, j que ainda no
teremos dados populados. As informaes sero armazenadas simultaneamente no banco de dados tanto do
lado cliente quanto do servidor e qualquer alterao em
um ou outro ser automaticamente impressa no browser,
independente do cliente a acessar (Firefox, Chrome,

Fique por dentro


Este artigo tem como principal objetivo demonstrar o uso do Meteor.
js para a construo de aplicaes web que rodem tanto no cliente
quanto no servidor. Criaremos um aplicativo de quiz dinmico de
perguntas, que pode ser facilmente adaptado para outras ferramentas
de pesquisa de opinio, testes e provas online, etc. Neste, o usurio
poder criar novos tpicos e assimilar opes a cada um, tendo os
dados sincronizados em tempo real tanto no contedo web quanto
para o banco de dados.
O Meteor.js flexibiliza essa implementao ao possibilitar que o cdigo tenha o deploy feito de forma automtica, isto , sempre que salvarmos qualquer arquivo no projeto as alteraes se espelharo para
todos os clientes navegadores sem a necessidade de reload da pgina.
Alm disso, aprenderemos a lidar com os packages do framework, que
so recursos para importao de bibliotecas JavaScript de terceiros,
como o Bootstrap que usaremos para o estilo da aplicao.

WebView, etc.). No final faremos uma tela de login com o Open


Auth utilizando a API do Facebook para isso. O usurio, portanto, ser direcionado para a tela de login e, uma vez logado com
sucesso, ser redirecionado para a tela do quiz.

O que o Meteor?
O conceito de Meteor vai alm de um simples framework, ele
funciona como uma plataforma completa que envolve tecnologias
como linguagem de programao, banco de dados e servios
web. Em comparao com o AngularJS, por exemplo, que um
framework amplamente usado para integrar servios e regras de
negcio no lado front-end da aplicao, o Meteor vai alm e consegue lidar com a mesma lgica tanto no lado cliente quando no
servidor do sistema. Veja na Figura 1 uma representao grfica de
como o framework dividido bem como os tipos de ferramentas

Copyright - Proibido copiar ou distribuir. Todos os direitos reservados para DevMedia

17 17

Edio 04 Front-end Magazine

Meteor.js: Construindo aplicaes web com Node.js e MongoDB

que ele suporta. Perceba que os itens marcados em negrito representam as tecnologias que o Meteor j traz consigo por padro, ao
passo que os demais tratam-se de itens tambm aceitos mas que
precisam ser baixados e instalados no ambiente.

Alm disso, o Meteor tambm lida com os conceitos de empacotamento dos binrios do projeto via atmosphere.js ou via npm
do Node.js. Voc tambm pode usar os pacotes do Cordova/
PhoneGap para realizar esse trabalho. No mais preciso, por
exemplo, configurar o Gulp para fluxos de controle e automao
diretamente no cdigo, o Meteor j tem o prprio recurso interno
para manter todas as dependncias alinhadas e sincronizadas.
E para conectar com servios e APIs externos voc pode fazer uso
do protocolo DDP que citamos, que funciona como um gerenciador
de updates: sempre que uma mudana acontecer no servidor sua
aplicao ser notificada automaticamente.

Meteor e o JavaScript

Figura 1. Diviso dos componentes e dependncias do Meteor


O Meteor baseado em sete princpios, a saber:
Dados na rede: O Meteor no envia qualquer HTML pela rede,
em vez disso ele envia os dados e deixa que o cliente os renderize. Assim, ganhamos em performance ao trafegar bem menos
informao, tal como teramos com os Web Services baseados em
restful e JSON, por exemplo.
Uma s linguagem: O Meteor possibilita que voc escreva
ambas as partes (cliente e servidor) da sua aplicao em JavaScript. No lado cliente isso j padro por causa do browser e do
ECMAScript, no servidor o Node.js entra na jogada para habilitar
essa funcionalidade.
Banco de dados em todo logar: Voc tambm pode usar os
mesmos meios para acessar o banco de dados tanto do lado cliente
quanto do servidor. Esse tipo de estratgia difere da que vemos em
aplicaes que usam servios para conectar com o banco, gerando
requisies HTTP desnecessrias.
Compensao de latncia: No lado cliente, o Meteor pr-carrega
alguns dados e simula os modelos de dados que temos no servidor
para fazer com que as chamadas ao servidor paream instantneas. Funciona semelhante aos recursos de cache que temos
em outros frameworks server side como c3p0 do Hibernate, por
exemplo.
Update automtico das camadas: No Meteor tempo real o padro. Todas as camadas, desde o banco de dados at os templates,
se atualizam automaticamente quando necessrio. como se fosse
um hot deploy por cdigo e para camadas.
Simplicidade igual a Produtividade: O Meteor tem uma API
extremamente limpa, com cdigos e chamadas de mtodos
simples e usando todos os padres de qualidade de cdigo Java.
Consequentemente, a produtividade aumenta ao no ter de configurar tudo do zero na aplicao.

18 Front-end Magazine Edio 04

18

A principal linguagem de programao usada para desenvolver


com o Meteor o JavaScript. Mas voc tambm pode fazer uso de
similares como o CoffeeScript (que no fim gera JavaScript), jQuery,
etc. Como o Node.js baseado em JavaScript, se voc quiser ter
total suporte no lado servidor e cliente importante usar essa
linguagem como padro.
O Meteor faz uso dos nomes dos diretrios onde esto arquivados os documentos do projeto para diferenciar entre o que deve
ser executado no cliente e no servidor. Qualquer coisa que voc
colocar no diretrio \server ser qualificado para executar no
servidor, da mesma forma para a pasta \client que ser rodado
no cliente. Os arquivos presentes nas demais pastas (como \lib,
por exemplo) sero executados em ambos os lados. comum
encontrarmos situaes onde preciso executar o mesmo cdigo
tanto no cliente quanto no servidor, como a definio das colees
de dados ou validao de formulrios que precisam ter dupla
camada de segurana, por exemplo.
Entretanto, voc no est limitado a estes dois diretrios; at
mesmo em arquivos que estiverem fora deles, pode-se simplesmente usar o cdigo representado na Listagem 1 para checar
que se trata de um ou outro. Os atributos booleanos isClient e
isServer servem para identificar se estamos executando no cliente
ou servidor, respectivamente.
Listagem 1. Mtodo de verificao do diretrio atual.
if(Meteor.isClient){
// execute cdigo cliente
}
// OR
if(Meteor.isServer){
// execute cdigo servidor
}

J em relao forma como devemos importar os arquivos JavaScript (e CSS) nas pginas HTML, no necessariamente precisamos
fazer isso dentro da tag head. O Meteor seleciona todos eles,
minifica-os e os coloca na sua aplicao sozinho. Funciona de forma
semelhante ao que o CoffeeScript e o Sass fazem com os arquivos JS
e CSS, respectivamente: o Meteor tem um gerenciador de pacotes

Copyright - Proibido copiar ou distribuir. Todos os direitos reservados para DevMedia

semelhante s gems do Ruby, por exemplo, que empacota todo o


cdigo com simples comandos.
Veja o comando a seguir:
meteor add coffeescript

Ao digit-lo na interface de linha de comando voc ter habilitada a tela para digitar quaisquer comandos em CoffeeScript e eles
sero convertidos automaticamente para JavaScript e assimilados
s suas respectivas pginas HTML. Esse s um dos pacotes
dos mais de quatro mil disponveis que voc pode encontrar na
especificao do Meteor (vide seo Links para uma lista completa deles).

Sincronizao de Dados
O Meteor consegue manter todos os dados da aplicao sincronizados em ambos os lados da arquitetura, bem como as
estruturas que os guardam. Por exemplo, as colees (listas, filas,
mapas, etc.) no Meteor funcionam como encapsuladores de dados
sncronos, ou seja, se voc alterar qualquer dado no lado servidor
a mesma estrutura que o mantm no browser ser atualizada
automaticamente.
Em relao s estruturas de templates funciona da mesma forma.
O Meteor usa o sistema de templates Spacebars para isso, que
funciona de forma semelhante ao famoso Handlebars, porm
com menos manipulao do DOM para manter as coisas mais
rpidas (muito semelhante API React do Facebook que segue o
mesmo conceito). Da mesma forma que os arquivos JS e CSS, no
preciso se preocupar em compilar os templates ou sincroniz-los
manualmente, o Meteor faz tudo isso para voc.
Veja na Figura 2 uma representao grfica de como os dados
so sincronizados pelo Meteor.

Figura 2. Comunicao entre cliente/servidor no Meteor

O Meteor faz uso tanto dos WebSockets quanto do protocolo


DDP para sincronizar os dados. Se fizssemos uma comparao
com o tradicional protocolo HTTP que a maioria das aplicaes
web usa, teramos algo como:
Esse modelo o substitui por completo, criando um novo conceito
interno de arquitetura baseado em requisies assncronas.
No modelo HTTP o cliente nem sempre sabe o que o servidor
est fazendo (como informar ao cliente quando o banco de dados
atualizado) e vice-versa. uma relao separada, ao contrrio
do Meteor: tudo que o cliente faz o servidor tem conhecimento,
e vice-versa.
Na figura temos ainda uma comparao entre o modelo que faz
uso de requisies Ajax (que so amplamente usadas em conjunto
com o HTTP para aumentar a performance das aplicaes) e o do
Meteor. Veja a quantidade de requisies e a velocidade com a qual
elas trafegam no segundo grfico. Esse o segredo do Meteor:
deixar o HTTP (mais lento) de lado e no trafegar HTML pesado,
somente dados.

Banco de Dados
No Meteor temos duas representaes de banco: O Mongo e
o Minimongo. O Mongo fica localizado no servidor e uma
representao verdadeira dos dados, onde de fato sero alocadas as informaes perenes. J o Minimongo uma biblioteca
JavaScript que existe no cliente com a inteno de simular um
banco de dados. Geralmente, ele s tem um subconjunto dos
dados do Mongo (a menos que voc decida publicar todos os
dados em um objeto coleo para o cliente), entretanto, independente dos dados que voc publique o Meteor ir mant-los
sempre sincronizados: tenham sido eles alterados no cliente
ou no servidor.
Veja na Figura 3 como essa sincronizao feita no Meteor.
Esse tipo de arquitetura se encaixa perfeitamente nas que
so usadas para chats. A resposta precisa ser rpida, os dados sincronizados entre cliente-servidor e nenhum HTML
trafegado.

Figura 3. Sincronizao de dados via DBs no Meteor

Copyright - Proibido copiar ou distribuir. Todos os direitos reservados para DevMedia

19 19

Edio 04 Front-end Magazine

Meteor.js: Construindo aplicaes web com Node.js e MongoDB

Configurao do ambiente
A instalao do Meteor se d de duas formas, dependendo do
seu Sistema Operacional:
1. Se voc usa Linux ou algum dos Sistemas Operacionais baseados em OSX, basta executar a seguinte instruo no terminal
de comandos:

Ao final do processamento voc ver impressa no console a


mensagem da Figura 5.

curl https://install.meteor.com/ | sh

2. Caso tenha um Windows ento voc precisar efetuar o


download do instalador especfico na pgina do Meteor (vide
seo Links).
A primeira opo baixar os arquivos e configurar as variveis
de ambiente automaticamente. Como a maioria dos usurios usa
Windows, mostraremos como configurar no mesmo. Aps efetuar
o download do instalador, execute-o e aguarde at que ele baixe
todas as dependncias. Quando ele finalizar, uma tela igual da
Figura 4 ir aparecer solicitando o seu login/senha da conta do
Meteor. Voc pode optar por criar uma nova conta na janela ou
logar com uma j existente, assim seus dados mantm-se sincronizados em todo ambiente que trabalhar. Se no desejar, basta
clicar na opo Skip this step.

Figura 5. Mensagem de projeto Meteor criado com sucesso


Trs arquivos tambm sero criados referentes ao HTML, JS e
CSS do projeto. Este ltimo vem vazio, pois nenhum estilo foi
selecionado ainda para a aplicao ficando a seu cargo definir.
Veja o cdigo dos dois primeiros arquivos nas Listagens 2 e 3,
respectivamente.
Listagem 2. Cdigo da pgina quiz-devmedia.html.
01 <head>
02 <title>quiz-devmedia</title>
03 </head>
04
05 <body>
06 <h1>Welcome to Meteor!</h1>
07
08 {{> hello}}
09 </body>
10
11 <template name=hello>
12 <button>Click Me</button>
13 <p>Youve pressed the button {{counter}} times.</p>
14 </template>
Listagem 3. Cdigo JavaScript do arquivo quiz-devmedia.js.

Figura 4. Tela de login/nova conta do Meteor


Aps isso, voc precisar reiniciar o SO para que as alteraes
sejam salvas. Faa um teste rpido para ver se tudo ocorreu com
sucesso: abra o seu terminal de comandos cmd e digite o seguinte
comando:
meteor --version

Voc ver a verso do Meteor instalada (no formato Meteor


1.x.x.x). Agora precisamos selecionar o diretrio no qual queremos criar o nosso projeto Meteor; navegue at ele via terminal e
digite o seguinte comando:
meteor create quiz-devmedia

20 Front-end Magazine Edio 04

20

01 if (Meteor.isClient) {
02 // counter starts at 0
03 Session.setDefault(counter, 0);
04
05 Template.hello.helpers({
06 counter: function () {
07 return Session.get(counter);
08 }
09 });
10
11 Template.hello.events({
12 click button: function () {
13 // increment the counter when button is clicked
14 Session.set(counter, Session.get(counter) + 1);
15 }
16 });
17 }
18
19 if (Meteor.isServer) {
20 Meteor.startup(function () {
21 // code to run on server at startup
22 });
23 }

Copyright - Proibido copiar ou distribuir. Todos os direitos reservados para DevMedia

Perceba que na tag head (linha 1 da Listagem 2) no definimos


nenhuma tag script de importao do arquivo de JavaScript que
sabemos que o projeto faz uso. Tudo acontece por associao, o
Meteor carregar sozinho o arquivo JS e analisar o que deve ser
executado no cliente.
Na linha 8 definimos o uso do template que foi criado na
linha 11. O template deve ter sempre um name e o seu contedo
(boto e pargrafo) nunca ir aparecer, exceto se voc explicitar
isso atravs dos operadores dupla-chave {{}} no corpo da pgina.
Esse tipo de seleo comum em vrios frameworks JavaScript,
como o CoffeeScript, por exemplo.
Em relao ao JavaScript, perceba que de cara j temos a verificao de qual cdigo pertence ao cliente e qual ao servidor (isClient/
isServer). Esses valores so preenchidos automaticamente pelo
Meteor ao iniciar o servidor.
Na linha 3 da Listagem 3 adicionamos um elemento da HTML ao
escopo de sesso do Meteor. O conceito semelhante aos atributos
que temos nas linguagens de programao server side (como ASP
.NET ou Java EE) onde cada atributo sempre constitudo pelo
par nome-valor.
Na linha 5 definimos as funes helpers que so funes utilitrias de contexto. A nica funo que temos counter() que ir
retornar o valor da varivel de sesso (o Meteor trabalha com
escopos, a sesso um dos mais abrangentes; vamos falar mais
sobre eles adiante). Na linha 11 criamos os eventos, semelhante
forma como mapeamos os eventos no jQuery: atravs de seletores.
A string click button diz que a funo seguinte deve ser executada sempre que um clique for efetuado em qualquer input do
tipo button na pgina. O cdigo da funo, por sua vez, apenas
incrementa em um o valor total do contador e o salva novamente
na sesso. A funo set() da classe Session sempre sobrescreve
o valor se ele j existir, impedindo assim que tenhamos valores
duplicados na memria.
Na linha 19 temos o cdigo que roda no servidor. Como nenhuma implementao vem por padro para este escopo, a funo
est em branco.
Para executar a aplicao no basta simplesmente abrir o arquivo HTML num browser, precisamos iniciar o servidor Node.js e
subir a aplicao no mesmo. Para isso, no terminal de comandos,
adentre a pasta do projeto (via comand cd) e execute o comando
meteor. Aps isso, o Meteor vai subir as instncias do Node.js,
um proxy interno e iniciar a aplicao, mostrando ao final em
qual endereo e porta voc poder acessar (geralmente http://
localhost:3000/). Um cursor ficar piscando informando que o
servidor est levantado, para par-lo basta digitar Ctrl-C.
Acesse o endereo informado em localhost e voc ver a tela
ilustrada na Figura 6.
Qualquer alterao que fizer nos arquivos do projeto no precisa
reiniciar o servidor, ele far o deploy automtico das mudanas
e atualizar a pgina sozinho. Faa um teste: modifique o texto
dos ttulos da pgina e verifique a mensagem Client modified
refreshing que aparecer no terminal, bem como a pgina
atualizada.

Figura 6. Tela do aplicativo inicial do Meteor

Construo da aplicao
O Meteor tambm possibilita a construo da sua aplicao
diferenciando cdigo de cliente e de servidor via pastas. Ao criar
uma pasta \client e outra \server ele automaticamente direcionar
a execuo para os respectivos ambientes e no mais teremos de
usar os atributos isClient/isServer. Portanto, vamos estruturar os
nossos diretrios conforme demonstrado na Listagem 4.
Listagem 4. Estrutura de diretrios do projeto.
| .meteor
| client/
// todo o cdigo do cliente vem aqui
|----- components/
// pasta que conter cada componente do projeto
|--- quiz-devmedia-form.css
|--- quiz-devmedia-form.html
|--- quiz-devmedia-form.js
|--- quiz-devmedia.css
|--- quiz-devmedia.html
|--- quiz-devmedia.js
|----- app.body.html
// layout para a aplicao inteira
|----- app.head.html
// layout do cabealho das pginas
|----- app.js
// js global da app
|----- app.css
// css global da app
| collections/
// salvaremos os modelos do mongo
|----- quiz.js
// colees mongo
| server/
// cdigo para o servidor
|----- bootstrap.js
// datas de exemplo para iniciar a aplicao

O primeiro passo para construir a aplicao criar uma coleo


de objetos no mongo. Para isso, abra o arquivo quiz.js na pasta \
collections e adicione o seguinte contedo ao mesmo:
Quiz = new Mongo.Collection(quiz);

Isso o suficiente para a coleo de que precisamos. O motivo


de termos criado esse arquivo na pasta \collections foi porque
precisaremos dele em ambos cliente e servidor. Agora vamos
criar alguns dados de exemplo para quando nossa aplicao for
iniciada. Veja na Listagem 5 o contedo que dever ser adicionado
ao arquivo bootstrap.js.
Note que na linha 2 estamos usando a funo do Meteor startup()
que ser a primeira a ser executada quando o projeto subir no
servidor. Na linha 5 verificamos se j existe algum dado de quiz
atravs do mtodo find() do MongoDB disponvel atravs do objeto
global Quiz que criamos antes. Este mtodo lista todos os objetos
adicionados ao banco e o mtodo count() retorna a quantidade.

Copyright - Proibido copiar ou distribuir. Todos os direitos reservados para DevMedia

21 21

Edio 04 Front-end Magazine

Meteor.js: Construindo aplicaes web com Node.js e MongoDB

Listagem 5. Cdigo de inicializao do projeto.


01 // essa funo ser executada quando a app for iniciada
02 Meteor.startup(function() {
03
04 // se no tiver nenhum quiz disponvel, cria um com dados simples
05 if (Quiz.find().count() === 0) {
06 var quizSimples = [
07 {
08
pergunta: Voc gostou do Meteor?,
09
alternativas: [
10
{ texto: Sim, muito!, votos: 0 },
11
{ texto: Mais ou menos..., votos: 0 },
12
{ texto: No. Prefiro JavaScript, votos: 0 }
13
]
14 },
15 {
16
pergunta: Como voc avalia este artigo?,
17
alternativas: [
18
{ texto: ruim, votos: 0 },
19
{ texto: bom, votos: 0 },
20
{ texto: excelente, votos: 0 }
21
]
22 }
23 ];
24
25 // itera sobre todos os quizes e insere cada um no banco
26 _.each(quizSimples, function(quiz) {
27 Quiz.insert(quiz);
28 });
29 }
30 });

Caso a lista venha vazia criamos um vetor com dois objetos


preenchidos (que tem como atributos a pergunta e um outro
vetor com as alternativas) para teste. Os valores da quantidade
de votos naquela opo sero salvos como subatributos do vetor
alternativas.
Na linha 26 iteramos sobre a lista de itens do quiz e inserimos
cada um no objeto do Mongo via mtodo insert().
Uma vez que o Meteor implementa uma instncia do Mongo no
cliente, podemos executar os comandos do MongoDB diretamente
do console do browser, via ferramenta do desenvolvedor. Ao ter
salvo todos os arquivos, o Meteor j reiniciou a aplicao, portanto
os objetos que criamos j esto no banco de dados.

Figura 7. Resultado da inspeo da lista de quiz

22 Front-end Magazine Edio 04

22

Abra o seu navegador (usaremos o Chrome para os exemplos


mostrados) e, dentro da pgina que executamos no Meteor, acesse
o console de depurao. Digite o seguinte comando:
Quiz.find().fetch()

O resultado ser a impresso dos dois objetos inseridos, tal


como mostra a Figura 7. Observe que existem outros atributos
que o Meteor cria para dar suporte ao objeto quiz, como um
identificador (_id) e o tamanho do vetor (length). Isso constitui
mais um benefcio do Meteor uma vez que os dados esto sempre
disponveis para debugging sem necessitar o uso do operador
debugger ou de break points.
Nota
Consulte o site oficial do MongoDB na seo Links para ver a lista de opes disponveis via linha de
comando. Caso queira limpar o banco de dados basta executar o comando meteor reset no terminal

Template da aplicao
Precisamos configurar os nossos templates que representaro o
cabealho e corpo das pginas para que no tenhamos que replicar
o cdigo em cada uma delas. Vamos comear pela pgina app.
body.html adicionando o contedo da Listagem 6 mesma.
A pgina tem uma composio simples onde, na linha 6, importamos o template do formulrio do quiz, que enxertar a HTML
dentro da referida div. Nessa linha, o Meteor ir procurar pelo
arquivo que tenha a tag <template name=formQuiz>. Note que
as classes que estamos criando so relativas ao Bootstrap: organizadas em colunas.
Na linha 12 criamos a div que ir iterar sobre todos os itens do quiz.
Veja o forEach que usamos na linha 13, at mesmo estruturas de repetio devem estar entre os sinais de dupla chave. E mais uma vez
importamos o template do quiz na linha 14. Toda importao deve
sempre comear com o sinal de maior >, e todo fim de bloco deve
finalizar com o nome do comando precedido de uma barra /.
Vamos editar agora o arquivo do cabealho (Listagem 7).
Trata-se de um cabealho comum a outras pginas HTML.
Se voc verificar o cdigo HTML
gerado da pgina carregada no
browser perceber que dentro da
tag head temos vrios arquivos
sendo importados (JS e CSS) que
guardam toda a lgica autogerada
pelo Meteor.
Uma vez com os templates de
cabealho e rodap prontos, ainda
no podemos execut-los pois precisamos antes criar as pginas de formulrio que os usaro por padro.
Abra o arquivo quiz-devmediaform.html e adicione o contedo da
Listagem 8.

Copyright - Proibido copiar ou distribuir. Todos os direitos reservados para DevMedia

Listagem 6. Cdigo template da pgina do corpo.


01 <body>
02 <!-- Importa o formulrio de criao do quiz aqui -->
03 <div class=container>
04 <div class=row>
05 <div class=col-md-6 col-md-offset-3>
06
{{ >formQuiz }}
07 </div>
08 </div>
09 </div>
10
11 <!-- Itera sobre os quizes, exibindo-os -->
12 <div class=quiz>
13 {{ #each quizes }}
14
{{ >quiz }}
15 {{ /each }}
16 </div>
17 </body>

No momento, o usurio estar limitado a criar somente trs


opes de escolha por simplicidade, mas voc pode adicionar
quantas desejar, inclusive criar um mecanismo para adicionar
mais campos dinamicamente. Para no deixar a exibio comprometida, vamos adicionar algum CSS ao arquivo quiz-devmediaform.css (Listagem 9).
Agora volte novamente pgina e veja o resultado (Figura 8).
Mesmo com as classes do Bootstrap adicionadas, nenhum estilo
relacionado ao mesmo foi impresso porque ainda precisamos
import-lo (faremos isso mais frente).
Vamos criar agora o contedo da pgina quiz-devmedia.html de
fato. nela que iremos iterar a lista de perguntas que debugamos
e exibi-las. Veja o cdigo contido na Listagem 10.

Listagem 7. Cdigo template da pgina de cabealho.


01 <head>
02 <meta charset=utf-8>
03 <title>Meu Quiz DevMedia!</title>
04
05 <!-- Todo o contedo CSS ser carregado aqui automaticamente -->
06 </head>
Listagem 8. Cdigo HTML da pgina de formulrio do quiz.
01 <template name=formQuiz>
02 <form>
03
<div class=form-group>
04
<label>Pergunta</label>
05
<input type=text name=pergunta class=form-control
placeholder=Sua Pergunta>
06
</div>
07
08
<div class=form-group>
09
<label>Opo #1</label>
10
<input type=text name=opcao1 class=form-control
placeholder=Opo #1>
11
</div>
12
<div class=form-group>
13
<label>Opo #2</label>
14
<input type=text name=opcao2 class=form-control
placeholder=Opo #2>
15
</div>
16
<div class=form-group>
17
<label>Opo #3</label>
18
<input type=text name=opcao3 class=form-control
placeholder=Opo #3>
19
</div>
20
21
<button type=submit class=btn btn-lg btn-primary btn-block>
Criar Quiz</button>
22 </form>
23 </template>

Dessa vez temos somente contedo HTML. Note que a tag


<template> marca o contedo a ser importado; o nome tambm
tem de ser igual aos usados na importao da pgina de corpo.
Note tambm que cada campo de input tem configuradas as propriedades name (que ser usada para recuperar o valor do campo
mais frente), class (com o CSS do Bootstrap) e placeholder (que
contm a dica do campo quando nada tiver sido preenchido).

Figura 8. Formulrio do Quiz com CSS inicial


Listagem 9. Cdigo CSS para estilo inicial da pgina de formulrio do quiz.
/* Seu CSS vem aqui */
.pergunta-group {
margin-bottom:20px;
background:#EEE;
padding:20px;
}
.pergunta-group label {
font-size:18px;
}
Listagem 10. Cdigo da pgina quiz-devmedia.html.
01 <template name=quiz>
02 <div class=quiz well well-lg data-id={{ _id }}>
03
04
<h3>{{ pergunta }}</h3>
05
06
{{ #each indexedArray alternativas }}
07
<a href=# class=voto btn btn-primary btn-block data-id={{ _index }}>
08
<span class=votos pull-right>{{ votos }}</span>
09
<span class=text>{{ texto }}</span>
10
</a>
11
{{ /each }}
12 </div>
13 </template>

Na linha 1 criamos um novo template de nome quiz que ser


importado na pgina de corpo. Na linha 4 acessamos os valores da
propriedade pergunta envolvendo em uma tag h3 de ttulo. Aps
isso, na linha 6, iteramos sobre a lista de alternativas disponveis
imprimindo-as em forma de link para que o usurio possa clicar
e votar na opo; e dentro de cada link exibiremos a quantidade
atual de votos e o texto da descrio.

Copyright - Proibido copiar ou distribuir. Todos os direitos reservados para DevMedia

23 23

Edio 04 Front-end Magazine

Meteor.js: Construindo aplicaes web com Node.js e MongoDB

O atributo data-id definido na linha 7 com o valor _index ser


responsvel por identificar cada questo com um nmero de
sufixo.
Agora precisamos dar pgina do corpo acesso ao banco de
dados. Para fazer isso precisamos atribuir a varivel do Mongo
ao template. Veja na Listagem 11 esse cdigo que dever estar
contido no arquivo app.js.
Esse cdigo disponibiliza a funo quizes para ser acessada na
pgina de corpo. A sua nica funo acessar o banco de dados
e retornar a lista de quizes.
Perceba que tambm adicionamos o vetor indexedArray ao forEach das perguntas. Isso foi feito porque no temos acesso direto
aos ndices quando iteramos sobre listas no Meteor. Esse um
tipo de recurso bsico que os desenvolvedores do Meteor esto
trabalhando para incluir nas prximas verses. Logo, precisamos
criar esse vetor dentro do app.js tal como na Listagem 12.

Para recuperar o valor de um campo pelo nome basta acessar o


objeto event e a propriedade target com o nome do respectivo
campo. J as propriedades votos iniciam vazias.

Listagem 11. Cdigo para funes helper no app.js.

Figura 9. Formulrio do quiz com perguntas exibidas

01 Template.body.helpers({
02 quizes: function() {
03 return Quiz.find();
04 }
05 });

Listagem 13. Funes de eventos no JS do formulrio.

Listagem 12. Cdigo para o vetor indexedArray de iterao.


01 // add um ndice a cada item
02 UI.registerHelper(indexedArray, function(contexto, opcoes) {
03 if (contexto) {
04 return contexto.map(function(item, indice) {
05 item._index = indice;
06 return item;
07 });
08 }
09 });

Esse trecho de cdigo se comunica diretamente com o atributo data-id que criamos antes: ele apenas cria uma espcie de
registro para cada ndice e todo o trabalho feito pela funo
registerHelper() interna API do Meteor. Dessa forma, agora
podemos visualizar as opes na tela recarregada mesmo que
sem estilo algum (Figura 9).

Eventos do Formulrio
Com toda a estrutura preparada, precisamos agora adicionar os
eventos e variveis aos templates. Cada arquivo de formulrios
HTML tem um arquivo JavaScript correspondente. Vamos comear pelo quiz-devmedia-form.js (Listagem 13).
A funo events (linha 1) deve ser usada sempre que se deseja
adicionar eventos a um template. Na linha 3 estamos mais uma
vez recuperando o objeto formulrio via seletores do Meteor. Na
linha 6 impedimos que o usurio efetue mais de um clique no
boto de submit.
Na linha 9 criamos uma nova instncia do vetor de perguntas recuperando cada um dos valores digitados nos campos do formulrio.

24 Front-end Magazine Edio 04

24

01 Template.formQuiz.events({
02 // lida com o submit do formulrio
03 submit form: function(event) {
04
05 // impede que o formulrio envie mais de uma vez
06 event.preventDefault();
07
08 // recupera os dados do form
09 var novoQuiz = {
10 pergunta: event.target.pergunta.value,
11 alternativas: [
12
{ text: event.target.opcao1.value, votos: 0 },
13
{ text: event.target.opcao2.value, votos: 0 },
14
{ text: event.target.opcao3.value, votos: 0 }
15 ]
16 };
17
18 // cria o novo quiz
19 Quiz.insert(novoQuiz);
20 }
21 });

Finalmente, na linha 19 inserimos o atributo no objeto Quiz


do Mongo. Mas ainda precisamos adicionar os eventos de votar
para quando o usurio clicar no link de cada opo. Portanto,
abra o arquivo quiz-devmedia.js e edite-o com o contedo da
Listagem 14.
Na linha 3 mapeamos a seleo para o evento de click da classe
CSS .voto na pgina. Na linha 6 prevenimos o duplo click novamente e na linha 9 selecionamos o id do objeto pai do quiz que
ser usado para distinguir entre as opes do quiz filho.
Na linha 15 adicionamos o valor inicial de cada item do quiz,
enquanto na linha 18 incrementamos em um a quantidade de
votos para aquela opo em especfico. O operador #inc ser
responsvel por isso.

Copyright - Proibido copiar ou distribuir. Todos os direitos reservados para DevMedia

Listagem 14. Funes de eventos no JS do quiz.


01 Template.quiz.events({
02 // evento para lidar com o click na opo
03 click .voto: function(event) {
04
05 // impede o click duplo
06 event.preventDefault();
07
08 // recupera o id do quiz pai
09 var idQuiz = $(event.currentTarget).parent(.quiz).data(id);
10 var idVoto = $(event.currentTarget).data(id);
11
12 // cria o objeto de incremento
13 var voteString = alternativas. + idVoto + .votos;
14 var action = {};
15 action[voteString] = 1;
16
17 // incrementa o nmero de votos para esta opo
18 Quiz.update(
19 { _id: idQuiz },
20 { $inc: action }
21 );
22 }
23 });

Aguarde at o processamento terminar e a mensagem de sucesso


ser exibida. Agora s retornar pgina e todo o design do projeto
ter mudado igual ao que vemos na Figura 11.

Agora s ir at a pgina e clicar nas opes. Voc ver os


itens sendo atualizados (Figura 10). Se voc publicar a aplicao
e tiver vrias pessoas usando poder ver os itens atualizando
automaticamente em todas as pginas. Faa um teste, abra a sua
aplicao em dois browsers distintos e incremente as opes em
um observando elas se atualizarem no outro.
Figura 11. Pgina do quiz com o Bootstrap

Login OAuth com Facebook

Figura 10. Formulrio do Quiz com opes incrementadas

Estilo com Bootstrap


Vamos adicionar agora o Bootstrap aplicao para aplicar
alguns estilos rpidos. Uma das vantagens ao se trabalhar com
o Meteor que s precisamos instalar os pacotes das bibliotecas
de terceiros via linha de comando para que sejam reconhecidas
pelo projeto, nada mais. Para importar o Bootstrap de maneira
tradicional teramos de baixar o pacote, descompactar e mover
para a pasta do projeto, alm de referenciar os arquivos certos
nas tags link e script do cabealho e lidar com problemas de
verso.
Com o Meteor s precisamos adicionar esse package ao nosso
projeto e pronto. Para isso, execute o seguinte comando no terminal de comandos dentro da pasta do projeto:
meteor add twbs:bootstrap

Um dos pacotes que o Meteor disponibiliza dentro da sua especificao o pacote de autenticao do Facebook. Esse tipo de
recurso, conhecido como Open Authentication, muito comum nas
aplicaes web para facilitar o acesso dos usurios s mesmas sem
perder tempo criando um cadastro completo. Os mesmos passos
tambm podem ser seguidos para implementar usando a API do
Google Plus e Twitter, entre outras.
O primeiro passo criar uma aplicao na pgina de desenvolvedores do Facebook (vide seo Links). No menu Apps selecione a
opo Add a New App e escolha o tipo de aplicao a qual deseja
logar: Site. D um nome mesma: Meteor-Teste, e clique em Criar.
Quando estiver criada, v at a opo Test Apps no menu da
lateral esquerda e clique no boto Create a Test App. Voc ser
redirecionado para a popup demonstrada na Figura 12. Informe
um nome para o App de teste e clique em Create Test App. Voc
ser levado a uma nova popup para confirmar um captcha.
Aps isso, a aplicao de teste estar configurada. V at o menu
Settings e clique no boto + Add Platform, selecionando a opo
Site novamente. No campo Site URL informe o endereo que
estamos testando: http://localhost:3000 e clique em Save Changes
(para toda alterao sempre clique no boto de salvamento que fica
no fim da pgina, seno suas configuraes sero perdidas).

Copyright - Proibido copiar ou distribuir. Todos os direitos reservados para DevMedia

25 25

Edio 04 Front-end Magazine

Meteor.js: Construindo aplicaes web com Node.js e MongoDB

Agora v na aba Advanced na mesma pgina e na seo OAuth


Settings, dentro do campo Valid OAuth redirect URIs coloque a
seguinte URL: http://localhost:3000/_oauth/facebook?close. Essa
URL representa o endereo de redirecionamento para o qual o
Facebook deve enviar a resposta requisio de login.
Com as configuraes feitas s precisamos voltar pgina de
detalhes do app e copiar as informaes de App ID e App Secret
que sero usadas pelo nosso cdigo.
Para configurar o acesso no lado do Meteor precisamos primeiro
adicionar os pacotes do OAuth e Facebook como dependncia ao
projeto. Para isso, v at o terminal de comandos e, de dentro do
projeto, execute os seguintes comandos:
meteor add accounts-facebook
meteor add service-configuration

Eles criaro os pacotes do login via Facebook e das configuraes do mesmo servio, respectivamente. Aguarde at que eles
finalizem, v at o projeto e crie trs novos arquivos: login.html e
login.js no diretrio \client e social-config.js no diretrio \server.
Os dois primeiros sero responsveis por conter os cdigos HTML
e JavaScript para o login e o ltimo tratar das configuraes
de login, bem como guardar os dados da autenticao. Vamos
comear por este ento: abre o arquivo e adicione o contedo da
Listagem 15.
A classe ServiceConfiguration, que agora disponvel atravs dos
imports que fizemos, faz todo o trabalho de remover o servio
do Facebook (caso ele j exista) e adicionar novamente. Na insero que fazemos na linha 5 precisamos informar o nome do
servio de autenticao, o id da aplicao que criamos e a senha
(app secret).
E para exibir a pgina com o boto de login vamos criar um
novo template e adicionar ao arquivo login.html que criamos
(Listagem 16).
O template traz novas configuraes que envolvem o uso de
servios e de usurios. O objeto currentUser refere-se ao usurio
global logado no momento. Dentro dele podemos acessar o objeto
services que, por sua vez, ter o objeto facebook como dependncia. Os valores de nome, gnero, etc. devem ser acessados com as

Figura 12. Popup para confirmar nome do novo app de teste

26 Front-end Magazine Edio 04

26

palavras-chave respectivas em ingls. H cada nova tecnologia


OAuth adicionada mais objetos ficam disponveis dentro do services (Twitter, Google, etc.).
A estruturas condicionais que vemos nas linhas 2 e 6 funcionam
como um if-else comum, sendo que o primeiro teste verifica se
o usurio diferente de null, mesmo sem precisar explicitar o
teste no cdigo. Assim, montamos dois botes distintos para cada
situao: um para login e outro para logout.
Listagem 15. Cdigo de configurao da autenticao com o Facebook.
01 ServiceConfiguration.configurations.remove({
02 service: facebook
03 });
04
05 ServiceConfiguration.configurations.insert({
06 service: facebook,
07 appId: seu_App_Id,
08 secret: sua_Senha_do_App
09 });
Listagem 16. Cdigo de definio do template de login.
01 <template name=login>
02 {{#if currentUser}}
03
{{currentUser.services.facebook.name}} 04
{{currentUser.services.facebook.gender}}
05
<button id=logout class=btn btn-lg btn-primary btn-danger>
Logout</button>
06 {{else}}
07
<button id=facebook-login class=btn btn-lg btn-primary btn-block>
Login com Facebook</button>
08 {{/if }}
09 </template>

Ainda precisamos definir os eventos de click nestes botes.


Portanto, abra o arquivo login.js e adicione o contedo da
Listagem 17.
Na linha 2 mapeamos o seletor do click nos campos de id facebook-login atribuindo a funo conseguinte ao mesmo. A mesma
funo se encarrega de chamar o mtodo loginWithFacebook()
da API do Meteor recebendo como resposta o objeto de erro e
lanando uma exceo caso algum acontea. Na linha 10 criamos
a funo de logout que far o mesmo processo de chamada API
lanando uma mensagem de erro caso algo
de errado acontea.
Para finalizar precisamos abrir o arquivo
app.body.html e modificar a importao do
template da linha 6 para >login e comentar (ou
remover) a div de quiz que ir aparecer junto
da outra. Feito isso, podemos ir no browser e
verificar o resultado (Figura 13).
Aps clicar no boto de Login voc ver uma
nova janela abrir igual da Figura 14. Clique
em OK e voc ser autenticado com sucesso,
tendo como resultado a pgina da Figura 15.
Se desejar deslogar da aplicao, basta clicar
no boto e voc ser redirecionado para a

Copyright - Proibido copiar ou distribuir. Todos os direitos reservados para DevMedia

Listagem 17. Cdigo de criao dos eventos de click para o template de login.
01 Template.login.events({
02 click #facebook-login: function(event) {
03
Meteor.loginWithFacebook({}, function(err){
04
if (err) {
05
throw new Meteor.Error(Login com Facebook falhou);
06
}
07
});
08 },
09
10 click #logout: function(event) {
11
Meteor.logout(function(err){
12
if (err) {
13
throw new Meteor.Error(Logout falhou);
14
}
15
})
16 }
17 });

Figura 13. Pgina de login com o Facebook

pgina inicial. Para unir a implementao do quiz com a de login,


podemos adicionar uma condio na div que engloba o mesmo
verificando se o usurio atual existe, tal como na Listagem 18.
Listagem 18. Div de quiz com condio para usurio logado.
{{#if currentUser}}
<div class=quiz>
{{ #each quizes }}
{{ >quiz }}
{{ /each }}
</div>
{{/if }}

Notas de Produo
Uma vez que estamos trabalhando em ambiente de desenvolvimento, todas as colees de dados so publicadas automaticamente no nosso servidor e assimiladas pelo cliente. No queremos esse
tipo de comportamento quando a aplicao estiver em produo.
O mais apropriado seria termos cada usurio subscrevendo somente os dados que ele est trabalhando naquele momento.
Dentro do diretrio .meteor/packages temos um pacote chamado
autopublish. Precisamos remov-lo para que essa funcionalidade
funcione como queremos. Execute ento o comando a seguir de
dentro do terminal:
meteor remove autopublish

Em relao publicao e deploy do projeto para um ambiente


real e na internet, se voc no tiver um servidor alocado para isso
pode usar o servio de postagem de aplicaes do prprio Meteor.
V at o terminal e execute o comando:
meteor deploy <nome da sua app>.meteor.com

Figura 14. Pgina de confirmao do login com o Facebook

Figura 15. Autenticao com sucesso. Pgina de Logout

Se certifique de substituir o <nome da sua app> por um nome real e


curto. Ao execut-lo voc estar enviando uma solicitao ao Meteor
para criar um subdomnio particular, mas para isso ele precisa ser
nico, logo se o nome que voc escolher j existir, uma tela de erro
aparecer informando: Sorry, that site belongs to a different user
(Desculpe, este site j pertence a um usurio diferente).
Obviamente, este artigo foi apenas um pequeno passo no caminho que ainda h para percorrer com o Meteor. Mas foi o suficiente para fornecer uma impresso completa sobre o potencial
desse framework. importante que voc tenha em mente que o
Meteor no uma soluo universal e podem existir situaes
onde a realidade do seu projeto leve a usar outros frameworks.
Por exemplo, se o seu sistema no necessita dessa integrao entre
cliente e servidor automtica ou j tem um mdulo desenvolvido
no servidor e precisa apenas do cliente, ento no compensa usar o
Meteor, voc pode fazer uso de outros frameworks mais robustos
para essa finalidade como AngularJS ou Backbone.
O Meteor tambm tem uma feature muito interessante chamada Iron Router, que adiciona roteadores de URLs aos servios

Copyright - Proibido copiar ou distribuir. Todos os direitos reservados para DevMedia

27 27

Edio 04 Front-end Magazine

Meteor.js: Construindo aplicaes web com Node.js e MongoDB

e pginas configuradas nele, flexibilizando muito a navegao


do usurio. Voc tambm pode integrar suas aplicaes a web
services com restful atravs da API RESTivus, testes unitrios
atravs do framework Velocity e validao de esquemas por meio
da Collection2. O segredo aprender a usar o gerenciador de pacotes Atmosphere.js para importar os pacotes e incorporar cada
vez mais recursos ao seu sistema.

Autor
Jorge Rodrigues
especialista em SEO e marketing na web, e freelancer no
universo mobile e front-end, tendo domnio sobre tecnologias
como CoffeeScript, JavaScript, HTML5 e Meteor.js. J trabalhou
em diversas empresas de TI tendo acumulado mais de dois anos de
experincia.
Links:
Pgina oficial de instalao do Meteor.
https://www.meteor.com/install
Pgina de desenvolvedores do Facebook.
https://developers.facebook.com/
Pgina oficial do MongoDB.
https://www.mongodb.com/

28 Front-end Magazine Edio 04

28

Copyright - Proibido copiar ou distribuir. Todos os direitos reservados para DevMedia

Primeiros passos com a


Google Dart
Principais tpicos para execuo em client e
server side

m meados de 2007 o Google inaugurou a sua primeira linguagem de programao, a linguagem


Go ou golang, iniciando um ciclo de lanamentos
futuros que desencadeariam em poderosas ferramentas
como AngularJS, GWT e App Engine. Inicialmente,
as linguagens assumiam caractersticas estruturadas
e estticas, em detrimento da ampla adoo que a
empresa fazia (e ainda faz) de linguagens como C e
C++. Mas com o tempo, a necessidade de abraar os
universos front-end, mobile e server side ao mesmo
tempo fez com a empresa criasse uma nova linguagem:
a Google Dart.
A Dart uma linguagem desenhada orginalmente
para a web, que foi concebida na conferncia GOTO na
Dinamarca em outubro de 2011, em um projeto fundado
pelos desenvolvedores Lars Bark e Kasper Lund. Como
toda linguagem client side, a Dart precisou passar por
uma bateria de testes junto ECMA International para
verificar seu funcionamento em browsers modernos,
tendo assim sua primeira especificao aprovada e
liberada para a comunidade.
De acordo com o site do projeto a Dart foi desenhada
para facilmente escrever ferramentas de desenvolvimento para aplicaes web modernas e capacitadas para
ambientes de alta performance. Dentre as principais
caractersticas da linguagem, podemos citar:
baseada em compilao de cdigo JavaScript;
Baseada em classes;
Orientada a objetos;
Tem sintaxe baseada na linguagem C;
Implementa heranas simples;
E suporta os principais tpicos da OO: interfaces,
classes abstratas, genricos e tipos opcionais.
Neste artigo abordaremos os principais conceitos da
nova linguagem, sua sintaxe, principais estruturas programticas, suas bibliotecas e seu SDK, alm da grande
quantidade de pacotes pblicos disponveis para impor-

Fique por dentro


A maioria das arquiteturas atuais faz uso de plataformas e linguagens
diferentes em ambos os lados cliente e servidor, o que muitas vezes
leva a cdigo duplicado e complexidade aumentada, isso sem falar
dos custos de manuteno e declnio da produtividade da equipe.
Foi pensando nisso que o Google criou a linguagem de programao
Dart, com o intuito de facilitar a forma como integramos a aplicao
como um todo.
Neste artigo veremos os principais tpicos acerca dessa linguagem:
como ela lida com a Orientao a Objetos, sintaxe, responsividade,
manipulao de erros, classes, interfaces, dentre outros. No fim, o
leitor estar apto a introduzir a linguagem nos seus projetos sem se
preocupar em perder o poder que tinha antes ao usar JavaScript e
Node.js, uma vez que ela gera a converso para essas e muitas outras
tecnologias.

tao nos seus projetos (conceito semelhante ao de frameworks


como Grunt e React).

Configurao do ambiente
Para se trabalhar com a Dart a primeira coisa a se fazer efetuar
o download da linguagem, juntamente com o Dark Editor, a Dart
SDK e o web browser Chrommium que traz consigo uma VM
Dart pr-construda e disponibilizada gratuitamente. Para isso,
acesse o site oficial disponvel na seo Links e clique no boto
Get Started. Aps isso, voc ser redirecionado para a pgina de
definio da plataforma, conforme mostra a Figura 1.
Selecione o seu Sistema Operacional, depois clique na opo
Editor + SDK para selecionar o instalador completo e no final
os itens na seo Download Dart Editor iro aparecer para voc
identificar se o seu SO 32 ou 64 bits.
Posicione o zip baixado na pasta onde voc deseja criar os seus
projetos Dart, e descompacte-o l. Neste arquivo estar contido o
executvel do Dart Editor, basta execut-lo e voc ver uma IDE
semelhante da Figura 2 aparecer.

Copyright - Proibido copiar ou distribuir. Todos os direitos reservados para DevMedia

29 29

Edio 04 Front-end Magazine

Primeiros passos com a Google Dart

Perceba como a interface muito prxima


da IDE Eclipse, isso porque o Google usou
o ncleo do projeto Eclipse (que free e
open source) para construir uma nova ferramenta de desenvolvimento. Esse tipo de
estratgia muito usado no mercado para
construir IDEs como Spring IDE, MyEclipse e as ferramentas Rational da IBM.
O pacote Dart SDK j vem selecionado e

Figura 1. Pgina de download com opes selecionadas

Figura 2. Interface do Dart Editor

30 Front-end Magazine Edio 04

30

no deve ser removido da IDE para que a


linguagem funcione corretamente.
A Dart pode ser usada para criar aplicaes que no estejam presas ao HTML, de
fora do browser. Para isso, basta integrar
o seu ambiente ao Node.js. Porm, como a
maioria das aplicaes so feitas visando o
JavaScript, trataremos de focar num exemplo inicial onde exibimos um menu de

navegao no browser e o usurio poder


clicar no mesmo e ser redirecionado para
duas telas: uma para inverter o texto num
campo de input e outra com informaes
sobre o site. Este exemplo nos permitir
entender como a linguagem lida com os
eventos de pginas HTML.
A Dart possibilita que criemos vrias sortes de aplicaes (a maioria com tecnologia
Google) como projetos:
Console Application: aplicaes de
execuo direta via terminal de comandos,
atravs da gerao de arquivos .bat ou
equivalentes de cada SO;
App Engine Application: aplicaes
focadas na Google App Engine, para execuo na nuvem do Google;
Chrome App: aplicaes ou plugins para
o navegador Google Chrome;
Dart Package: para criar um componente modularizado da Dart;
Polymer Web Server: para hospedar
aplicaes desenvolvidas com o framework
JavaScript Polymer.js;
Web Applications: aplicaes web simples, com suporte a JavaScript/bibliotecas,
HTML e CSS.
Para isso, v at o menu File > New
Application. Preencha os campos Application name com o nome da aplicao e
Parent directory com o diretrio onde
deseja salv-la. Vamos dar o nome de
AloMundoDart. Mantenha a checkbox
Generate sample content marcada para
que a wizard de criao j nos traga uma
estrutura pr-criada, e selecione a opo
Web application na lista que aparecer
logo abaixo. Clique em Finish. Isso ir
gerar uma estrutura de projeto igual da
Figura 3.
A pasta lib conter todos os arquivos
de script da Dart, inclusive com dois gerados para o exemplo criado pela wizard.
A pasta web guarda todo tipo de contedo relacionado ao front-end: imagens,
CSS, arquivos HTML, favicons e outros
arquivos .dart.
Antes de executar o projeto, faamos
algumas alteraes. Abra o arquivo nav_
menu.dart e substitua seu contedo pelo
representado na Listagem 1. Vejamos
alguns detalhes da implementao:

Copyright - Proibido copiar ou distribuir. Todos os direitos reservados para DevMedia

Figura 3. Estrutura de pastas do projeto recm-criado


Listagem 1. Contedo do arquivo nav_menu.dart.
01 // Copyright (c) 2015, DevMedia. All rights reserved. Use of this source code
02 // is governed by a BSD-style license that can be found in the LICENSE file.
03
04 library nav_menu;
05
06 import dart:html;
07
08 initNavMenu() {
09 var navdrawerContainer = querySelector(.navdrawer-container);
10 var appbarElement = querySelector(.app-bar);
11 var menuBtn = querySelector(.menu);
12 var main = querySelector(main);
13
14 closeMenu(e) {
15 document.body.classes.remove(open);
16 appbarElement.classes.remove(open);
17 navdrawerContainer.classes.remove(open);
18 }
19
20 toggleMenu(e) {
21 document.body.classes.toggle(open);
22 appbarElement.classes.toggle(open);
23 navdrawerContainer.classes.toggle(open);
24 navdrawerContainer.classes.add(opened);
25 }
26
27 main.onClick.listen(closeMenu);
28 menuBtn.onClick.listen(toggleMenu);
29 navdrawerContainer.onClick.listen((event) {
30 if (event.target.nodeName == A || event.target.nodeName == LI) {
31 closeMenu(event);
32 }
33 });
34 }

Na linha 4 declaramos o nome da biblioteca que estamos implementando (que tambm pode ser empacotada e importada
como um componente independente em outros projetos). Essa
biblioteca ser responsvel por gerenciar o menu de navegao
da nossa pgina.
Na linha 6 importamos a biblioteca html da Dart. Todos os imports
devem ser sempre feitos usando a sintaxe fabricante:biblioteca.
Da linha 9 linha 12 estamos recuperando os elementos
HTML referentes s divs de container, botes e barra de menu.

A funo querySelector() recebe o seletor do elemento a ser recuperado e varre a pgina buscando-o, caso exista mais de um, um
vetor ser criado e associado.
As funes closeMenu() e toggleMenu() (linhas 14 e 20) apenas
tratam de mudar as classes CSS dos mesmos elementos recuperados para que eles mudem de estilo quando um item de menu
for selecionado e desselecionado. A funo remove(), por sua vez,
remove a classe CSS passada por parmetro do elemento, enquanto toggle() testa se a classe j existe, seno ela insere a informada
como argumento. J a funo add() (linha 24) adiciona a classe
informada ao elemento HTML.
Nas linhas 27 a 29 definimos o ouvinte de click dos componentes
de menu para executar as funes de navegao de pgina. Na
Dart, sempre usamos os mesmos atributos dos eventos ouvintes
on para informar qual evento deve ser executado. J a funo
listen() da API da Dart recebe uma segunda funo como parmetro para ser executada sempre que o click for efetuado. Veja que a
Dart tambm nos permite criar funes annimas (linha 30) em
vez de defini-las sempre em funes separadas.
Agora abra o arquivo reverser.dart que conter o cdigo de reverso dos textos e adicione o contedo da Listagem 2.
Listagem 2. Contedo do arquivo reverser.dart.
01 // Copyright (c) 2015, DevMedia. All rights reserved. Use of this source code
02 // is governed by a BSD-style license that can be found in the LICENSE file.
03
04 library reverser;
05
06 import dart:html;
07
08 InputElement get _inputElement => querySelector(#nome);
09 Element get _outputElement => querySelector(#out);
10
11 // Exemplo de gancho no DOM e resposta s mudanas de campos de entrada.
12 initReverser() {
13 // Revete assim que o cdigo inicia.
14 _reverse();
15
16 // Reverte h cada soltura de tecla.
17 _inputElement.onKeyUp.listen((_) => _reverse());
18 }
19
20 _reverse() {
21 _outputElement.text = _inputElement.value.split().reversed.join();
22 }

Vejamos alguns detalhes:


Na linha 4 definimos novamente o nome da biblioteca, e na
linha 6 a importao da lib html.
Na linha 8 recuperamos o campo de input do nome a ser digitado
e adicionamos a um objeto InputElement da API da Dart.
Na linha 9 recuperamos o elemento referente ao campo de
output (a Dart disponibiliza essa e outras novas tags HTML) que
imprimir o texto reverso.
Na linha 20 chamamos a funo _reverse() que simplesmente
acessa o valor do campo de input, quebra-o em um vetor de chars

Copyright - Proibido copiar ou distribuir. Todos os direitos reservados para DevMedia

31 31

Edio 04 Front-end Magazine

Primeiros passos com a Google Dart

(split) e chama a propriedade reversed que ser responsvel por


reverter as posies do vetor. No fim, chamamos a funo join()
que une o vetor em uma string novamente e o adiciona propriedade text (como se trata de um campo de output, no usamos o
value dos input, e sim text) do elemento.
Finalmente, na linha 17 implementamos o evento de onKeyUp
para quando o usurio digita algo no campo e associamos a funo _reverse() ao mesmo.
Agora precisamos editar o arquivo main.dart que representa o
escopo inicial de execuo do framework, isto , ele sempre ir
carregar os demais arquivos dart a partir deste. Para isso, adicione
o contedo da Listagem 3 ao mesmo.
Listagem 3. Contedo do arquivo main.dart.
01 // Copyright (c) 2015, DevMedia. All rights reserved. Use of this source code
02 // is governed by a BSD-style license that can be found in the LICENSE file.
03
04 import dart:html;
05
06 import package:AloMundoDart/nav_menu.dart;
07 import package:AloMundoDart/reverser.dart;
08 import package:route_hierarchical/client.dart;
09
10 void main() {
11 initNavMenu();
12 initReverser();
13
14 // Webapps precisam de routing para ouvir as mudanas na URL.
15 var router = new Router();
16 router.root
17 ..addRoute(name: sobre, path: /sobre, enter: showSobre)
18 ..addRoute(name: home, defaultRoute: true, path: /, enter: showHome);
19 router.listen();
20 }
21
22 void showSobre(RouteEvent e) {
23 // Extremely simple and non-scalable way to show different views.
24 querySelector(#home).style.display = none;
25 querySelector(#sobre).style.display = ;
26 }
27
28 void showHome(RouteEvent e) {
29 querySelector(#home).style.display = ;
30 querySelector(#sobre).style.display = none;
31 }

Vejamos alguns detalhes:


Nas linhas 6 a 8 vemos a importao dos dois arquivos de script
dart que criamos antes, alm de um novo client.dart. Esse arquivo ser herdado da API para implementar o routing das pginas,
ou seja, lidar com as mudanas de URL de acordo com as aes
definidas para cada pgina.
Na linha 15 criamos um novo objeto Router, que se encarrega
de definir as rotas possveis para a aplicao como um todo.
O mtodo addRoute() recebe alguns parmetros, a saber:
- name: nome da rota.
- path: URL relativa do caminho interno da rota.
- enter: recebe a funo a ser chamada quando essa rota for
acessada.

32 Front-end Magazine Edio 04

32

- defaultRoute (opcional): booleano para definir se a rota


atual a padro.
Os mtodos showHome e showSobre se encarregam de exibir e
esconder as divs de contedo da pgina. Estas devem ser incrementadas medida que as pginas aumentam na aplicao.
Para finalizar, vamos editar a pgina HTML index.html. Ela um
pouco extensa, ento vamos dividir em duas partes: cabealho/navegao (Listagem 4), e pgina de converso/pgina de sobre.
Listagem 4. Contedo do cabealho e div de navegao da pgina index.html.
01 <!DOCTYPE html>
02
03 <html>
04 <head>
05 <meta charset=utf-8>
06 <meta http-equiv=X-UA-Compatible content=IE=edge>
07 <meta name=viewport content=width=device-width, initial-scale=1.0>
08 <meta name=scaffolded-by content=https://github.com/google/stagehand>
09 <title>AloMundoDart</title>
10
11 <!-- Add homescreen pelo Chrome no Android -->
12 <meta name=mobile-web-app-capable content=yes>
13 <link rel=icon sizes=192x192
href=images/touch/chrome-touch-icon-192x192.png>
14
15 <!-- Add homescreen pelo Safari no iOS -->
16 <meta name=apple-mobile-web-app-capable content=yes>
17 <meta name=apple-mobile-web-app-status-bar-style content=black>
18 <meta name=apple-mobile-web-app-title content=Web Starter Kit>
19 <link rel=apple-touch-icon-precomposed
href=apple-touch-icon-precomposed.png>
20
21 <!-- Tile icon for Win8 (144x144 + tile color) -->
22 <meta name=msapplication-TileImage
content=images/touch/ms-touch-icon-144x144-precomposed.png>
23 <meta name=msapplication-TileColor content=#3372DF>
24
25 <!-- TODO: Troque as duas referncias de folha de estilo para usar o Sass
26 (e tire o transformador sass no arquivo pubspec.yaml. -->
27 <link rel=stylesheet href=styles/main_gen.css>
28 <!-- link rel=stylesheet href=styles/main.css -->
29 </head>
30
31 <body>
32 <!-- contedo do exemplo. -->
33
34 <header class=app-bar promote-layer>
35 <div class=app-bar-container>
36 <button class=menu><img src=images/hamburger.svg alt=Menu>
</button>
37 <h1 class=logo>Reversor de Palavras</h1>
38 <section class=app-bar-actions>
39 <!-- Put App Bar Buttons Here -->
40 <!-- e.g <button><i class=icon icon-star></i></button> -->
41 </section>
42 </div>
43 </header>
44
45 <nav class=navdrawer-container promote-layer>
46 <h4>Navegao</h4>
47 <ul>
48 <li><a href=/>Home</a></li>
49 <li><a href=/sobre>Sobre</a></li>
50 </ul>
51 </nav>

Copyright - Proibido copiar ou distribuir. Todos os direitos reservados para DevMedia

A maior parte dessa listagem compreende tags de importao de


estilo e tags meta, alm da estrutura de divs HTML para conter o
menu de navegao. Vejamos alguns detalhes:
As tags meta das linhas 12 e 13 servem para criar um atalho
da aplicao nos dispositivos Android. Da mesma forma, as representadas nas linhas 16 a 18 fazem o mesmo para dispositivos
iOS. J na linha 22 temos uma representao deste cdigo para
dispositivos que rodam Windows 8/Windows Phone.
Na linha 25 temos o contedo da tag de estilo necessria para
incutir Sass nas pginas, caso deseje.
O restante da implementao traz apenas divs e links para a
navegao. A estrutura foi feita baseada no CSS disponibilizado
pelo Dart no projeto recm-criado.
A segunda parte da pgina pode ser encontrada na Listagem 5
e deve ser adicionada logo aps o final da anterior.
Como boa prtica de implementao no front-end, estamos
importando os arquivos de script da Dart apenas no final, assim
ganhamos em performance pois a pgina j estar carregada
quando chegarmos nestes arquivos. Perceba que o atributo type da
tag script (comumente preenchido com o valor text/javascript)
deve ser preenchido com application/dart sempre.
J o src aponta para o arquivo main.dart. A segunda tag de script
(linha 33) serve para carregar a API da Dart na pgina.
Note tambm que a segunda div deve vir escondida (display:none)
para que possamos exibi-la somente quando selecionada no menu.
Veja como fcil incutir navegao na Dart: basta criar divs e
escond-las, deixando que a API se encarrega de redirecionar para
onde voc mandar.

Listagem 5. Contedo das pginas de converso e sobre.


01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18

<main>
<div id=home>
<p>
Nome:<br>
<input type=text id=nome placeholder=Digite o seu nome...>
</p>
<p>
Revertido:<br>
<output id=out></output>
</p>
</div>

<div id=sobre style=display:none>


<p>
Este um aplicativo de demonstrao HTML bsico construdo com Dart.
Para os desenvolvedores que no querem, ou no podem,
usam polymer.dart,
19
este um ponto de partida opcional.
20 </p>
21 </div>
22
23 <div class=sass-hidden>
24 <p>
25
Nota: para usar Sass com esta aplicao,
26
mude as referncias de folha de estilo na tag &lt;head&gt;
27
e descomenteo transformador sass no arquivo pubspec.yaml.
28 </p>
29 </div>
30 </main>
31
32 <script type=application/dart src=main.dart></script>
33 <script data-pub-inline src=packages/browser/dart.js></script>
34 </body>
35 </html>

Copyright - Proibido copiar ou distribuir. Todos os direitos reservados para DevMedia

33 33

Edio 04 Front-end Magazine

Primeiros passos com a Google Dart

Figura 4. Resultado da pgina de reverso

Figura 5. Navegando pgina de sobre

Aps isso, salve todos os arquivos e


clique no boto Run no topo da IDE ou
selecione o atalho Ctrl + R. O resultado
dever ser igual ao das Figuras 4 e 5.
Note que o Editor abrir uma janela
interna do Google Chrome. Voc no
precisa ter o browser instalado, j que ele
traz uma instncia interna do mesmo no
pacote de instalao. Essa abordagem
usada pelo Google para evitar fazer testes em browsers internos s IDEs (como
no Eclipse, por exemplo), possibilitando
testes mais reais e automatizados. A comunicao com frameworks de teste como
o Selenium fcil de ser feita nessa verso
do Chromium.
Veja que na barra de URLs do browser
interno ele abriu a aplicao no endereo
http://localhost:8080. Essa a URL padro
do framework, pois ele faz uso do Node.js
para compilar e executar o JavaScript no
servidor. Por acaso se no estiver conseguindo executar ou aparecer algum erro
de porta em uso, verifique se no est
executando alguma ferramenta que usa a
porta 8080, como os servidores Java Tomcat
e JBoss, por exemplo.
Ainda sobre a URL, veja que na tela Sobre
temos a URL com a respectiva terminao.
Isso acontece porque definimos que a ao
exibir a div com a propriedade name de
valor sobre.
A Dart tambm gera contedo responsivo automaticamente. Logo, se executarmos
a mesma tela em um dispositivo smartphone ou tablet, teremos como resultado a tela
exibida na Figura 6.

Principais caractersticas
A Dart inaugurou uma lista de novos
conceitos no mundo da programao.
Vejamos alguns deles.

Modularidade e Namespace

Figura 6. Telas da aplicao em dispositivo menor

34 Front-end Magazine Edio 04

34

O conceito de modularidade baseado


na diviso em componentes menores e
independentes. Alm disso, cada mdulo
precisa ter uma responsabilidade nica e
fornecer estruturas que permitam se conectar a ele. Por exemplo, se tivermos um
sistema hospitalar e desejamos dividi-lo
em mdulos que possam ser acoplados a
outros sistemas de terceiros, teramos um

Copyright - Proibido copiar ou distribuir. Todos os direitos reservados para DevMedia

mdulo para o almoxarifado, outro para o controle de consultas,


mais um para o cadastro de exames, e por a vai.
Esse tipo de recurso muito usado por softwares de clientes
que precisam de alguns componentes enquanto outros do mesmo negcio no. No universo de programao, essa diviso leva
o nome de decomposio. Para que cada parte do sistema seja
decomposta ela precisa passar por um ciclo de aes: criao,
mudana, teste, uso e substituio separada.
A modularidade na Dart feita atravs dos pacotes, bibliotecas
e classes:
Uma biblioteca expe as funcionalidades como um conjunto
de interfaces e esconde a implementao do resto do mundo.
Como um conceito, muito similar separao de responsabilidades que temos na Programao Orientada a Objetos, por
exemplo. Como resultado, o usurio passa a ter menos cdigo
concentrado e mais facilidade na hora de manter o mesmo, j
que as mudanas se concentram agora sempre num componente s. Alm disso, o conceito de biblioteca passa a no mais
englobar somente APIs server side, mas tambm frameworks
front-end.
Um pacote um simples diretrio que contm um arquivo
chamado pubspec.yaml e inclui em si uma quantidade x de bibliotecas e recursos. Este arquivo contm informaes importantes
sobre o pacote como seus autores, alm de suas dependncias em
relao a outros pacotes. Vejamos na Listagem 6 o contedo deste
arquivo criado no nosso exemplo de AloMundo. Perceba que ele
funciona como uma espcie de Google Doc, porm especificamente para a Dart; alm disso, estes so apenas campos bsicos,
possvel encontrar uma lista das demais opes no site oficial
da linguagem (vide seo Links). Esse arquivo obrigatrio para
que o seu Sistema Operacional reconhea o tipo de tecnologia
que ir operar ali.
Antes de ser usado, um pacote deve sempre ser publicado em
um sistema de gerenciamento de pacotes, que est disponvel
como um recurso online chamado pub (veja na seo Links a URL
do pub oficial da Dart). Em relao recuperao dos mesmos
pacotes no pub, uma aplicao utilitria de mesmo nome pode
ser usada para tal. Esta usa informaes sobre as dependncias
do pubspec.yaml para recuperar todos os pacotes necessrios dos
seguintes locais:
- Pacotes recentemente atualizados no site da pub Dart;
- Repositrio Git;
- Diretrio no filesystem local.
As classes podem ser representadas usando funes comuns
ou prottipos de herana.
J os namespaces so containers para todos os membros de uma
biblioteca. Um namespace definido pelo nome da biblioteca.
Ou seja, se uma biblioteca implicitamente nomeada ento ela
tem um namespace vazio. Isso resulta muitas vezes em conflitos
ao tentar importar bibliotecas com os mesmos namespaces. Tais
conflitos podem ser evitados com uma clusula prefixada (as) e
um nome de prefixo.

Veja a Listagem 7. Nela, temos um exemplo de biblioteca implicitamente nomeada na qual todos os recursos da dart:html
esto disponveis atravs do escopo da nossa biblioteca com o
prefixo dom.
Listagem 6. Estrutura de diretrios padro do projeto.
01 name: AloMundoDart
02 version: 0.0.1
03 description: >
04 A mobile-friendly web app with routing, responsive CSS, and (optional) Sass
05 support.
06 #author: <your name> <email@example.com>
07 #homepage: https://www.example.com
08 environment:
09 sdk: >=1.0.0 <2.0.0
10 dependencies:
11 browser: >=0.10.0 <0.11.0
12 sass: >=0.4.0 <0.5.0
13 script_inliner: >=1.0.0 <2.0.0
14 route_hierarchical: >=0.5.0 <0.7.0
15 transformers:
16 - script_inliner
17 #- sass:
18 # style: compressed
Listagem 2. Exemplo de biblioteca implicitamente nomeada.
01 /**
02 * Biblioteca nomeada implicitamente.
03 * A lib dart:core automaticamente importada.
04 */
05 import dart:html as dom;
06 /**
07 * Recupera [Elemento] por [id].
08 */
09 dom.Element getById(String id) => dom.querySelector(#$id);

Obviamente, todas as marcaes e seletores s sero reconhecidos em um ambiente Dart. O browser no consegue interpretar
essa notao. Veja que na linha 5 fazemos uso da clusula as
para importar o recurso (biblioteca HTML da Dart) de forma
dinmica. Na linha 9 fazemos a recuperao do elemento id pelo
seu atributo id da HTML. Isso bem semelhante forma como
o jQuery faz a seleo de seus atributos, por exemplo. Contudo,
quando for compilado para JavaScript, todo esse cdigo perde as
informaes das bibliotecas e temos um arquivo bem diferente
sendo gerado.
A Dart implementa o conceito de encapsulamento atravs da
privacidade. Cada membro ou identificador de uma biblioteca
tem um dos dois nveis de acesso: pblico ou privado. Membros
privados so visveis apenas de dentro da biblioteca na qual eles
so declarados. Por outro lado, os membros com um acesso pblico
so visveis em todos os lugares. A diferena entre eles o prefixo
sublinhado (_), como mostrado no cdigo da Listagem 8.
O cdigo mostra uma biblioteca de animao com duas classes
e uma varivel. A classe de Animao e a varivel animationSpeed so pblicas e, portanto, visveis de fora da biblioteca.
A classe _AnimationLibrary privada e s pode ser utilizada
na biblioteca.

Copyright - Proibido copiar ou distribuir. Todos os direitos reservados para DevMedia

35 35

Edio 04 Front-end Magazine

Primeiros passos com a Google Dart

Listagem 8. Exemplo de encapsulamento na Dart.


01 // Biblioteca Animation.
02 library animation;
03 // Classe publicamente disponvel em qualquer lugar.
04 class Animation {
05 // ...
06 }
07 // Classe visvel apenas dentro da biblioteca.
08 class _AnimationLibrary {
09 // ...
10 }
11 // Varivel publicamente disponvel em qualquer lugar.
12 var animationSpeed;

Acessos pblicos podem ser controlados com as extenses show


e hide na declarao de importao. Use a seguinte extenso show
com uma classe especfica, que estar disponvel dentro da biblioteca em que importada:
import animation.dart as animation show Animation;
main() { new animation.Animation(); }

O prefixo animation na declarao de importao define o


namespace para importar a biblioteca animation.dart. Todos os
membros da biblioteca animation.dart esto disponveis no namespace global atravs deste prefixo.
J a extenso hide especificada na classe far com que a mesma
esteja inacessvel de dentro da biblioteca na qual foi importada.
Isso interessante quando precisamos que uma classe s seja
acessa de dentro da prpria API, como classes de segurana,
conexo com banco, etc.:

O resultado ser 3. Veja que criamos uma funo simples de


soma de dois valores e adicionamos a funo a uma varivel
(operacao, linha 10) chamando-a em vez de funo soma(). Na
linha 13 imprimimos o resultado da soma. Veja que as impresses
no console JavaScript so feitas via mtodo print() e os valores a
se concatenar via operador ${}.
A Dart ainda lida com a passagem de funes como argumentos
para outras funes; retorno de funes como resultado de outras
(return) e consegue salvar funes em estruturas de dados, como
vetores, por exemplo.
A funo pode ser criada em mbito global ou no mbito de
uma outra funo. Uma funo que pode ser referenciada com
um acesso para as variveis no seu escopo lxico chamada de
closure. Vejamos o cdigo da Listagem 10.
Listagem 10. Exemplo de closure na Dart.
01 library function_closure;
02
03 // Funo retorna uma closure.
04 calcular(base) {
05 // Contador
06 var cont = 1;
07 // Funo interna - closure
08 return () => print(Valor ser ${base + cont++});
09 }
10 void main() {
11 // A funo externa retorna a interna
12 var f = calcular(2);
13 // Agora chamamos a closure
14 f();
15 f();
16 }

import animation.dart as animation hide Animation;


main() { var speed = animation.animationSpeed; }

Funes e Closures
Na Dart possvel criar funes via varivel, isto , criamos
uma referncia a uma funo e a atribumos para uma varivel,
conforme pode ser observado na Listagem 9.
Listagem 9. Exemplo de funo com associao de variveis a funes.
01 library function_var;
02 // Returna a soma de [a] e [b]
03 soma(a, b) {
04
return a + b;
05 }
06 // Operao
07 var operacao;
08 void main() {
09
// Atribui a referncia funo [soma]
10
operacao = soma;
11
// Execute operacao
12
var resultado = operacao(2, 1);
13
print(Resultado ser ${resultado});
14 });
15 }

36 Front-end Magazine Edio 04

36

A estrutura para criar uma closure a mesma para as funes


comuns. A diferena que a closure criada e retornada de dentro de uma funo j existente. Ela funciona como uma funo
annima que pode ser criada facilmente sem a necessidade de
todo o aparato de palavras-chave para formar as funes comuns.
Veja que na linha 8, aps criar a varivel contadora, estamos associando o ato de imprimir a soma e contador a uma funo vazia
(). O operador => serve para fazer essa associao, muito comum
em estruturas como lambdas. Aps isso, sempre que quisemos
chamar essa closure basta retornar para uma varivel e efetuar
as chamadas: f() (linhas 14 e 15).
Neste exemplo, os resultados sero 3 e 4, respectivamente.

Classes
No mundo real, encontramos muitos objetos individuais, todos
do mesmo tipo. H muitos carros com a mesma marca e modelo.
Cada carro foi construdo a partir do mesmo conjunto de projetos.
Todos eles contm os mesmos componentes e cada um uma
instncia da classe de objetos conhecida como Carro.
O conceito de classe na orientao a objetos o mesmo na Dart.
Atributos, mtodos, classes internas e construtores se mantm na

Copyright - Proibido copiar ou distribuir. Todos os direitos reservados para DevMedia

linguagem. Vejamos a Listagem 11, onde temos a representao


de um objeto do tipo Carro.
Listagem 11. Representao da classe Carro na Dart.
01 library carro;
02 //Classe abstrata [Carro] no pode ser instanciada.
03 abstract class Carro {
04 String cor;
05 double velocidade;
06 double capacidade;
07
08 // Construtor da classe
09 Car(this.cor, this. capacidade);
10 // Move o carro de acordo com a [velocidade]
11 void move(double velocidade) {
12
this.velocidade = velocidade;
13 }
14 // Para o carro.
15 void stop() {
16
velocidade = 0.0;
17 }
18 }

Vejamos alguns detalhes da listagem:


Na linha 3 declaramos a classe sendo de um tipo abstrato (abstract). Isso significa que essa classe no poder nunca ser instanciada (new), e sim somente servir com classe pai de outras.
Nas linhas 4 a 6 declaramos os atributos, todos globais e pblicos
(no preciso usar palavras reservadas para isso). O tipo String
pertence API da Dart e funciona da mesma forma que em outras
linguagens OO (Java, C#, etc.). Os tipos primitivos (int, double,
char, boolean...) tambm se mantm.
Na linha 9 criamos o construtor da classe que recebe os dois
parmetros para associar aos atributos de cor e capacidade. Veja
que no precisamos fazer a associao dos valores manualmente,
a prpria Dart faz isso para gente automaticamente, simplificando
muito o cdigo.
Os mtodos tambm so pblicos. A palavra void define que eles
no tm nenhum retorno, apenas executando o cdigo interno.

Mixins
A Dart tem um sistema de herana baseado em mixins, que permitem que o corpo de certas classes possa ser reusado em classes
hierrquicas. Vejamos o cdigo da Listagem 12.
A classe Reboque independente da classe Carro, mas pode
aumentar a capacidade de carregar peso do carro. Para adicionar
um mixin de Reboque classe CarroPassageiro podemos usar a
palavra-chave with seguida pela classe mixin Reboque, como no
cdigo da Listagem 13.
Com a adio da clusula with na linha 5 temos agora assimilada a funcionalidade de adicionar mais peso ao reboque do
carro (linha 15). Para isso, no precisamos mudar nada na classe
CarroPassageiro, basta adicionar o mixin e os mtodos sero
automaticamente carregados sem a necessidade de uma herana
explcita (extends).

Listagem 12. Exemplo de classe a ser mixada.


01 library reboque;
02 // O reboque
03 class Reboque {
04 // Acessa a informao de [carga] do carro
05 double carga = 0.0;
06 // O reboque pode carregar tanto de [peso]
07 void carregar(double peso) {
08
// O carregamento aumenta com pesos extra.
09
carga += peso;
10 }
11 }
Listagem 13. Exemplo de mixin na Dart.
01 library passenger_carro;
02 import carro.dart;
03 import reboque.dart;
04 // Carro de passageiro com reboque.
05 class CarroPassageiro extends Carro with Reboque {
06

// N max de passageiros.

07

int maxPassageiros = 4;

08

/**

09

* Cria um [Passageiro] com a [cor], [carga] e [maxPassageiros].

10

* Podemos usar o [Reboque] para carregar [pesoExtra].

11

*/

12

Passageiro(String cor, double carga, this.maxPassageiros,

13

{double pesoExtra:0.0}) : super(cor, carga) {

14

// S podemos carregar peso extra com [Reboque]

15
16

carregar(pesoExtra);
}

17 }

Os mixins so semelhantes s interfaces e s podem ser definidos


via classe, tendo algumas restries no seu uso, a saber:
No podem ter construtores definidos;
A superclasse de um mixin s pode ser um Object;
Eles no podem ter chamadas ao operador super.

Colees e Genricos
A Dart suporta o uso de vetores na forma de classes de List.
Digamos que precisamos usar uma lista para salvar informaes
temporrias. O dado que voc coloca na lista depende do contexto
do cdigo. A lista deve conter diferentes tipos de dados ao mesmo
tempo, conforme demostrado pela Listagem 14.

Listagem 14. Exemplo de lista na Dart.


01 // Lista de dados aleatrios
02 List lista = [1, Letra, {test:errado}];
03
04 // Item qualquer
05 double item = 1.53;
06
07 void main() {
08 // Add o item ao array
09 lista.add(item);
10 print(lista);
11 }

Copyright - Proibido copiar ou distribuir. Todos os direitos reservados para DevMedia

37 37

Edio 04 Front-end Magazine

Primeiros passos com a Google Dart

Neste exemplo adicionamos dados de diferentes tipos ao mesmo array. Quando o cdigo for executado vermos o resultado
[1, Letra, {test: errado}, 1.53] ser impresso no console. Esse tipo de
funcionalidade permitido em vrias linguagens de programao. Entretanto, no interessante ter dados conflitando em uma
estrutura que pode dar erros mais frente. Para evitar esse tipo de
comportamento podemos verificar qual tipo de dado est vindo
na lista atravs do operador is (Listagem 15).
Listagem 15. Exemplo de lista checada na Dart.
01 // Array de dados String
02 List parts = [roda, ignio, motor];
03
04 // Item qualquer
05 double item = 1.53;
06
07 void main() {
08 if (item is String) {
09
// Add o item ao array
10
parts.add(item);
11 }
12 print(parts);
13 }

Vejamos o cdigo da Listagem 17. Ele representa um exemplo


onde um eventual erro acontece na Dart.
Listagem 16. Exemplo de lista com Genricos na Dart.
01 // Array de dados String
02 List<String> parts = [roda, ignio, motor];
03
04 // Ordinary item
05 double item = 1.53;
06
07 void main() {
08 // Add o item ao array
09 parts.add(item);
10 print(parts);
11 }
Listagem 17. Exemplo de cdigo com erro na Dart.
01 main() {
02 // Lista de tamanho fixo
03 List lista = new List(5);
04 // Preenche a lista com os valores
05 for (int i = 0; i < 10; i++) {
06
lista[i] = i;
07 }
08 print(Resultado ser ${lista});
09 }

Agora o resultado impresso ser [roda, ignio, motor]. Dessa


forma, garantimos que nenhum tipo de dado que no seja
String seja adicionado ao nosso array. Agora, imagine como
seria se tivssemos centenas de arrays no nosso projeto, ao ter
de fazer esse tipo de verificao sempre que quisermos criar ou
manipular um. muito trabalho desnecessrio. Para resolver
isso podemos usar um analisador esttico de cdigo que faz
o trabalho todo. Chamamos essas estruturas de Genricos.
Vejamos na Listagem 16 como ficaria nosso cdigo.
Dessa forma, caso o programador tente informar algum valor
que no seja String no vetor, receber um erro informando a
tipagem errada.

Erros e Excees
Existe sempre uma confuso muito grande entre a diferena do
que um erro e uma exceo nas linguagens de programao.
Erros geralmente acontecem precedidos de falhas graves no fluxo
dos algoritmos que impedem a continuao do sistema, como por
exemplo o estouro de memria ou quando uma VM no consegue
encontrar o recurso (classes, arquivos, etc.) que foi solicitado. J
as excees so manipulveis via cdigo, o programador pode
captur-las, entender o que aconteceu e ento tomar uma deciso
programtica.

Estamos criando uma lista simples com a classe List de um


tamanho fixo e preenchendo com os valores do inteiro contador
em um loop que contm mais itens do que o tamanho mximo
permite. Ao executar este cdigo teremos uma exceo semelhante
da Figura 7.
Este erro ocorreu porque foi realizada uma condio de violao
em nosso cdigo quando tentamos inserir um valor na lista em
um ndice fora do intervalo vlido. Principalmente, esses tipos de
falhas ocorrem quando o contrato entre o cdigo e a API chamada
foi quebrado. No nosso caso, RangeError indica que o pr-requisito
foi violado. H um monte de erros no Dart SDK como CastError
(Erro de converso de um tipo para outro invlido), NoSuchMethodError (Quando no possvel encontrar um mtodo informado),
UnsupportedError (Quando um tipo de dado no suportado), OutOfMemoryError (Quando no h memria suficiente para carregar
objetos) e StackOverflowError (Quando a pilha de memria estoura
o limite mximo). Alm disso, existem muitos outros erros que voc
pode encontrar no arquivo errors.dart como uma parte da biblioteca
dart.core. Todas as classes de erro herdam da classe Error e podem
retornar informaes de rastreamento de pilha para ajudar a encontrar a causa dos mesmos rapidamente. No exemplo anterior, o erro
aconteceu na linha 6 do principal mtodo no arquivo .dart.

Figura 7. Tela de erro sendo impresso no console da Dart

38 Front-end Magazine Edio 04

38

Copyright - Proibido copiar ou distribuir. Todos os direitos reservados para DevMedia

Os erros podem ser detectados via cdigo, mas so difceis de


manipular, dada a sua natureza imprevista. O mais ideal sempre
conhecer bem a API de erros da Dart para evitar as situaes, que
so bem exclusivas.
Excees, ao contrrio de erros, so feitas para serem capturadas e geralmente carregam informaes sobre a falha, mas
no incluem as informaes de rastreamento de pilha. Excees
acontecem em situaes recuperveis e no param a execuo
de um programa. Voc pode lanar (throw) qualquer objeto no
nulo como uma exceo, mas uma boa prtica criar uma nova
classe de exceo que implemente a classe abstrata Exception e
sobrescrever o mtodo toString da classe Object, a fim de fornecer
informaes adicionais. Uma exceo deve ser tratada dentro
das clusulas catch ou propagadas para as chamadas exteriores.
Vejamos na Listagem 18 um exemplo de cdigo sem o uso de
excees, que faz acesso a um arquivo, uma vez que esse tipo
de operao uma das mais propensas a erro nas linguagens de
programao em detrimento do acesso a diretrios, permisses,
tamanhos dos arquivos, etc.

O mtodo fromUri() da linha 8 se encarrega de carregar o arquivo em memria para ser manipulado.
O mtodo existsSync() da linha 10 verifica se o arquivo de fato
existe. Esse o primeiro tratamento de erro que fazemos, isto ,
em vez de manipularmos uma exceo diretamente, fazemos um
teste para cada arquivo vendo se ele existe antes de us-lo.
Na linha 12 abrimos o arquivo para pegar seus bytes e na linha 16
lemos o seu contedo a fim de iterar sobre os dados do mesmo.
Na linha 22 imprimimos o contedo que foi concatenado, fechando o arquivo na linha 25.
interessante observar que, mesmo que o contedo seja impresso com sucesso e nenhuma exceo acontea pelas precaues que
tomamos, ainda assim na linha 25, ao fechar o arquivo, corremos
o risco de receber uma exceo por vrias razes: o arquivo foi
removido por outrem, falha na conexo de rede, etc.
Em vista disso, para se ter uma maior segurana nesse fluxo e
manter a organizao do cdigo, vamos evoluir o mesmo para o
que est contido na Listagem 19.

Listagem 18. Exemplo de cdigo com exceo sem tratamento.

Listagem 19. Exemplo de cdigo com exceo e tratamento.

01 import dart:io;
02 main() {
03 // URI do arquivo
04 Uri uri = new Uri.file(teste.json);
05 // Checa a uri
06 if (uri != null) {
07
// Cria o arquivo
08
File file = new File.fromUri(uri);
09
// Checa se o arquivo existe
10
if (file.existsSync()) {
11
// Abra o arquivo
12
RandomAccessFile random = file.openSync();
13
// Checa se o arquivo foi aberto
14
if (random != null) {
15
// L o arquivo
16
List<int> conteudoNaoPronto = random.readSync(random.lengthSync());
17
// Checa o contedo no pronto
18
if (conteudoNaoPronto != null) {
19
// Converte para String
20
String conteudo = new String.fromCharCodes(conteudoNaoPronto);
21
// Imprime o resultado
22
print(contedo: ${conteudo});
23
}
24
// Fecha o arquivo
25
random.closeSync();
26
}
27
} else {
28
print (Arquivo no existe);
29
}
30 }
31 }

01 import dart:io;
02 main() {
03 RandomAccessFile random;
04 try {
05
Uri uri = new Uri.file(teste.json);
06
07
File file = new File.fromUri(uri);
08
09
random = file.openSync();
10
11
List<int> notReadyContent = random.readSync(random.lengthSync());
12
13
String conteudo = new String.fromCharCodes(notReadyContent);
14
15
print(conteudo: ${conteudo});
16 } on ArgumentError catch(ex) {
17
print(Erro de argumento invlido);
18 } on UnsupportedError catch(ex) {
19
print(URI no pode referenciar um arquivo);
20 } on FileSystemException catch(ex) {
21
print (Arquivo no existe ou est inacessvel);
22 } finally {
23
try {
24
random.closeSync();
25
} on FileSystemException catch(ex) {
26
print(Arquivo no pode ser fechado);
27
}
28 }
29 }

O resultado da execuo ser contedo: [{name: teste, length: 150}].


Vejamos alguns detalhes do cdigo:
Na linha 1 importamos a biblioteca IO da Dart, que se encarrega de todas as operaes de Entrada/Sada, incluindo acesso a
arquivos e serializao.
Na linha 4 carregamos a URI (URL interna) do arquivo. O leitor
pode usar qualquer arquivo que desejar para efetuar o teste.

As mudanas no foram to grandes, mas fazem uma grande


diferena na execuo final. O bloco try/on/catch a estrutura
usada para capturar as excees e a sintaxe bem semelhante
das outras linguagens. O nome do erro/exceo que voc imagina
que possa acontecer no cdigo deve sempre vir declarado aps
a clusula on, evitando sempre usar superclasses genricas para
capturar as excees especficas. Veja que no bloco finally (atrelado

Copyright - Proibido copiar ou distribuir. Todos os direitos reservados para DevMedia

39 39

Edio 04 Front-end Magazine

Primeiros passos com a Google Dart

ao catch, que ser obrigatoriamente executado ao final da sentena)


efetuamos o fechamento do arquivo, mas caso algum erro acontea
nessa parte tambm faremos a validao e tratamento do erro.
Dessa forma, garantimos um cdigo organizado e livre de falhas
que impeam o sistema de continuar executando.
Existem muitos outros recursos que a linguagem Dart disponibiliza, tais como Anotaes (para diminuir a quantidade de
cdigo em XML), Proxies dinmicos (para aumentar a performance salvando dados em cache), reflection (para modificar as
prprias estruturas programadas em tempo de execuo), bem
como outros conceitos da Orientao a Objetos (polimorfismo,
interfaces, composio, etc.).
Contudo, com o contedo aqui exposto o leitor estar apto a criar
aplicaes mais robustas usando a Dart, seu SDK e o poderoso
Editor que a mesma disponibiliza. Para publicar suas aplicaes,
voc pode utilizar a pgina do Google Code ou do prprio GitHub,
bem como participar do projeto open source e ajudar a melhorar
cada vez mais a linguagem. A Dart tambm se integra facilmente
a bancos de dados, web services, outros frameworks JavaScript,
como jQuery, Prototype.js e AngularJS. Agora com voc e a sua
criatividade. Bons estudos!

40 Front-end Magazine Edio 04

40

Autor
Jlio Sampaio
analista de sistema e entusiasta da rea de Tecnologia da
Informao. Atualmente consultor na empresa Visagio,
trabalhando em projetos de desenvolvimento de sistemas estratgicos, tambm instrutor JAVA. Possui conhecimentos e experincia
em reas como Engenharia de Software e Gerenciamento de Projetos,
tem tambm interesse por tecnologias relacionadas ao front-end web.
Links:
Pgina de download oficial da Dart.
https://www.dartlang.org/downloads
Pgina do repositrio de pacotes da Dart.
https://pub.dartlang.org/

Copyright - Proibido copiar ou distribuir. Todos os direitos reservados para DevMedia

Testes automatizados
com o framework
Selenium
Aprenda a automatizar os testes das suas
telas front-end e ganhe em produtividade e
escalabilidade

automao de testes existe para, atravs de


ferramentas e estratgias, reduzir ao mximo o
envolvimento humano em atividades manuais
repetitivas, como o cadastro de um cliente ou o login/
logout em uma aplicao.
O principal objetivo de um teste automatizado ser
usado futuramente em testes de regresso. Esse termo,
por sua vez, usado para quando precisamos efetuar
ciclos de re-teste de uma ou vrias funcionalidades,
com a inteno de identificar problemas ou defeitos
introduzidos pela adio de novas funcionalidades ou
pela correo de alguma j existente.
Levando em considerao um exemplo real, quando
um projeto de software no utiliza testes automatizados
em sua concepo, sempre que uma alterao acontece
em determinada tela ou mdulo, um novo ciclo de testes
manuais precisa ser refeito e, assim, sucessivamente at
que o projeto esteja terminado. O problema aumenta
mais ainda quando o projeto no tem fim e exige manuteno constante, implicando consequentemente em
mais custos com uma equipe de teste e possivelmente
em entregas sem qualidade, j que no houve tempo o
suficiente para testar e re-testar tudo.
Em contrapartida, a utilizao de testes automatizados
acelera os ciclos do software, uma vez que o teste passa a
ser executado por outro software inteligente, que acessa
as telas e reexecuta os mesmos testes nos dando relatrios rpidos do que deixou de funcionar. Alm disso,
estamos menos suscetveis a erros, j que a mquina
nunca erra, ao contrrio de termos humanos testando.
Existem vrias abordagens diferentes para a automao de testes. Os tipos so normalmente agrupados de

Fique por dentro


A automao de testes soma praticamente 20% do tempo de
trabalho de um testador (ou desenvolvedor testador) e economiza
vrias horas de manuteno e de testes de regresso para verificar
se tudo est funcionando h cada nova release de software lanada.
O Selenium se popularizou como um dos principais frameworks de
automao de testes do mercado, principalmente pelo seu suporte a
linguagens como Python, Ruby, Java, C# e Node.js.
Neste artigo aprenderemos a configurar o Selenium de duas formas:
via IDE Eclipse e via Selenium IDE. Voc ver como gravar testes nos
browsers, salvar scripts, re-execut-los, alm de comunicar seus testes
com JavaScript, jQuery e HTML5. Ao final deste, o leitor estar apto a
executar testes sncrona e assincronamente via API, linha de comando
ou interface grfica, alm de entender que tipo de teste se encaixa
melhor em cada realidade de software.

acordo com a maneira com a qual os testes se integram e interagem


com o software. Um testador pode construir seu teste baseando-se
em dois conceitos:
1. Interface grfica
a. Gravao/Execuo (Capture /Playback): os testes so
feitos diretamente na interface grfica da aplicao: HTML,
XML, Swing, etc. As ferramentas geralmente disponibilizam
recursos para efetuar a gravao (capture) das aes feitas
nas telas que sero convertidas para uma linguagem de script
inteligvel pela mesma, a qual poder futuramente ser reexecutada (playback).
b. Dirigido a dados (Data-Drive): representa uma abordagem mais dirigida aos dados no sentido de gravar as aes do

Copyright - Proibido copiar ou distribuir. Todos os direitos reservados para DevMedia

41 41

Edio 04 Front-end Magazine

Testes automatizados com o framework Selenium

usurio, porm sempre fornecendo


dados distintos para deixar o teste mais
prximo da realidade.
c. Dirigido a palavras-chave (KeywordDriven): so testes com alto nvel de
abstrao, onde at mesmo usurios
comuns podem criar instrues para
iniciar um teste, uma vez que o mesmo
ser baseado em palavras-chave. Cada
palavra-chave representa um comando
da ferramenta.
2. Lgica de negcio
a. Linha de comando (Command
Line Interface): fornece uma interface
com um mecanismo de interao com
a aplicao por meio de um prompt
cmd do SO e os comandos podem ser
enviados de l.
b. API (Application Programming
Interface): fornece bibliotecas ou um
conjunto de classes para permitir que
outras aplicaes acessem a interface
do teste sem necessariamente ter de
conhecer como eles foram feitos.
c. Test Harness (Equipamentos de teste): um teste especfico que visa o teste
nico e exclusivo da lgica de negcio.
No permitida interao alguma com
as interfaces grficas.
O sucesso desse tipo de teste depende
de identificar e alocar elementos da GUI
(Graphical User Interface) na aplicao a
ser testada e ento executar operaes e
verificaes nestes mesmos elementos
para que o fluxo do teste seja completado
com sucesso.
O Selenium um framework de testes
automatizados portvel para aplicaes
web desenvolvido em 2004 por Jason
Huggins como um projeto interno da
empresa ThougthWorks. Ele fornece todo
o aparato para capturar e reproduzir os
testes via scripts sem a necessidade de
aprender nenhuma linguagem de scripting. Tambm disponibiliza uma linguagem de teste especfica para linguagens
populares como Java, C#, Groovy, Perl,
PHP, Python e Ruby. Os testes podem
ser executados em browsers web modernos e os deploy de aplicao rodam
tanto em Windows, quanto em Linux e
Macintosh.

42 Front-end Magazine Edio 04

42

Dentre a lista de funcionalidades fornecida pelo framework, temos:


Preenchimento de caixas de texto;
Checagem de checkboxes e botes de
rdio;
Click em botes e links;
Navegao de e para <iframe>s;
Navegao de e para novas janelas/tabs
criadas por links;
Interao com a maioria dos elementos
como um humano faz.
Na lista de funcionalidades que ele no
suporta, temos:
Interao com Flash, PDF ou Applets;
Interao com quaisquer objetos colocados dentro das tags HTML <object> e
<embed>.
Neste artigo exploraremos os principais
recursos desse framework, atravs da
construo de exemplos reais usando as
linguagens JavaScript, jQuery e Java em
conjunto com HTML5 e testes efetuados no
Google Chrome e Firefox. Veremos desde
a configurao e instalao da ferramenta,
bem como as principais diferenas entre
usar o Selenium embarcado (com uma
linguagem de programao) e o Selenium
IDE (diretamente no browser Firefox como
Add-On).

Configurao do ambiente
O primeiro requisito obrigatrio para
executar o Selenium no seu Sistema
Operacional ter uma verso recente do
JDK (Java Development Kit) instalada. Para
verificar se voc j tem alguma, basta

acessar o terminal de comandos e digitar


o seguinte comando:
java -version

Se voc vir um nmero com a verso do


Java sendo impresso, ento voc j o tem
instalado. Caso contrrio, acesse a pgina de
downloads do mesmo (seo Links) e efetue
os passos para instalao (voc encontrar
tutoriais de como instalar no prprio site da
Oracle caso tenha alguma dvida).
Em seguida, precisamos efetuar o
download do Eclipse (seo Links), que a
IDE mais utilizada para desenvolver com o
Selenium. Selecione sempre a opo Eclipse
IDE for Java EE Developers, dessa forma
teremos uma verso da IDE que tambm desenvolve para a web. Certifique-se tambm
de baixar a verso correspondente com o seu
Sistema Operacional (32/64 bits). Quando
finalizar o download, mova o arquivo zip
baixado e o descompacte em um local de sua
preferncia. Como no preciso instal-lo,
basta dar clique duplo no arquivo eclipse.
exe e a ferramenta ir iniciar.
Por fim, precisamos selecionar tambm
os jars do Selenium para termos pleno
suporte ao mesmo dentro dos projetos.
Optaremos por usar o Java como linguagem server side, em vista de a imensa
maioria dos usurios do Selenium usarem
essa linguagem no mercado por padro.
Portanto, acesse a pgina de download
do Selenium (seo Links) e na seo
Selenium Client & WebDriver Language
Bindings clique no link correspondente
linguagem Java (Figura 1).

Figura 1. Pgina de download do WebDriver do Selenium

Copyright - Proibido copiar ou distribuir. Todos os direitos reservados para DevMedia

Figura 2. Estrutura de pastas e arquivos do Selenium

boto Add External JARS... e navegue


at as pastas onde voc descompactou o
Selenium. Selecione todos os jars da raiz
do diretrio e da pasta libs e clique em
Abrir (Figura 4).
Para fazer um teste rpido, v at o
diretrio src do projeto, clique com o
boto direito e selecione a opo New
> Class e d um nome de pacote (br.
edu.devmedia.selenium) e um nome de
classe AloMundoSelenium e clique em Finish. Na classe que
for aberta, adicione o contedo da Listagem 1 mesma.
Listagem 1. Classe de teste com o browser Firefox.
01 package br.edu.devmedia.selenium;
02
03 import java.io.File;
04
05 import org.openqa.selenium.WebDriver;
06 import org.openqa.selenium.chrome.ChromeDriver;
07 import org.openqa.selenium.firefox.FirefoxDriver;
08 import org.openqa.selenium.ie.InternetExplorerDriver;
09
10 public class AloMundoSelenium {
11

public static void main(String[] args) {

12
13

abrirFirefox();
}

14
15

private static void abrirFirefox() {

16

WebDriver driver = new FirefoxDriver();

17

driver.get(http://devmedia.com.br);

18

String i = driver.getCurrentUrl();

19

System.out.println(i);

20
21

driver.close();
}

22

Figura 3. Wizard de criao de novo projeto Selenium no Eclipse


O arquivo baixado estar tambm no formato zip, logo extraia-o
novamente no diretrio do projeto. A Figura 2 mostra a representao dos arquivos internos, dos quais faremos uso essencialmente
dos jars.
Execute agora o Eclipse e selecione um workspace para salvar
o projeto. Aps isso, vamos criar um primeiro exemplo de AloMundo com o browser Firefox. Seleciona a opo File > New >
Project > Java Project e, na janela que aparecer, d o nome AloMundoSelenium ao projeto e certifique-se de selecionar a opo
JavaSE-7 no boto Use na execution environment JRE, conforme
mostra a Figura 3.
Clique em Finish. Para que as nossas classes reconheam o
Selenium WebDriver, precisamos adicionar os jars ao classpath.
Para isso, clique com o boto direito no projeto gerado e selecione
Properties > Java Build Path e acesse a tab Libraries. Clique no

23 }

Figura 4. Libs do Selenium adicionadas ao projeto

Copyright - Proibido copiar ou distribuir. Todos os direitos reservados para DevMedia

43 43

Edio 04 Front-end Magazine

Testes automatizados com o framework Selenium

O cdigo traz uma representao simples de teste no Selenium


que ir somente abrir uma instncia do browser Firefox (linha 16),
acessar o site da DevMedia (linha 17) e retornar a URL para o
qual o mesmo foi redirecionado (linha 18). No final, ele fecha
a conexo com o driver (linha 20). Para executar v at o menu
Run no topo da pgina ou clique com o boto direito na classe
e selecione Run As > Java Application.
O resultado ser a abertura de uma instncia do browser citado
com o respectivo site e a mensagem final impressa no console
(Figura 5).

Figura 5. Resultado de execuo do teste no Firefox


O Selenium trabalha com o conceito de drivers para o browser a ser
trabalhado. Nos projetos reais, geralmente temos cdigo para lidar
com ao menos trs browsers: Firefox, Chrome e IE, que so os mais
usados. Caso voc queria adicionar uma nova instncia, precisar
tambm efetuar o download do driver dele, uma vez que o Selenium
reconhece apenas o Firefox em vista da sua IDE ser desenvolvida
nele. Para isso, efetue o download do arquivo chromedriver.exe na
sua verso mais recente no endereo disponvel na seo Links e
posicione-o no endereo do workspace do projeto.
O cdigo para acessar agora passa a ser igual ao da Listagem 2.
Veja que na linha 6 temos a importao do arquivo do driver
diretamente da pasta onde ele foi alocado e, em seguida, setamos
a propriedade webdriver.chrome.driver nas propriedades do
sistema com o valor do caminho do driver, para que o Selenium
possa encontrar uma instncia correta da classe ChromeDriver.
O restante do procedimento o mesmo. Na linha 25 vemos o
equivalente para o browser do Internet Explorer, mas tambm
ser necessrio baixar o driver do mesmo.
Um outro bom exemplo quando queremos no s acessar uma
pgina, como tambm enviar informaes para ela, gerar submits
e recuperar dados dos responses. Esse tipo de funcionalidade
possvel atravs da classe HTMLUnitDriver, que funciona como os
mesmos drivers que vimos para os browsers, porm trabalhando
internamente, sem interface grfica. Essa estratgia muito usada
por desenvolvedores ou testadores que querem criar scripts rapidamente sem ter de ficar acessando o browser o tempo todo.
Vamos criar um exemplo de acesso pgina do Google e enviar
uma palavra para ser pesquisada, dando submit no formulrio
e recebendo a resposta. Quando uma pesquisa feita o ttulo da
pgina do Google muda de acordo com o texto, assim podemos
recuperar essa nova informao e checar se o teste funcionou.
Veja a Listagem 3 para isso.
Agora possvel ver o acesso direto ao browser virtual do
HTMLUnitDriver que tambm pode ser retornado para uma
instncia do WebDriver (linha 13). O mtodo findElement() da
linha 17 recupera o contedo HTML completo da pgina e faz

44 Front-end Magazine Edio 04

44

Listagem 2. Cdigo para acessar a instncia do Chrome.


01 package br.edu.devmedia.selenium;
02
03 import java.io.File;
04
05 import org.openqa.selenium.WebDriver;
06 import org.openqa.selenium.chrome.ChromeDriver;
07 import org.openqa.selenium.firefox.FirefoxDriver;
08 import org.openqa.selenium.ie.InternetExplorerDriver;
09
10 public class AloMundoSelenium {
11 public static void main(String[] args) {
12
abrirChrome();
13 }
14
15 private static void abrirChrome() {
16
File file = new File(D:/Downloads/chromedriver.exe);
17
System.setProperty(webdriver.chrome.driver, file.getAbsolutePath());
18
WebDriver driver = new ChromeDriver();
19
driver.get(http://devmedia.com.br);
20
String i = driver.getCurrentUrl();
21
System.out.println(i);
22
driver.close();
23 }
24
25 private static void abrirIE() {
26
WebDriver driver = new InternetExplorerDriver();
27
driver.get(http://devmedia.com.br);
28
String i = driver.getCurrentUrl();
29
System.out.println(i);
30
driver.close();
31 }
32 }
Listagem 3. Cdigo de teste para pesquisa no Google.
01 package br.edu.devmedia.selenium;
02
03 import java.util.concurrent.TimeUnit;
04
05 import org.openqa.selenium.By;
06 import org.openqa.selenium.JavascriptExecutor;
07 import org.openqa.selenium.WebDriver;
08 import org.openqa.selenium.WebElement;
09 import org.openqa.selenium.htmlunit.HtmlUnitDriver;
10
11 public class HTMLDriver {
12 public static void main(String[] args) {
13
WebDriver driver = new HtmlUnitDriver();
14
15
driver.get(http://www.google.com);
16
17
WebElement element = driver.findElement(By.name(q));
18
19
element.sendKeys(Queijo!);
20
21
element.submit();
22
23
System.out.println(O ttulo da pgina : + driver.getTitle());
24
25
driver.quit();
26 }
27 }

Copyright - Proibido copiar ou distribuir. Todos os direitos reservados para DevMedia

uma busca pelo critrio definido no se parmetro que, por sua


vez, ser responsvel por buscar um elemento nico de nome q
(no caso, a caixa de pesquisa da pgina do Google). Os critrios
podem ser vrios como por nome, id, classe CSS, etc.
O mtodo sendKeys() na linha 19 envia o valor exatamente para o campo de input que deve ser preenchido antes do
submit (linha 21) ser enviado. No final, extramos o valor do
atributo title do mesmo driver que j estar atualizado com
a resposta.
Para conferir o resultado, execute a aplicao via comando Run
e voc ver algo parecido com o contedo da Listagem 4.
Listagem 4. Cdigo de resultado da execuo.
01 ADVERTNCIA: CSS error: http://www.google.com.br/?gfe_rd=cr&ei=
Z1h4VdzSMabX8gew3oHgAg [1:9364] Error in expression;
: found after identifier progid.
02 jun 10, 2015 12:31:42 PM com.gargoylesoftware.htmlunit.DefaultCssError
Handler error
03 [...]
04 ADVERTNCIA: CSS error: http://www.google.com.br/?gfe_rd=cr&ei=Z1h4Vdz
SMabX8gew3oHgAg [1:12791] Error in expression. (Invalid token ;.
Was expecting one of: <S>, <NUMBER>, inherit, <IDENT>, <STRING>, -,
<PLUS>, <HASH>, <EMS>, <EXS>, <LENGTH_PX>, <LENGTH_CM>,
<LENGTH_MM>, <LENGTH_IN>, <LENGTH_PT>, <LENGTH_PC>,
<ANGLE_DEG>, <ANGLE_RAD>, <ANGLE_GRAD>, <TIME_MS>, <TIME_S>,
<FREQ_HZ>, <FREQ_KHZ>, <RESOLUTION_DPI>, <RESOLUTION_DPCM>,
<PERCENTAGE>, <DIMENSION>, <URI>, <FUNCTION>.)
05 [...]
06 jun 10, 2015 12:31:42 PM com.gargoylesoftware.htmlunit.DefaultCssError
Handler error
07 ADVERTNCIA: CSS error: http://www.google.com.br/?gfe_rd=cr&ei=Z1h4VdzS
MabX8gew3oHgAg [1:15068] Error in expression;
: found after identifier progid.
08 jun 10, 2015 12:31:42 PM com.gargoylesoftware.htmlunit.DefaultCssError
Handler error
09 [...]
10 O ttulo da pgina : Queijo! - Pesquisa Google

Veja que no final da listagem temos a exibio do ttulo da pgina. Nas linhas anteriores temos alguns erros exibidos (dentre
outros que foram omitidos da listagem) que caracterizam o processo de validao do Selenium, ou seja, sempre que alguma tag
no for fechada ou faltar algum atributo obrigatrio ou tivermos
qualquer erro a nvel de HTML, essas linhas sero impressas. Mas
no precisa se preocupar com isso, esse um comportamento
padro do Selenium.
Em algumas situaes ser preciso tambm acessar propriedades
via JavaScript de dentro das pginas. Por exemplo, suponha que
em vez de acessarmos o ttulo da pgina via mtodo getTitle()
do driver, ns quisssemos executar um script JavaScript que
fizesse o mesmo procedimento. Para isso, precisaramos fazer
uso da classe JavaScriptExecutor da API do Selenium e passar
a string do nosso script como parmetro para o seu mtodo
executeScript().
Entretanto, como em todo browser, tambm precisamos habilitar
o seu suporte ao JavaScript. Os browsers comuns j vm com ele
habilitado, mas no o caso do HTMLUnitDriver do Selenium.
Vejamos o cdigo da Listagem 5 para isso. Vamos acessar agora

o site da DevMedia que tem mais recursos visuais para usarmos


de exemplo.
Listagem 5. Cdigo para busca de elementos via JavaScript.
01 package br.edu.devmedia.selenium;
02
03 import java.util.concurrent.TimeUnit;
04
05 import org.openqa.selenium.By;
06 import org.openqa.selenium.JavascriptExecutor;
07 import org.openqa.selenium.WebDriver;
08 import org.openqa.selenium.WebElement;
09 import org.openqa.selenium.htmlunit.HtmlUnitDriver;
10
11 public class HTMLDriver {
12 public static void main(String[] args) {
13
HtmlUnitDriver driver = new HtmlUnitDriver();
14
driver.manage().timeouts().implicitlyWait(5, TimeUnit.SECONDS);
15
driver.setJavascriptEnabled(true);
16
17
driver.get(http://www.devmedia.com.br/);
18
19
WebElement element = driver.findElementByCssSelector(.dm-busca);
20
System.out.println(Cor de fundo: + element.getCssValue
(background-color));
21
System.out.println(Padding: + element.getCssValue(padding));
22
System.out.println(Classe CSS: + element.getAttribute(class));
23
24
JavascriptExecutor javascript = (JavascriptExecutor) driver;
25
String tituloPagina = (String) javascript.executeScript
(return document.title);
26
System.out.println(O ttulo da pgina : + tituloPagina);
27
28
driver.quit();
29 }
30 }

Veja que na linha 14 estamos configurando um timeout para


as requisies feitas ao HTMLUnitDriver. Isso porque os testes
podem ser impactados quando um request demorar muito a
retornar, logo voc tem essa opo em mos semelhante ao que
fazemos com Web Services. O mtodo implicityWait() define o
tempo mximo de processamento, no caso cinco segundos.
Em seguida, na linha 15, usamos o mtodo setJavascriptEnabled()
para definir que o JavaScript estar habilitado nesse browser. Se
estiver usando uma instncia do Firefox ou Chrome como fizemos
antes, esse cdigo no ser necessrio.
Nas linhas seguintes vemos algumas propriedades novas, a
saber:
Linha 19: O mtodo findElementByCssSelector() recebe o seletor
do elemento a ser recuperado na pgina HTML, no caso a caixa de
pesquisas da pgina inicial; A Tabela 1 traz uma lista completa
dos mtodos possveis.
Linhas 20 a 22: Imprimimos o valor das propriedades CSS de cor
de fundo, padding e classe do mesmo elemento, respectivamente;
Linha 24: Instanciamos um novo objeto do tipo JavascriptExecutor a partir do prprio objeto driver (que o herda automaticamente
pela herana de classes);
Linha 25: Chamamos o mtodo executeScript() passando
o JavaScript que queremos que seja executado no browser.

Copyright - Proibido copiar ou distribuir. Todos os direitos reservados para DevMedia

45 45

Edio 04 Front-end Magazine

Testes automatizados com o framework Selenium

Essa clusula sempre deve vir precedida da palavra-chave return, j que precisamos que algo seja retornado;
Linha 28: Encerramos o driver.
Para verificar o resultado, reexecute a aplicao e voc dever
ver no console a mensagem impressa pela Listagem 6.
Listagem 6. Mensagem final de execuo do teste.
Cor de fundo: rgb(48, 47, 49)
Padding: 95px 0 45px 0
Classe CSS:container-fluid dm-busca
O ttulo da pgina : DevMedia - Tutoriais, Videos e Cursos de Programao

Agora suponha que precisamos migrar toda essa lgica de testes


para o Firefox. Mais que isso, precisamos enviar apenas um texto
de sugesto para a caixa de pesquisa do Google, mas sem clicar
no submit. E aps isso, esperar at que a caixa de sugestes aparea para que recuperemos todas as sugestes que o Google deu
para a palavra informada. Vejamos como ficaria o nosso mtodo
main (Listagem 7).
At a linha 18 fazemos a mesma configurao de recuperao
do campo de pesquisa e informao da string a ser pesquisada.
Na linha 20 criamos uma varivel inteira com um valor cinco
segundos frente do tempo atual atravs do mtodo currentTimeMillis(), assim teremos como pausar a execuo do Selenium
at que a pgina de sugestes seja gerada. O teste se baseia nos
cinco segundos ou at que o objeto driver encontre o elemento de
classe CSS sbdd_b que corresponde respectiva caixa.
Uma vez encontrada (linha 24), recuperamos todos os elementos
que casem com o xpath (expresso de caminho) da linha 29. Essa
expresso diz que o driver tem de buscar por todos os elementos
do tipo div que tenham classe CSS com valor sbqs_c que correspondem aos itens de sugesto.
No final, iteramos sobre essa lista (linha 31) e exibimos todos os
seus valores (geralmente quatro). O interessante a se notar que
dessa vez acompanharemos a execuo j que estamos executando
via driver do Firefox.
Para ver o resultado, reexecute a aplicao e aguarde. Voc
dever ver uma tela semelhante da Figura 6 aparecer e fechar
sozinha quando finalizar o teste, bem como o texto da Listagem 8
aparecer no console da IDE.

Listagem 7. Teste caixa de sugestes do Google.


01 package br.edu.devmedia.selenium;
02
03 import java.util.concurrent.TimeUnit;
04
05 import org.openqa.selenium.By;
06 import org.openqa.selenium.JavascriptExecutor;
07 import org.openqa.selenium.WebDriver;
08 import org.openqa.selenium.WebElement;
09 import org.openqa.selenium.htmlunit.HtmlUnitDriver;
10
11 public class HTMLDriver {
12 public static void main(String[] args) throws Exception {
13
WebDriver driver = new FirefoxDriver();
14
15
driver.get(http://www.google.com/webhp?complete=1&hl=en);
16
17
WebElement query = driver.findElement(By.name(q));
18
query.sendKeys(devmedia);
19
20
long end = System.currentTimeMillis() + 5000;
21
while (System.currentTimeMillis() < end) {
22
WebElement resultsDiv = driver.findElement(By.className(sbdd_b));
23
24
if (resultsDiv.isDisplayed()) {
25
break;
26
}
27
}
28
29
List<WebElement> allSuggestions = driver.findElements
(By.xpath(//div[@class=sbqs_c]));
30
31
for (WebElement suggestion : allSuggestions) {
32
System.out.println(suggestion.getText());
33
}
34
35
driver.quit();
36
}
37 }
Listagem 8. Mensagem final de execuo do teste com sugestes impressas.
devmedia
devmedia cursos
devmedia player
devmedia java magazine
jun 10, 2015 1:04:47 PM org.openqa.selenium.os.UnixProcess$SeleniumWatchDog
destroyHarder
INFORMAES: Command failed to close cleanly. Destroying forcefully (v2). org.
openqa.selenium.os.UnixProcess$SeleniumWatchDog@53aad5d

Estratgia

Sintaxe

Descrio

Por ID

driver.findElement(By.id(<ID do elemento>))

Recupera um elemento pelo atributo id

Por nome

driver.findElement(By.name(<Nome do elemento>))

Recupera um elemento pelo atributo name

Por nome da classe

driver.findElement(By.className(<Classe CSS do elemento>))

Recupera um elemento pelo atributo class

Pelo nome da tag

driver.findElement(By.tagName(<Nome da tag HTML>))

Recupera um elemento pelo nome da tag HTML

Pelo texto do link

driver.findElement(By.linkText(<Texto do Link>))

Recupera um link usando seu texto.

Pelo texto parcial do link

driver.findElement(By.partialLinkText(<Texto parcial do Link>))

Recupera um link pelo seu texto parcial

Por CSS

driver.findElement(By.cssSelector(<Seletor do elemento>))

Recupera um elemento pelo seu seletor CSS

Por XPath

driver.findElement(By.xpath(<expresso query xpath>))

Recupera um elemento usando um query XPath

Tabela 1. Lista de mtodos para recuperar elementos no Selenium

46 Front-end Magazine Edio 04

46

Copyright - Proibido copiar ou distribuir. Todos os direitos reservados para DevMedia

no precisamos baix-los estaticamente. A pgina traz apenas dois


campos de input (email e senha, linhas 22 e 32), trs checkboxes, dois
botes de rdio e o boto de submit no fim da mesma. Voc pode
visualizar a pgina executando o arquivo diretamente no browser,
tal como mostrado na Figura 7.
Figura 6. Tela de teste no Firefox com sugestes
A mensagem final quer dizer que, uma vez que chamamos o
mtodo driver.quit() a instncia do Firefox ser finalizada.

Seletores jQuery
A biblioteca jQuery extremamente mais simples e produtiva
de usar em relao ao JavaScript puro. Voc pode optar por us-la
em conjunto com seus seletores para recuperar elementos, definir
eventos e funes de callback, bem como enviar submits em formulrios. Para criar um cenrio mais prximo da realidade dos
projetos, vamos criar uma pgina de cadastro de usurio simples
com suporte a jQuery para os scripts e Bootstrap para o estilo e
estrutura da mesma. Vejamos na Listagem 9 o cdigo para isso.
A listagem faz a importao no incio dos arquivos de script necessrios para carregar o jQuery e o estilo do Bootstrap (linhas 7 a 9).
Os imports foram feitos via CDN (Content Delivery Network) portanto,

Figura 7. Tela de cadastro de usurios para teste

Listagem 9. Cdigo da pgina HTML de cadastro de usurios.


01 <!DOCTYPE html>
02 <html lang=en>
03 <head>
04 <title>Selenium Teste</title>
05 <meta charset=utf-8>
06 <meta name=viewport content=width=device-width, initial-scale=1>
07 <link rel=stylesheet href=http://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/
css/bootstrap.min.css>
08 <script src=https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js>
</script>
09 <script src=http://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/js/
bootstrap.min.js></script>
10 </head>
11 <body>
12
13 <div class=container>
14 <div class=col-md-12>
15 <h2>Cadastro de Pessoa</h2>
16 <div class=panel panel-info>
17
<div class=panel-heading>Formulrio Bsico</div>
18
<div class=panel-body>
19
<form role=form>
20 <div class=form-group>
21
<label class=control-label for=exampleInputEmail1>Email</label>
22
<input type=email class=form-control id=exampleInputEmail1
placeholder=Digite seu email>
23 </div>
24
25 <div class=form-group>
26
<label class=control-label for=exampleInputPassword1>Password</label>
27
<input type=password class=form-control id=exampleInputPassword1
placeholder=Digite sua senha>
28 </div>
29

30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52

<div class=form-group>
<div class=checkbox>
<label> <input type=checkbox> Ativo </label>
</div>
<p class=help-block>Lorem ipsum dolor sit amet</p>
</div>
<div class=form-group>
<label class=control-label>Opes</label>
<div class=checkbox>
<label> <input type=checkbox name=optionsRadios
id=optionsCheckbox1 value=option1 checked=> Opo 1 </label>
</div>
<div class=checkbox>
<label> <input type=checkbox name=optionsRadios
id=optionsCheckbox2 value=option2> Opo 2 </label> </div>
</div>
<div class=form-group>
<label class=control-label>Sexo</label>
<div class=radio>
<label> <input type=radio name=optionsRadios id=optionsRadios1
value=option1 checked=> Masculino </label>
</div>
<div class=radio>
<label> <input type=radio name=optionsRadios id=optionsRadios2
value=option2> Feminino </label>
</div>
</div>

53
54
55
56 <button type=submit class=btn btn-default>Criar Usurio</button>
57 </form>
58 </div>
59 </div></div></div></body></html>

Copyright - Proibido copiar ou distribuir. Todos os direitos reservados para DevMedia

47 47

Edio 04 Front-end Magazine

Testes automatizados com o framework Selenium

Listagem 10. Cdigo para acessar propriedades da pgina de cadastro.


01 package br.edu.devmedia.selenium;
02
03 import java.util.concurrent.TimeUnit;
04
05 import org.openqa.selenium.By;
06 import org.openqa.selenium.JavascriptExecutor;
07 import org.openqa.selenium.WebDriver;
08 import org.openqa.selenium.WebElement;
09 import org.openqa.selenium.htmlunit.HtmlUnitDriver;
10
11 public class HTMLDriver {
12 public static void main(String[] args) {
13
WebDriver driver = new FirefoxDriver();
14
driver.get(file:///D:/Downloads/login.html);
15
16
List<String> checked = Arrays.asList(new String[]{optionsCheckbox1,
optionsRadios1});
17
JavascriptExecutor js = (JavascriptExecutor) driver;
18
19
@SuppressWarnings(unchecked)
20
List<WebElement> checkedElements = (List<WebElement>)
js.executeScript(return jQuery.find(:checked));
21

22
23

@SuppressWarnings(unchecked)
List<WebElement> focusElements = (List<WebElement>)
js.executeScript(return jQuery.find(:focus));

24
25
if (checkedElements.size() == 2)
26
System.out.println(Duas checkboxes selecionadas);
27
28
if (focusElements.size() == 1)
29
System.out.println(Campo com foco: + focusElements.get(0).getAttribute(id));
30
31
for (WebElement element : checkedElements) {
32
if (checked.contains(element.getAttribute(id))) {
33
System.out.println(Elemento contm id);
34
}
35
}
36
37
js.executeScript(jQuery(#optionsRadios2).attr(checked, checked));
38
js.executeScript(jQuery(button[type=\submit\]).text(Texto Mudado));
39
40
// driver.close();
41 }
42 }

Nossos objetivos com esta pgina sero (Listagem 10):


Buscar todos os elementos checked e exibir a quantidade;
Buscar o id do elemento que recebeu o foco (email);
Mudar a seleo do campo sexo para feminino;
Mudar o texto do boto de submit para Texto Mudado.
A primeira mudana significativa est na linha 14, onde estamos acessando o arquivo HTML localmente, diretamente da
pasta onde voc salvou a pgina. Dessa forma no precisamos
hospedar a aplicao para fazer os testes e o Selenium prov
esse recurso de maneira off-line. Na linha 16 criamos uma lista
de WebElements para recuperar todos os itens checados (rdio e
checkbox) da pgina. Veja que nesse trecho onde executamos o
primeiro cdigo jQuery que precisa ter o seletor informado dentro
mtodo executeScript().
Na linha 23 fazemos a mesma seleo, s que agora para o campo
que tem o foco (:focus). Na linha 25 testamos o tamanho da lista
de elementos checados e na linha 28 para a lista de elementos
com foco. Da linha 31 a 35 verificamos se algum dos elementos
recuperados contm o atributo id, apenas para imprimir a
mensagem de sucesso.
No final, na linha 37 executamos o cdigo jQuery para selecionar
o rdio de Feminino, e na linha 38 mudamos o texto do boto de
submit.
Para verificar o resultado, reexecute a aplicao e voc ver algo
semelhante ao que temos na Figuras 8 (no browser Firefox) e 9
(no console da IDE).
O leitor ainda pode adicionar mais arquivos de scripts ou CSS
dinamicamente a partir do cdigo Selenium via varivel var headID que est disponvel para representar o cabealho da pgina.
Isso vale, inclusive, para quaisquer frameworks jQuery que queira
acrescentar na implementao.

48 Front-end Magazine Edio 04

48

Figura 8. Tela de cadastro de usurios aps o teste

Figura 9. Tela de console com resultado da execuo

Selenium IDE na prtica


A Selenium IDE uma ferramenta de testes para aplicaes web
totalmente integrada com os conceitos do framework no que se
refere gravao e playback dos testes de regresso. Atravs dela,
o desenvolvedor no mais obrigado a usar qualquer linguagem
de programao, apesar de poder fazer isso. Tambm possvel
exportar os scripts para quaisquer linguagens suportadas.

Copyright - Proibido copiar ou distribuir. Todos os direitos reservados para DevMedia

Os scripts criados para a aplicao de teste so chamados


de casos de teste e um conjunto de casos de teste chamado
de sute. Para trabalhar com ela, preciso primeiro fazer o

download (seo Links). Efetue o download da verso mais


recente na subseo Selenium IDE e d um click duplo para
iniciar a instalao.
importante que o leitor considere que essa IDE s suportada
pelo Firefox, logo no possvel configur-la em outros browsers
(caso prefira o Chrome, use a opo com Java mostrada na seo
anterior). Reinicie o Firefox e pronto, sua IDE est instalada. Para
verificar, v at a opo Tools > Selenium IDE e uma janela igual
da Figura 10 ir aparecer.
Na Tabela 2 voc pode encontrar um detalhamento dos principais botes e funcionalidades fornecidos pela IDE.

Primeiros testes na IDE


Agora que temos a IDE instalada, podemos gravar um teste
automatizado apenas usando a aplicao desejada normalmente.
Faamos um teste com os seguintes passos:
1. Entrar no site da DevMedia.
2. Clicar no boto Login.
3. Digitar um login e senha qualquer.
4. Clicar em OK.

Figura 10. Janela da Selenium IDE no Firefox

O teste demasiadamente simples, mas o suficiente para que


voc entenda como o Selenium salva seus scripts. Agora, abra
uma nova aba do browser (em branco) e na IDE clique no boto

Boto

Descrio

Controlador de Velocidade

usado para controlar o quo rpidos seus casos de teste iro executar.

Boto Run All

usado para executar a sute de testes completa, com todos os testes


adicionados a ela. A execuo ocorre na ordem em que os testes forem
declarados.

Botes Pause/Resume

O primeiro boto pausa a execuo do teste atual, enquanto o segundo


retoma-a.

Boto Step

usado para executar os comandos de teste um por um, manualmente.


Suponha que voc tenha pausado o teste e agora deseja ver linha por
linha o que est acontecendo.... Esse boto faz isso, simulando um debug
comum.

Botes Record/Stop Recording

O primeiro usado para iniciar a gravao de um script e o segundo para


encerr-la.

Boto Toggle Schedule

usado para agendar execues de script. Serve para situaes onde o


software precisa rodar um teste de tempos em tempos, sem a necessidade de um humano por perto.

Janela Table

Exibe os comandos gravados. Voc pode modificar e incluir novos comandos, que so divididos em trs partes:
Command: descreve o nome do comando;
Target: descreve o elemento alvo (id ou name) do Xpath;
Value: descreve o valor do elemento.

Tabela 2. Lista de botes e comandos padro da Selenium IDE

Copyright - Proibido copiar ou distribuir. Todos os direitos reservados para DevMedia

49 49

Edio 04 Front-end Magazine

Testes automatizados com o framework Selenium

Record. Em seguida, efetue a lista de passos que mostramos e


ao finalizar, clique no boto Stop Recording.
Ao final, sua IDE estar semelhante que temos na Figura 11.
Veja que temos cinco comandos com tipos e targets diferentes.
Por exemplo: o tipo open define que entramos numa URL
(exibida no topo da janela, no campo Base URL); o tipo click
define que clicamos num elemento de nome usuario e o tipo
clickAndWait define que foi enviado um submit e que o Selenium deve aguardar at que a resposta retorne. Em relao aos
campos que precisam de um valor a ser informado (input text), a
terceira coluna preenchida com os mesmos.

Listagem 11. Cdigo script gerado para o teste na Selenium IDE.


01 <?xml version=1.0 encoding=UTF-8?>
02 <!DOCTYPE html PUBLIC -//W3C//DTD XHTML 1.0 Strict//EN http://www.
w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd>
03 <html xmlns=http://www.w3.org/1999/xhtml xml:lang=en lang=en>
04 <head profile=http://selenium-ide.openqa.org/profiles/test-case>
05 <meta http-equiv=Content-Type content=text/html; charset=UTF-8 />
06 <link rel=selenium.base href=http://www.devmedia.com.br/ />
07 <title>New Test</title>
08 </head>
09 <body>
10 <table cellpadding=1 cellspacing=1 border=1>
11 <thead>
12 <tr><td rowspan=1 colspan=3>New Test</td></tr>
13 </thead><tbody>
14 <tr>
15 <td>open</td>
16 <td>/</td>
17 <td></td>
18 </tr>
19 <tr>
20 <td>click</td>
21 <td>css=div.popover1</td>
22 <td></td>
23 </tr>
24 <tr>
25 <td>type</td>
26 <td>name=usuario</td>
27 <td>test</td>
28 </tr>
29 <tr>
30 <td>type</td>
31 <td>name=senha</td>
32 <td>123</td>
33 </tr>
34 <tr>
35 <td>clickAndWait</td>
36 <td>css=button[type=&quot;submit&quot;]</td>
37 <td></td>
38 </tr>
39
40 </tbody></table>
41 </body>
42 </html>

Figura 11. Selenium IDE com testes finalizados e gravados


Voc tambm pode modificar os seus testes via script. Clique
na aba Source ao lado de Table e voc ver um contedo semelhante ao da Listagem 11.
O contedo do script sempre gerado em HTML, logo temos as
importaes das tags meta e link na tag head, bem como a tabela com
os comandos logo abaixo. aconselhvel que o leitor sempre utilize
a opo grfica para evitar qualquer erro de sintaxe na ferramenta.
Agora, sempre que quiser reexecutar o mesmo teste, basta selecionar o nome do test case na barra lateral esquerda e clicar no
boto Play test suite.

Sobre os Casos de Teste


A primeira vez que abrimos a IDE do Selenium o boto de gravao j vem ativado, e isso permite uma interao via uso do site
que ter seus scripts salvos. Se voc no deseja que a IDE faa isso,
v at o menu Options > Options... e desmarque a opo Start
recording immediately on open.

50 Front-end Magazine Edio 04

50

Quando se est construindo um caso de testes, algumas consideraes devem ser levadas em conta:
Para gravar aes do tipo submit, necessrio que o usurio
clique no boto em vez de dar um enter em algum dos campos do
formulrio. Isso porque o Selenium no consegue reconhecer esse
evento e associar a um envio de request, j que o usurio pode
dar vrios enters, ou ter um controle de navegao de campo para
campo via tecla Enter, em vez de Tab.
Quando clicamos em um link durante uma gravao, o Selenium
IDE grava o comando no tipo click. Porm, voc deve mudar
esse tipo para clickAndWait para garantir que o seu caso de
teste far uma pausa at que a pgina carregue por completo e
o fluxo possa prosseguir sem erros. Caso contrrio, nosso caso
de teste continuar executando os comandos antes que a pgina
tenha todos os elementos UI carregados na HTML.
Os seus casos de teste tambm tero que verificar as propriedades de uma pgina da web. Isso requer o uso dos comandos assert

Copyright - Proibido copiar ou distribuir. Todos os direitos reservados para DevMedia

(comparar dois valores) e verify (fazer um teste qualquer). Quando


o Selenium IDE estiver gravando, v at o navegador exibindo
seu aplicativo de teste e clique com o boto direito em qualquer
lugar da pgina. Ser exibido um menu de contexto mostrando
os referidos comandos bem como outros (Figura 12) que podem
ser usados via Selenium.

verifyText: verifica se o texto esperado e sua tag HTML correspondente esto presentes na pgina;
verifyTable: verifica se contedo esperado de uma tabela est
presente;
waitForPageToLoad: finaliza a execuo at que uma nova
pgina seja carregada. Chamado automaticamente quando o
clickAndWait usado;
waitForElementPresent: finaliza a execuo at que um elemento da interface do usurio esperado, conforme definido pela
sua tag HTML, est presente na pgina.
Existem inmeras outras abordagens nas quais o leitor poder
usar o Selenium. Como vimos, a automao precisa estar obrigatoriamente vinculada a telas, estejam elas executando num PC,
smartphone, tablet, etc. O Selenium conta ainda com dois drivers
especficos para ambientes mveis: AndroidDriver, classe da API
do Selenium exclusiva para dispositivos Android; e iWebDriver,
para simular testes em ambiente iOS.
Tambm possvel integrar o Selenium com o JUnit, QUnit,
JTestDriver e outros inmeros frameworks de teste unitrio disponveis no mercado. Os arquivos que eles geram em conjunto so
leves e podem facilmente se adaptar a um controle de integrao
com o Jenkins, por exemplo, bem como ser manuseados por ferramentas de versionamento (Git, Mercurial, etc.).
Para os desenvolvedores PHP que querem fazer uso do Selenium,
o mesmo no prov suporte nativo linguagem, mas possvel
usar o PHPUnit: uma instncia do xUnit para testes unitrios que
traz consigo mdulos do Selenium que podem ser instalados via
linha de comando.

Figura 12. Menu de contexto com comandos Selenium


A primeira vez que voc acessar a IDE, ter apenas um ou dois
comandos disponveis. Mas medida que for criando seus casos
de teste e o browser for efetuando operaes mais complexas,
como submits, scrolling, dentre outras, o Selenium ir preenchendo essa lista automaticamente com as opes que ela julgar
que voc possa precisar. Dentre a lista de comandos mostrada na
figura, os principais so:
open: abre uma pgina usando a URL passada;
click/clickAndWait: executa uma operao de clique e, opcionalmente, aguarda uma nova pgina carregar;
verifyTitle/assertTitle: verifica se um ttulo esperado para a
pgina est presente;
verifyTextPresent: verifica se um texto esperado est em algum
lugar na pgina;
verifyElementPresent: verifica se um elemento UI esperado, tal
como definido pela sua tag HTML, est presente na pgina;

Autor
Sueila Sousa
tester e entusiasta de tecnologias front-end. Atualmente
trabalha como analista de testes na empresa Indra, com foco
em projetos de desenvolvimento de sistemas web, totalmente
baseados em JavaScript e afins. Possui conhecimentos e experincias
em reas como Gerenciamento de processos, banco de dados, alm do
interesse por tecnologias relacionadas ao desenvolvimento e teste client side.
Links:
Pgina oficial de download do JDK.
http://www.oracle.com/technetwork/java/javase/downloads/index.html
Pgina oficial de download do Eclipse.
https://eclipse.org/downloads/
Pgina de download do driver do Chrome para o Selenium.
http://chromedriver.storage.googleapis.com/index.html

Copyright - Proibido copiar ou distribuir. Todos os direitos reservados para DevMedia

51 51

Edio 04 Front-end Magazine

Testes automatizados com o framework Selenium

52 Front-end Magazine Edio 04

52

Copyright - Proibido copiar ou distribuir. Todos os direitos reservados para DevMedia

Vous aimerez peut-être aussi