Fork me on GitHub

Viagens, opiniões e afins

by Andre Fonseca


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

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

Você realmente está testando?

Na maioria dos livros que li nos últimos tempos do mais diversos assuntos ligados a engenharia de software, testes automatizados, e mais especificamente, TDD (test driven development) e BDD (behavior driven development) são dominantes. É certo que, atualmente, se desejamos ter qualidade e velocidade de entrega nos nosso produtos precisamos de testes automatizados. E vou além: digo que abordagens como TDD e BDD auxiliam o desenvolvedor a escrever código melhor e mais focado no valor para o cliente.

A questão é que se estabeleceu axiomas – verdades absolutas – onde para ser bom o projeto precisa ter 100% de cobertura de código e  ter testes unitários e testes de integração e testes de aceitação (tela e feature), etc. Isso nem sempre é verdade e pode ser um verdadeiro “tiro no pé”. Antes de mais nada é preciso entender a real função do teste. E qual será a melhor forma de utilizá-lo. Não estou discutindo aqui abordagens e sim se estamos usando de forma inteligente e consciente os testes.

Em uma conversa recente com Bernardo Heynemann, vimos, que, por exemplo, em alguns casos testes de aceitação que usavam Cucumber ou Pyccuracy, estavamos testando mais o navegador que a funcionalidade em si. Quando falamos de cobertura temos outro ponto interessante: 100% não é garantia de nada. Já ouvi falar  de sistemas com 100% de cobertura que quando foram fazer refactoring – confiando na cobertura de testes,  ”quebrou” tudo ao colocar em produção pois vários detalhes escaparam.  Isso porque, provavelmente existiam diversos testes que faziam “nada” e que ali estavam apenas para garantir a cobertura mínima.

Novamente citando Bernardo Heynemann, ele me disse que para os que estão começando, é importante seguir uma fórmula:  testes unitários, testes de integração, testes de aceitação, etc. Isso porque ainda estão formando sua base de experiência e tem pouco discernimento para saber quais seriam os pontos críticos a serem testados para termos a garantia de qualidade.  Mas a medida que for ganhando bagagem e aguçando seu senso crítico, é importante se questionar o que testar, como testar, etc.

Uma coisa que sempre falo é que testar da trabalho. Por mais que possa trazer benefícios, ainda é mais trabalho. Se falamos de testes automatizados – programáticos – é mais linha de código. Por exemplo, tiveram coisas que levei mais tempo escrevendo os testes do que implementando.  Teste onera sim.

Antes de mais nada quero esclarecer que não sou contra testes. Muito pelo contrário, acredito que não existe a possibilidade de fazer algo bem sem usar TDD ou BDD. A questão que levanto é o quanto estamos realmente testando nossos sistemas e o quanto estamos apenas “inventando” para cumprir com regras pré-definidas que ninguém de fato entendeu para que servem.

Um exemplo disso que estou falando é quando temos diversos níveis de teste em nossa aplicação … E testamos a mesma coisa em todos eles. Sabe aquele teste que você fica criando o Model, colocando os dados  no banco, acessando o banco, etc? Isso mesmo. É um bom smell disso que estou falando.

Uma coisa que faço é primeiro me concentrar no objetivo que quero atingir com aquele teste. Tudo mais é superfluo e logo pode ser ignorado(entenda mock e outras tecnicas).  Logo, se quero testar as chamadas do controller de minha aplicação, eu não preciso, nem quero me preocupar com que está acontecendo dentro do Model associado.   Outro ponto é se já testei algo em algum ponto, evito ficar testando novamente… Se por acaso isso for necessário é sinal que preciso fazer um refactoring no meu código.

Em futuro artigos pretendo trazer o assunto e ir mais fundo inclusive trazendo exemplos, trechos de código, etc.  Até a próxima.

 

 

 

Published by Andre, on abril 20th, 2011 at 7:21 pm. Filled under: codigo,TDD Tags: , , , 5 Comments

Pyccuracy – Uma boa ferramenta de teste. Coloque-a na sua maleta

Ultimamente, no meu emprego atual, tenho a oportunidade de usar um excelente framework de testes de aceitação brasileiríssimo que é o pycurracy . Ele é uma ferramenta feita em python que permite que você escreva suas histórias de aceitação em linguagem natural. Isso significa dizer, que você pode escreve o seu teste em português.

Não preciso dizer o quanto isso traz de vantagem. Só para citar, uma das mais imediatas, pelo menos para mim, é a questão da documentação.  Quem já está na estrada um tempo, sabe como é uma verdadeira luta manter documentações atualizadas do produto.  Tudo sempre começa bem, mas com o passar do tempo, sempre surgem outras tarefas mais urgentes e os “casos de uso”  ou histórias acabam ficando não condizentes com a realidade da aplicação.  Para muitos, isso pode soar como preciosismo porém imagine um contexto de um projeto open source… sem uma documentação bem feita, colaborar pode ficar bem difícil.

Um outro aspecto também é que desenvolvedores “não são muito amigos” de escrever documentos. Esta aí uma tarefa que vejo poucos colegas fazerem com prazer. Se puderem evitar, a grande maioria em minha humilde opinião,  evitarão fazê-lo.

Ferramentas como o pyccuracy, vem unir o “útil ao agradável”: vem possibilitar escrever testes, programando, e como resultado indireto obter uma excelente fonte para consultas.  Por permitir escrever os cenários  em linguagem natural (inglês e português) acabamos por ter um documento descrevendo o funcionamento esperado… as nossas histórias.

O pyccurace é todo feito em python usando o Selenium .  Para maiores detalhes recomendo uma visita a página do projeto.

A única coisa que tenho a dizer sobre ele é que bem que poderia ter uma implementação que usasse o WebDriver ao invés do Selenium RC. Acredito que ficaria bem mais rápido. Mas, até agora só temos versões estáveis do WebDriver para Java. A versão python está bem timida ainda.

Published by Andre, on março 12th, 2010 at 8:37 pm. Filled under: codigo,Java,python Tags: , , 1 Comment