user1185081
user1185081

Reputation: 2118

Understanding RSPEC Users tests in Ruby on Rails Tutorial

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

Answers (1)

PinnyM
PinnyM

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

Related Questions