Fork me on GitHub

Viagens, opiniões e afins

by Andre Fonseca


MVC no javascript

No artigo anterior que escrevi sobre Jasmine, recebi um comentário de um amigo no qual ele me perguntava como fazer para testar códigos Javascript que interagem com o DOM ou que tenham uma certa dependência dele.

O primeiro impulso foi de responder para usar um recurso de Fixtures ( ou similiar), onde ele pode “criar” elementos no DOM durante um cenário de teste e depois removê-los para não atrapalhar os demais. Embora isso resolva o problema dele – de testar funções que precisem de elementos HTML, a pergunta dele suscita uma discussão bem mais ampla e interessante.

Hoje é um fato que nossos front-end ( client side ou interface web ou como queira chamar) são cada vez mais ricos … Tem muito ( mas muito mesmo) código Javascript para criar uma experiência para o usuário boa. Se acha que estou exagerando, abrar seus próprios arquivos ou então converse com um desenvolver front-end mais experiente.

Com uso maior do javascript, o cuidado com seu uso também tem que ser maior. Não é mais aquela função de duas linhas que abre um alert ou aquelas validações simples do seu form. Acredito que em muitas páginas a quantidade de linhas de Javascript é maior que a de html e css. Tudo depende da riqueza da experiência ( veja que não estou considerando CSS3 que “substitui” bastante algumas coisas).

Mas chega de enrolação e vamos ao que interessa: como a gente organiza melhor o nosso código.
Primeira dica é separá-lo em um arquivo. Nada de script na página, por favor. Deixe para fazer isso em última instância. Acredite, sempre existe um jeito de desacoplar.

Caso você já tenha programado alguma coisa no SERVER-SIDE(adoro esse nome, parece que é outra dimensão), sabe que existem diversos padrões de designs( boas práticas). Um deles, e mais famoso, é o MVC – model view controller. Esse pattern ajuda a gente manter bem separado a lógicas de apresentação da lógica de negócio. Assim ao mexer num, não necessariamente precisará mexer noutro.

Seguindo essa filosofia, procuro desenvolver minhas lógicas de forma que eu separe bem oque é apresentação/animação da lógica de “negócio” da minha página. Por exemplo, imaginemos que agora temos que validar alguns dados e mostrar um aviso com os erros. O que faria seria quebrar isso em diversas funções. Uma para cada camada, no mínimo:

function validaCampo(dados){
...
}

function avisaErro(mensagem){
...
}

Erros = {
  "nome_obrigatorio": "Campo nome deve ser obrigatorio"
}

Sei que o exemplo acima pode ser muito simples. Mas ele facilita testar e ainda por cima facilita alterar qualquer coisa na lógica de cada parte sem ter que mexer em um monte de lugar ou ter um método de 40 linhas para fazer uma validação.

Outro exemplo, mais próximo do real, imagina que recebe dados de um form, posta-os via ajax, atualiza uma listagem abaixo e mostra mensagem de sucesso ou erro:

function Requisicao(){
}

