Uma das coisas que mais me incomoda quando estou fazendo os meus testes, é escrever testes para verificar os campos obrigatórios. Eu gosto muito de usar o RSpec e aqui está um exemplo comum de código que testa um modelo ‘Usuario’ que tem os atributos ‘nome’ e ‘idade’ obrigatórios:
describe Usuario do
before :all do
@obrigatorios = {nome: 'David Paniz', idade: 25}
end
it "deve ter Nome obrigatório" do
u = Usuario.new(@obrigatorios.merge(nome: nil))
u.should_not be_valid
u.should have_at_least(1).error_on(:nome)
end
it "deve ter Idade obrigatório" do
u = Usuario.new(@obrigatorios.merge(idade: nil))
u.should_not be_valid
u.should have_at_least(1).error_on(:idade)
end
it "Deve ser valido com todos os campos obrigatório" do
u = Usuario.new(@obrigatorios)
u.should be_valid
end
end
Sempre que escrevo um código desses sinto que estou testando o Rails e não o meu model. No fundo a única coisa que tenho que testar é se eu coloquei a linha do validates_presence_of :atributo. O resto do trabalho (deixar o valid? falso e criar o error no campo) é problema do Rails e não do meu modelo. Além desse sensação estranha de testar a coisa errada esse é o tipo de código que eu escrevo e na hora percebo que a abordagem não é nada DRY.
Dei uma olhada em 2 opções para melhorar a abordagem dos testes, o Shoulda e o Remarkable.
Remarkable
Para instalar o remarkable com o Rails 3 o RSpec 2 precisamos usar a versão 4 que ainda está em alpha, nesse instante 4.0.0.alpha4.
Adicione ao seu Gemfile as dependências:
gem "rspec" gem "rspec-rails" gem "remarkable_activerecord", '4.0.0.alpha4'
Usando o Remakable você ganha alguns matcher especiais para verificar apenas se você realmente colocou a validação do atributo no seu model, por exemplo o matcher validate_presence_of. O código de teste equivalente ao de cima ficaria assim:
describe Usuario do
it {should validate_presence_of :nome }
it {should validate_presence_of :idade }
end
Para que o RSpec reconheça esses matchers do Remakable é preciso um último detalhe de configuração que é adicionar um require do remarkable no seu spec_helper.rb logo abaixo do require ‘rspec/rails’
# This file is copied to spec/ when you run 'rails generate rspec:install'
ENV["RAILS_ENV"] ||= 'test'
require File.expand_path("../../config/environment", __FILE__)
require 'rspec/rails'
require 'remarkable/active_record'
Shoulda
O shoulda ficou muito famoso sendo utilizado com o TestUnit, mas existe um sub-projeto dele que é o ‘shoulda-matchers’, atualmente na versão 1.0.0.beta1, que é a gem que vamos usar com o Rails 3 o RSpec 2. Adicione ao seu Gemfile as dependências:
gem "rspec" gem "rspec-rails" gem "shoulda-matchers"
Curiosamente para esses casos mais básicos o matcher do Shoulda é idêntico ao do Remakable e o código de teste fica idêntico ao dele:
describe Usuario do
it {should validate_presence_of :nome }
it {should validate_presence_of :idade }
end
Dessa vez não é preciso nenhuma configuração extra, basta apenas executar os testes e: Seja uma pessoa mais feliz!
Conclusão
Ambas são ótimas opções para dar uma bombada nos seus testes, cada um com suas vantagens e desvantagens. Recomendo uma lida nas respectivas documentações para conhecer mais de cada um deles e escolher o que melhor supre suas necessidades.
Æ!!
Utilizei bastante o Remarkable, mas depois de migrar para o Rails 3 eu comecei a usar o Shoulda.
Tive vários problemas com algumas macros do Remarkable no Rails 3, portanto decidi migrar e o shoulda atendeu bem o que eu precisava.
Há blaços
Ótimo post Paniz.
Eu tenho usado RSpec2 com Shoulda em todos os projetos que participo, e tenho gostado bastante do resultado.
Parabéns novamente pelo post.
O Shoulda até um tempinho atrás deixava a suíte de testes beeeemm mais lenta.. acho que a razão era de 3x ou 4x mais. Confesso que não sei se continua assim, mas acredito que sim.
[]‘s