Reputation: 2118
I'm currently developing a RoR 4 application.
In my application, I'm trying to implement Users tests similar to Mickael Hartl's tutorial. I'd like to understand a few things about the eMail uniqueness test :
1 - Uniqueness is tested when actually writing to the database, right ?
When writing my test the same way as in the tutorial, it is not efficient. The @user = User.new(...) actually instantiates the user in memory only. The following test:
describe "when email address is already used" do
before do
user_with_same_email = @user.dup
user_with_same_email.save
end
it { should_not be_valid }
end
works only, in my case, when the @user = user.new(...) instruction is followed by a user.save instruction. Am I right ?
Additional note: when email uniqueness is implemented in the user model, it always fails !?! Can you tell me what is wrong with this test ?
VALID_EMAIL_REGEX = /\A[\w+\-.]+@[a-z\d\-.]+\.[a-z]+\z/i
validates :email, presence: true, uniqueness: true, length: { maximum: 100 }, format: { with: VALID_EMAIL_REGEX }
2 - Does RSPEC really write to the TEST database ?
After running the above test (user.new(...) - user.save - user.dup - user.save), I check the 'modified date' of the TEST SQLite3 database file. It has not been touched when running the test. The spec_hepler.rb files starts with:
ENV["RAILS_ENV"] ||= 'test'
Did I miss something ?
Thank you for your help,
Best regards,
Fred
Upvotes: 0
Views: 177
Reputation: 35533
About your first point, the validation for uniqueness indeed occurs when you call save
. However, you can also invoke all the validations by calling valid?
- which is what be_valid
does. So it doesn't actually need to save the @user
model for this test to work.
About your second point, RSpec absolutely writes to the database. However, it runs each test within a transaction scope (by default). At the end of each test, instead of committing the transaction, it rolls it back. This leaves the database in the same state it was before the test started, effectively allowing each test to be isolated from the others while making use of the database just as your code would do in production (almost). Regarding your point about the file modification time, SQLite doesn't necessarily write out the data to the file as you make calls until they are actually committed.
Upvotes: 1