RSpec test if all models respond_to attribute
I'm trying to write an RSpec test for what seems like a relatively simple test, but it's proving pretty tricky (though I am new to RSpec).
In simple terms, I want to test that all models in my application respond_to :owner or :owners.
My first problem is looping through all of the models - how to do this in RSpec? I can normally loop through the models like:
ActiveRecord::Base.descendants.each { |model|
model.should respond_to :owner
}
But not sure how to do this correctly in RSpec? I can't find much documentation about using loops within tests.
My second question is about an "OR" clause - how can I achieve "responds to owner or owners"? Something like:
model.should respond_to :owner || :owners
But again I can't find much documentation about using or clauses.
You can accomplish the OR condition by testing each method and rolling up the answer:
ActiveRecord::Base.descendants.each do |model|
instance = model.new
expected = instance.respond_to?(:owner) || instance.respond_to?(:owners)
expected.should be_true
end
But this smells wrong to me. If the model is going to respond to only one of :owner
and :owners
, you should test that it responds to the correct one. Even if this means creating a spec for each model (which you should have in any case) and adding a new example, you're better off in the long run by being specific. It also helps future maintainers of your code, who would expect a model spec to be in the spec file for the model itself, not in a catch-all spec.
In this case the example is quite small—for longer ones you might consider using a shared example to DRY things up a bit.
When your running Rspec tests you are still using Ruby. So your loop should work, as long as you are in an it
block. Your only problem is you have a model object not an instance of the object, so you need to create one. so one solution would be:
it "every model should respond to owners" do
ActiveRecord::Base.descendants.each { |model|
model.new.should respond_to :owner
}
end
I am not sure about the or clause.