9
votes

My trouble arose in Chapter 11 of the Ruby on Rails Tutorial here.

I was seeing this rspec error:

Failure/Error: :user => Factory(:user, :email => Factory.next(:email)))
     ActiveRecord::RecordInvalid:
       Validation failed: Email has already been taken

first in user_spec.rb then in micropost_spec.rb. It was pretty puzzling. I thought the factory statements were generating a user in a fresh testing db each time autotest ran rspec. I checked out source files from the master branch with git and tried again, but saw the same error. I therefore suspected it related to the db contents somehow and not the code.

So, I did the following:

restarted "rails s"  
restarted autotest  
rake db:reset  
rake db:migrate  
rake db:test:prepare  
rake db:populate  

... and it all went green. The rspec tests passed.

There may be a more “to the point” solution, but I was thrilled this worked. Hope it helps someone else. I am left to conclude that my testing/development somehow added something to the db that was unexpected. I suppose the above steps are a good way to make yourself a fresh db near the end of chapter 11.

Was there a more direct way to solve this? Does the error indicate some other issue that I addressed without realizing it? I am left thinking that running rspec does not guarantee a fresh testing db each time. Is that a wrong assumption?

5
There wasn't any question here... This is a question => answer site. It's perfectly acceptable to ask a question and then answer it yourself, but the way you've gone about it is not correct :(nzifnab
nzifnab you are correct. My post is mostly a statement that, nevertheless, I hoped would be useful to some. I did close with a genuine query, "If someone else could shed some light here, I guess that would be nice too." My 'solution' was something of a shotgun approach. I'm still not sure what was wrong, but the recipe above might be a handy fix for those who are comfortable living in the dark.Perry Horwich
I see your point. I could have posted this as "I have puzzling rspec errors in Chapter 11...." And then also posted my own answer with commentary. Sorry. Next time. If it hadn't been 4:00 a.m. local time, I might have thought of that first go-around. P.Perry Horwich

5 Answers

12
votes

I had trouble with the Integration tests shortly after Chapter 9.4. All of my controller tests and the request integration test blew up with the message 'Email has already been taken'

What I learned from RailsTutorial - chapter 8.4.3 - Test database not clearing after adding user in integration test is that you need to do something to clean up after integration tests, because unlike unit tests they may not clean up after themselves.

The solution presented there was to use the DatabaseCleaner gem, the implementation of which is also explained in the linked Question.

I think that if you don't implement some strategy for cleaning up after the integration test you will continue to have to use your 'shotgun' solution for cleaning up the DB every time you run the test suite. Definitely not fun.

4
votes

This works for me:

bundle exec rake db:test:prepare

It's also in the tutorial.

2
votes

For me, the issue seemed to be running Spork. After restarting it I can run the tests as many times as I need.

1
votes

It helped, added to the file factories

sequence(:email) {|n| "person#{n}@example.com" }
-1
votes

In my case problem was in equals emails in

factory :user

and

factory :user_with_additional_options