Requisicao.prototype.envia = function(url,dados){ //faz algo aqui};

function ItemLista(){}

ItemLista.prototype.renderizaHtml = function(){ //aqui voce pode colocar a logica e escrever o item no html};

function submit(){
  var form = document.getElementByTag("form");
  ...
  var requisicao = new Requisicao();
  var item;
  try {
    requisicao.envia(form.url);
    item  = new Item(requisicao);
  catch {
    avisaErro("Ocorreu um envio no envia de dados");
  }

  item.renderizaHtml();
}

O exemplo acima é apenas conceitual e está faltando coisa para caramba. Mostra bem, como separar bem as coisas e garantir uma boa legibilidade. Para testar isso você pode fazer sem precisar de acessar o DOM, fazendo mock das chamadas onde isso ocorre.

Bom num próximo artigo avançamos mais no assunto e mostro algumas bibliotecas e frameworks para ajudar nesse sentido.

Published by Andre, on outubro 18th, 2011 at 5:11 pm. Filled under: agil,TDD Tags: , , , 1 Comment

Jasmine testes: Usando o before e o after e testes assincronos.

Um dos pontos fortes que considero no Jasmine é seu “suporte” a execuções assíncronas para teste. Isso significa, que dado aquele seu código, que tem um chamada que tem duração de tempo, ocorre com callback, etc, você será capaz de testar isso com relativa facilidade com Jasmine.

 
Somente para lembrar, todo arquivo de teste do Jasmine é composto de um contexto onde temos diversas asserts que irão validar o funcionamento do nosso código:

describe("teste de algo", function(){
    it("deve acontecer algo e o valor ser outro", function(){
        expect(true).toBeTruthy();
    });
});

 

No código acima criamos o contexto com a função describe, que recebe um texto com a descrição e uma função a ser executada. Dentro do corpo da função a gente tem a chamada do it que também recebe um texto com descrição e um função.

Uma coisa legal é que como qualquer framework de teste, ele tem métodos para executar código antes e depois de cada teste (acertiva). Esse métodos são o beforeEach (para executar algo antes) e o afterEach(para executar o depois).
Essas funções recebem como argumento uma função cujo o corpo será executado. Veja o exemplo abaixo:

describe("teste algo com before e after", function(){
    var variavel;

    beforeEach(function(){
        variavel = true;
    });

    afterEach(function(){
        variavel = false;
    });

    it("teste", function(){
        expect(variavel).toBeTruthy();
    });
});

 
Mais isso não é o objetivo do artigo. O nosso objetivo é mostrar o quão é fácil colocar a rotina de espera para dentro do seu teste:

describe("teste algo com before e after", function(){
    var variavel;

    beforeEach(function(){
        variavel = true;
        setTimeout(function(){
            variavel = false;
        }, 100);

    });

    it("teste", function(){
        expect(variavel).toBeTruthy();
        waits(200);
        runs(function(){
            expect(variavel).toBeFalsy();
        });
    });
});

 
O método de waits que usamos acima, gerar uma espera para a execução de 200 milisegundos. Depois ele irá executar na ordem, o contéudo das funções runs que vierem em seguida. Com isso podemos ter testes para nossas animações ou até chamadas com callback. Para callback, ao invés de usarmos a função waits, devemos usar a a função waitFor que recebe uma função que retornará true ou false.

Bem ficamos por aqui. Leia a documentação do projeto e aguarde nosso próximo posts. Aguardo os comentários.

Published by Andre, on outubro 6th, 2011 at 7:30 pm. Filled under: agil,TDD Tags: , , , , , No Comments

Jasmine BDD: Instalando e escrevendo primeiro teste

Para os que ficaram interessados devido aos posts anteriores em usar o Jasmine BDD para fazer (até começar a fazer) seus testes, esse será o primeiro de uma série de artigos que tentaram explicar o como usar, como escrever seus testes e coisas mais avançadas como assíncrono e stub.

Primeira coisa é que caso não esteja familiarizado em escrever testes ou está começando a programar, antes de mais nada aprender os conceitos básicos e procure um Dojo mais próximo de você. Independente de ser testes em javascript ou qualquer outra linguagem, escrever testes é uma forma de pensar e filosofia que deve ser aprendida. Senão, você ficará perdido, sem saber por onde começar e além disso, não conseguirá colher os benefícios que isso trará para seu produto.

Avisos paroquiais feitos vamos ao que interessa.

Antes de escrever a sua primeira linha de qualquer coisa é preciso que instale as coisas. Nesse momento, seguiremos do jeito mais simples e hard, sem uso de ferramentas, linhas de comando, etc. Vamos nos ater ao básico e mais simples.

O Jasmine BDD é uma biblioteca Javascript. (.js). Ele roda dentro de uma página com alguma markup que permite que ele coloque na tela a saída do resultado da tela. Sendo assim, acesso o site do produto (clique aqui). Na página principal escolhe a opção de standalone. (voce pode ir direto para esse link).

Ao descompactar o arquivo verá uma estrutura de arquivos e pastas, praticamente pronta para uso. Para rodar os testes basta carregar o SpecRunner.html no seu browser preferido.  Suas specs(js com testes). Devem ficar dentro da pasta spec (vejo o exemplo que vem junto). É costume chamar o nome do arquivo com o nome do que irá testar seguido de Spec.

 

Para incluir um novo teste ou um novo arquivo de dependencia (tipo jquery ou mootools) bastar colocar a chamada no SpecRunner.html

 

<html>
<head>
  <title>Jasmine Test Runner</title>
  <link rel="stylesheet" type="text/css" href="lib/jasmine-1.0.2/jasmine.css">
  <script type="text/javascript" src="lib/jasmine-1.0.2/jasmine.js"></script>
  <script type="text/javascript" src="lib/jasmine-1.0.2/jasmine-html.js"></script>

  <!-- include source files here... -->
  <script type="text/javascript" src="src/Player.js"></script>
  <script type="text/javascript" src="src/Song.js"></script>

  <!-- include spec files here... -->
  <script type="text/javascript" src="spec/SpecHelper.js"></script>
  <script type="text/javascript" src="spec/PlayerSpec.js"></script>

</head>
<body>

<script type="text/javascript">
  jasmine.getEnv().addReporter(new jasmine.TrivialReporter());
  jasmine.getEnv().execute();
</script>

</body>
</html>

 
Só com isso, você já tem o seu framework de teste funcionando perfeitamente em sua máquina.

Seu arquivo de teste é composto por, basicamente, dois blocos – um dentro do outro. Num bloco você descreve ou define o contexto. Ele é definido pelo método describe. Assim todo teste jasmine deve começar por:

describe("contexto", function(){
//Aqui dentro as expectativas
});

&nbps;

Assim como o Rspec, no qual o Jasmine se inspirou, a idéia não é simplesmente pensar em testes unitários e sim criar expectativas, coisa que tem mais a ver com o BDD.

Assim se continuar nossos testes ficarão assim:

describe("contexto", function(){
  it("deve ser true", function(){
    expect(true).toBeTruthy();
  });
});

 

Pronto taí o seu primeiro teste com jasmine escrito. Onde, o it define o ponto de teste dentro daquele contexto. Ele contém uma frase que será exiba na execução do teste no HTMl e facilita o entendimento do objeto do teste. Os asserts são feitos usando um método expect que define oque será auditado e em seguida o que espera de resultado.

Ficamos por aqui. No próximo post, vou falar sobre os matcher e vamos avançar mais sobre jasmine.

Published by Andre, on outubro 2nd, 2011 at 8:00 pm. Filled under: atualidades,TDD Tags: , , , 1 Comment

Escolhendo minha ferramenta de TDD para Javascript

Seguindo dentro da temática de testes e javascript. Quero falar de frameworks de testes.  Como já disse em artigos anteriores me rendi a pouco tempo a usar TDD para escrever meus javascript  (mais precisamente meus códigos de front end).  No momento que resolvi, influenciado por alguns, amigos parti em busca de ferramentas e frameworks que tornassem essa tarefa mais simples e produtiva.

Nesse mesmo momento estava trabalhando com um projeto em Rails e usava o Rspec para fazer os testes de todo meu código server.  O Rspec possui uma forma, sintaxe, para escrita de código que considero elegante e funcional: facilita a leitura, a compreensão e a escrita pois tem um jeitão que meio que te leva a escrever seus teste de forma bem estruturada.

Essa estrutura é basicamente formado por um contexto, que pode ou não conter outros contextos, e dentro dele as suas especificações. Assim se temos um Model a ser testado posso quebrar meus testes em vários contextos, por exemplo:

describe "Model Aluno" do
  before :each do
    @aluno = Aluno.new
  end

  subject { @aluno.nome }

  it "Deve ser um model válido" do
    @aluno.should be_valid
  end
end

 
Note como fica claro o alvo e o objetivo do teste. Para quem precisar entender o sistema basta ler as especificações do sistema que conseguirá pegar bem o funcionamento das coisas.

Bem, após ter provado isso, queria algo igual para testar meu javascript. A princípio pensei em usar o QUnit, pois ele é o framework oficial do pessoal que dsenvolve o Jquery. Como sempre achei o Jquery legal, pensei que algo que eles usem deve ser bom. Meu primeiro contato não foi bom e achei que meus testes ficaram feios, ruim de entender e ainda tinha vários problemas de mock, stub e testes assíncronos.

Descobri então o Jasmine BDD. Ele é exatamente tudo que queria pois seus desenvolvedores se inspiraram no RSpec para fazê-lo. Logo os primeiros pré-requisitos foram atendidos. Outra parada killer – lembrando que estava trabalhando num projeto rails – é sua integração com a app. Basta uma gem e alguns yamls e tudo funciona perfeitamente. Basta um rake jasmine e seus teste rodam.

Outro ponto sensacional é o fato dele já trazer uma api maravilhosa que muito lembra o Mock do Rails, incluso. Para ver se alguma coisa foi chamada fica mais ou menos assim:

spyOn(minhaClasse, "meuMetodo")
...
it("ve se foi chamado", function(){
  minhaClasse.meuMetodo("qualquer string");
  expect(minhaClasse.meuMetodo).toHaveBeenCalledWith(jasmine.any(String));
});

 

Por fim a decisão final veio pelo suporte que a api tem para teste assíncronos. Ou seja, sabe toda aquelas coisas de callback que você tem ou testes de animação.. Fica muito simples de escrever:

//codigo de animaçao com tempo aqui
..
wait(500);
run(function(){
expect(elemento.style('display')).toEquals('none')
});

 

Agora tudo isso parece que só é para código javascript que você escreve para o seu client side. Mas se você gosto do javascript no server side saiba que a biblioteca também pode e deve ser usado. Existem excelente pacotes para Node e outras plataformas (V8, Java – Rhino, etc).

Fiquem ligado no blog que em breve vou colocar uns tutoriais de coisas do Jasmine para você que ficou interessado mergulhar de cabeça nessa também.

Published by Andre, on setembro 30th, 2011 at 4:36 pm. Filled under: agil,codigo,TDD Tags: , , , , 2 Comments