Testando relacionamentos no Rails
Estive procurando por uma maneira elegante de testar relacionamentos utilizando Rails, e achei interessante como pouca gente está preocupada com isso. Na maioria das vezes, dizem simplesmente que isto é função do próprio framework. Tudo bem, o has_many e belongs_to (esqueça que existe o HBTM) já foram devidamente testados, mas é importante saber que o que cabe a você testar o que você escreve no seu código. Portanto, se você quer ter certeza que a linha has_many :comments realmente existe, você deve escrever um teste para ela. Então, resolvi listar algumas abordagens:
1 – Utilizando fixtures:
No começo, pensei em utilizar as fixtures, mas usando relacionamentos dentro delas. É uma solução simples, porém traz um revés. Quando utilizamos um relacionamento dentro das fixtures, e este relacionamento não está explicitado nos models, será retornado um erro, ao invés de uma falha. Por exemplo:
# post.rb class Post < ActiveRecord::Base end# comment.rb class Comment < ActiveRecord::Base end # posts.yml testing_relationships: title: Hello World body: Hello... # comments.yml commenting_relationships: body: I disagree! author: Filipe Coimbra post: testing_relationships
Como não foi explicitamente dito que Comment belongs_to :post, ao se executar a fixture comments.yml será retornado um erro. Além disso, o relacionamento contrário, Post has_many :comments não será testado.
2 – Novamente utilizando fixtures:
Depois, encontrei este artigo, que também utiliza fixtures com uma abordagem diferente (e mais Rails 1.x) que é definir apenas a chave estrangeira na fixture. Assim, não seria retornado erro.
É funcional, mas eu quero apenas testar se as linhas de relacionamento estão definidas nos models. O resto, fica por conta do ActiveRecord. Além disso, não quero usar fixtures como se fossem testes, já que, primeiro, não são documentadas automaticamente (como no caso dos métodos de teste) e porque, caso você mude a estrutura da sua tabela, poderá ter seus testes quebrados por causa das fixtures que não refletem as mudanças.
3 – A opção errada que funciona:
Acabei utilizando a solução mais lógica, e baseada neste post do Err The Blog.
# post_spec.rb describe Post do before(:each) do @post = Post.new end it "should be related to comments" do comment = Comment.new(:body => "Testing relationships") @post.comments << comment @post.comments.should include(comment) end end # comment_spec.rb describe Comment do before(:each) do @comment = Comment.new end it "should be related to a post" post = Post.new @comment.post = post @comment.should equal(post) @comment.post.should equal(post) end end
É simples, mas… por que é errada? Quando fazemos “@post.comments << comment”, estamos chamando o método comments do objeto @post. Como não foi declarado que Post has_many :comments, este método não existirá. Ela funciona porque o rSpec não acusará o erro, e apenas retornará uma falha no teste.
Ainda assim, prefiro essa solução porque eu não precisarei lidar com fixtures.
March 18, 2008 at 10:46 am
[...] Testing relationships in Rails Ler este artigo em português [...]