After learning about shoulda-matchers by answering another StackOverflow question on attribute accessibility tests (and thinking they were pretty awesome), I decided to try refa
Lower testing levels' requirements mostly come from within your organization (internal docs), customer mostly provides only the customer requirement spec (let's say this is the highest level in testing V-model). As your organization starts design the sw creates the lower test levels specs step by step.
For the "do we really need this" question: it depends on many things: the app complexity, safety critical or not, standards to follow, contractual/legal/industrial regulations, etc.
In generally I would say, for a correct ideal application reqirement responsible for unit testing should write the unit level spec and tester should implement test based on this spec.
For "have_many and respond_to" I am afraid I have no background info how they are implemented, so can not answer.
I think this whole thing should be seen from specification point of view.
If you have a component-testing-level specification which covers the necessary database columns for the given model, you should, otherwise not.
If not covered, but as a responsible developer you feel it important to have (your sw and its quality characteristics are better that way), you have to arrange to include this info in the spec, then you can put these tests in the test suite.
I've found some value in writing tests for the presence of database columns. Here's why:
1) Writing them keeps me in the rhythm of TDD.
2) Migrations are usually pretty awesome, until they aren't. I know you're not supposed to edit an existing migration, but when I'm just working on something myself I sometimes do it anyway. And if someone else is working on the same application and changes an existing migration instead of writing a new one, these tests have isolated the problem pretty quickly for me.
If you get bogged down with too many column names & types you can do something like this to save yourself typing:
describe User do
describe 'database' do
describe 'columns' do
%w[reset_password_sent_at remember_created_at current_sign_in_at
last_sign_in_at confirmed_at confirmation_sent_at
created_at updated_at
].each do |column|
it { should have_db_column(column.to_sym).of_type(:datetime) }
end
end
describe 'indexes' do
%w[confirmation_token email reset_password_token
].each do |index|
it { should have_db_index(index.to_sym).unique(true)}
end
end
end
end
Hope that helps.
1) The Shoulda::Matchers::ActiveRecord module has a lot more in it than just column and index matchers. I would dig around in the included classes a little and see what you can find. This is where the have_many
, belong_to
etc come from. For the record though, I see little value in most of what is in there.
2) Yes, macros such as have_many
test a lot more than whether or not a model responds to a method. From the source code, you can see exactly what it is testing:
def matches?(subject)
@subject = subject
association_exists? &&
macro_correct? &&
foreign_key_exists? &&
through_association_valid? &&
dependent_correct? &&
class_name_correct? &&
order_correct? &&
conditions_correct? &&
join_table_exists? &&
validate_correct?
end
3) Making the tests more readable and/or concise is definitely a subjective question to answer. Everyone will give you a different answer to this depending on their background and experience. I would personally get rid of all of the respond_to
tests and replace them with tests that have value. When someone looks at your tests, they should be able to understand the public API for that class. When I see that your objects respond_to something like "following?", I can make assumptions, but don't really know what it means. Does it take an argument? Does it return a boolean value? Is the object following something or is something following the object?
Your question touched on a few points, I would like to address two of them:
The answer is subjective, so I will give you my personal take.
1) Test ActiveRecord that way?
My answer is yes. You could write complex tests with real data but if you basically trust ActiveRecord you can do it this way and if you get to doing tdd, with these tests first they can help in that process.
2) Write the model tests at all?
My answer is yes. What I do is focus controller and request specs on the happy path and then for cases where validations and the like are needed I write unit model tests for them. This has turned out to be a good division of responsibility to me.