Fork me on GitHub

Viagens, opiniões e afins

by Andre Fonseca


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

Respondendo uma pergunta sobre TDD

No post que anterior, no qual falei sobre TDD, recebi um comentário perguntando dentro de algumas situações se O TDD se encaixava ou não.  Como a dúvida é recorrente e o tema é bastante controverso, resolvi, ao invés de responder o comentário dele, escrever um post.

A primeira coisa, em minha opinião, que tem que ficar clara, que TDD é um metodologia de desenvolvimento e não de projeto. Usamos TDD para gerar código melhor e com isso aumentar a qualidade do que estamos fazendo.  Testar antes não é garantia de zero bugs, mas ajuda a construir uma solução melhor pensada, simples, concisa,  e, sim, com testes automatizados que irão evitar muitos bugs.

TDD é uma forma de trabalho que se encaixa em qualquer modelo de equipe/projeto.  Se o seu time está em algo mais ágil ou waterfall, não faz a mínima diferença. Sem o seu time, irá entregar complexidade, pontos por caso de uso ou pontos de função isso também não faz diferença.  Pois, como já disse, TDD é um filosofia de desenvolvimento e não de gestão.

Ela trabalha em cima de ciclos pequenos onde a gente escreve o teste com a necessidade; após escrevemos o código para atender a necessidade e fazer o teste passar e por fim revistamos a solução para melhorá-la buscando princípios de Clean Code ( SOLID).  Se no final desse ciclo temos uma história entrega (por exemplo uso de quadros – Kanban, etc) ou se temos um ponto de função, observe que não faz diferença.  O que pode acontecer, no caso de pf é que deverá prever isso ( eu acho – nunca trabalhei com pontos de função).

Uma boa dica é que procure um DOJO (acesse o site do DojoRio) e veja na prática isso acontecer e como ela não tem relação com a gestão.

Se quer entender mais sobre TDD leia o livro do Kent Beck. Existe uma infinidade de outros livros sobre tão bons, mas acredito que seja legal começar pelo início. Depois a medida que for se sentindo mais confortável …

Assim, sem mais rodeios vamos a resposta a pergunta que me fizeram:

1. Posso usar TDD com um projeto que me exija entregar 4 a 40Pf ou qualquer outra coisas?

SIM ! Se acha que estou exagerando, procure o Alex Gomes da SEA Tecnologias. Seu maior cliente é o governo federal.  Existem outros exemplos como por exemplo

2. Código legado ?

Sim dá para usar TDD. Para te ajudar recomendo a leitura do livro Working Effectively with Legacy Code do Michael Feathers. Ele é uma excelente forma de ver como você pode testar o seu código legado.

Por fim espero ter te ajudado. E caso tenham dúvidas podem comentar que irei responder.

 

Published by Andre, on setembro 28th, 2011 at 9:40 am. Filled under: atualidades,codigo,TDD Tags: , , , No 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

Mais uma do SOLR – Dynamic Fields

Como alguns que acompanham o blog já devem ter percebido, eu estou usando o SOLR em um projeto. O SOLR é um servidor Web de busca, feito em cima do Lucene (grupo Apache). Ele é realmente poderoso e simples de usar. Recomendo muito para quem precisa fazer buscar textuais pesados e que tem uma quantidade razoável de documentos/dados para indexar.  Como minha aplicação é Rails, estou usando uma GEM, chamada Sunspot, que serve de DSL (facilitador) nessa “conexão” entre minha app e o SOLR.

Nesse dias surgiu a necessidade de fazer uma nova feature em nosso sistema que parece ser bem simples mas como busco pelo SOLR a coisa ganhou bastante complexidade.Só para que entendam o problema, deixe me contextualizá-los.  Minha aplicação é uma ferramenta de seleção de pessoas – CASTING. Nela um administrador cria uma campanha e define um formulários com N perguntas que serão respondido pelo candidato. Ao finalizar o preenchimento, esse formulário vira um inscrições e salvamos suas respostas.  Surgiu então a necessidade de buscarmos por inscrições através de valores de respostas a perguntas específicas:  Quero buscar por todas as inscrições que responderam Vasco para a pergunta “Qual é o seu time do coração?”.

Muitos, se não considerarmos que estamos usando o SOLR e que vamos fazer essa pesquisa direto no banco de dados, vão dizer é a solução bem simples: Se resume a um query onde informo o campo e o valor de resposta desejado. Tendo isso busca pelas inscrições que tenha aquela resposta. Simples, não é? Nem tanto. O meu cliente deseja que isso esteja integrado aos demais filtros já existentes – idade, sexo, estado, status, etc.

Bem antes desse nova funcionalidade, a busca direto no banco, dado a quantidade de dados, já se mostrou inviável. Logo, sem chances de eu largar o SOLR e voltar para o banco ou tentar fazer algo híbrido.

Parte para tentar descobrir se existia algo dentro do universo do SOLR e/ou do Sunspot onde eu pudesse definir um campo do indice de forma dinâmica, ou seja, para cada instancia que for criando. Depois de um certo tempo gasto com o Oráculo (Google) , fiquei feliz que mais uma vez nem a gem nem o servidor me decepcionou.

O Sunspot tem um recurso que é o “dynamic field” que é o seguinte: todo o indice de sua classe é feito no build da classe, ou seja, no seu load.  Como precisava definir coisas que só existiriam no contexto da instância, eu precisa de algum recurso que me permitisse delegar a criação de alguns campos nesse momento de indexação (instancia). Esse recurso de “dynamic” é exatamente isso: ele  configura um bloco que será criado quando ele for indexar. Com isso eu pude buscar no SOLR por campos que só existem para algumas inscrições.

Em termos de código é mais ou menos o seguinte. Imagine que sua Inscricao tenha uma relação has_many com Resposta.

class Inscricao << ActiveRecord

has_many :repostas

end

A classe Resposta faz referencia a um campo de seu formulário. Logo a busca terá como nome do campo do indice o campo + id e seu valor será a resposta. Assim o mapeamento fica:

searchable do

dynamic :respostas do

respostas.inject({}) do |mapa, resposta|

mapa.merge({ resposta.campo.id.to_sym => resposta.valor})

end

end

end

 

Com isso acima, fica pronto a configuração. Para busca fica assim:

search do

dynamic :respostas do

with(:1, “teste”)

end

Assim estou buscando por Inscrições cujo a resposta a pergunta 1 foi teste. E pronto. A mágica foi feita.

Espero sinceramente que isso ajuda alguém como outros blogs que consultei me ajudaram. Fiquem em paz e até a próximo.

Published by Andre, on abril 8th, 2011 at 8:39 pm. Filled under: atualidades,codigo Tags: , , , 1 Comment