I have a naked rails 3 app with one model, generated using rails g model User.
I've added a factory (using factory_girl_rails):
Factory.define :user do |f|
f.email "test#test.com"
f.password "blah"
f.password_confirmation "blah"
f.display_name "neezer"
end
Then I've added one test:
require 'spec_helper'
describe User do
subject { Factory :user }
it "can be created from a factory" do
subject.should_not be_nil
subject.should be_kind_of User
end
end
Then I migrate my database using rake db:migrate.
Then I run the test using rspec spec, and the test fails with the following:
Failures:
1) User can be created from a factory
Failure/Error: subject { Factory :user }
ActiveRecord::StatementInvalid:
Could not find table 'users'
# ./spec/models/user_spec.rb:5:in `block (2 levels) in <top (required)>'
# ./spec/models/user_spec.rb:8:in `block (2 levels) in <top (required)>'
I'm confused, because I did just migrate my database, and my schema.db file reflects that there is a users table present, so what gives?
I know this is a beginner question, but banging my head against a wall isn't working...
factory_girl (1.3.3)
factory_girl_rails (1.0.1)
rails (3.0.5)
rspec-rails (2.5.0)
sqlite3 (1.3.3)
Try to execute
rake db:test:prepare
This should fix your tests db.
The point here is that rspec command doesn't execute migrations on your test database. and rake db:migrate only runs migrations in your current environment, probably development. Others environment like production and test ends without having those changes.
You can run
rake spec
That will prepare your testing db (drop and create using schema.rb) and run all tests.
As the other answer suggested, this:
rake db:test:prepare
Will also setup your testing db, but you have to run the rspec command after that, so, personally I prefer the first option.
try this out:
For rails version > 4.1+ this solution will work as the current scenario.
but in Rails 4.1+, rake db:test:prepare is deprecated.
try using
rake db:migrate RAILS_ENV=test (it will work for all version of rails)
Related
The following command is supposed to create a new database.
rails db:create
Where is this function defined? Or is this a pre-packaged function in rails?
It's in the databases.rake file of the framework:
namespace :create do
task all: :load_config do
ActiveRecord::Tasks::DatabaseTasks.create_all
end
ActiveRecord::Tasks::DatabaseTasks.for_each do |spec_name|
desc "Create #{spec_name} database for current environment"
task spec_name => :load_config do
db_config = ActiveRecord::DatabaseConfigurations.config_for_env_and_spec(Rails.env, spec_name)
ActiveRecord::Tasks::DatabaseTasks.create(db_config.config)
end
end
end
Whenever you doubt or want to know where a task has been defined, you can use the rails -W (or rake) command, passing the task:
$ rails -W db:create
rails db:create /path/databases.rake:26:in `block in <top (required)>'
rails db:create:all /path/databases.rake:20:in `block (2 levels) in <top (required)>'
Note it was introduced in the version 0.9 of Rake. This might or might not work depending on the versions which you're working with.
I have a controller spec something like this
describe :bizzaro_controller do
let(:credit_card_account) { FactoryGirl.build :credit_card_account }
it "doesn't blow up with just the stub" do
CreditCardAccount.stub(:new).and_return(credit_card_account)
end
it "doesn't blow up" do
credit_card_account
CreditCardAccount.stub(:new).and_return(credit_card_account)
end
end
Which results in this:
bizzaro_controller
doesn't blow up with just the stub (FAILED - 1)
doesn't blow up
Failures:
1) bizzaro_controller doesn't blow up
Failure/Error: let(:credit_card_account) { FactoryGirl.build :credit_card_account }
NoMethodError:
undefined method `exp_month=' for nil:NilClass
# ./spec/controllers/user/bizzareo_controller_spec.rb:5:in `block (2 levels) in <top (required)>'
# ./spec/controllers/user/bizzareo_controller_spec.rb:9:in `block (3 levels) in <top (required)>'
Finished in 0.23631 seconds
2 examples, 1 failure
My credit card factory looks like this:
FactoryGirl.define do
factory :credit_card_account do
exp_month 10
exp_year 2075
number '3'
end
end
My CreditCardAccount is an empty ActiveRecord::Base model
=> CreditCardAccount(id: integer, exp_month: integer, exp_year: integer, number: string)
Versions
0 HAL:0 work/complex_finance % bundle show rails rspec-rails factory_girl
/home/brundage/.rvm/gems/ruby-2.0.0-p247#complex_finance/gems/rails-4.0.0
/home/brundage/.rvm/gems/ruby-2.0.0-p247#complex_finance/gems/rspec-rails-2.14.0
/home/brundage/.rvm/gems/ruby-2.0.0-p247#complex_finance/gems/factory_girl-4.2.0
This should be working. all points that your test database is not correct.
RAILS_ENV=test rake db:drop db:create will drop and recreate your test database. Then try to run your rspec using the rake command, in order to migrate the database: rake rspec
I was having the same problem, but I think the cause of my problem was different. My solution, however, may perhaps be useful: I used the Fabrication gem (http://www.fabricationgem.org/) instead of FG.
The reason why I was having this problem was because I was trying to have FG create/build an object that was not ActiveRecord, it was only an ActiveModel, and it had to be initialized with arguments.
I didn't see in the Fabricator documentation an example totally like what I needed, but I got it with this syntax:
Fabricator(:my_class) do
on_init do
init_with("Company Name", "Fake second arg")
end
end
My problem was that in model I made a private method called :send (forgot that it is already used in Ruby).
I've been building my application and I'm now ready to start testing. I have Factory girl defined in seeds.rb but as I'm running tests I've also defined the tests in the usual place /spec/factories.rb for Rspec.
However my first tests fails with the following error.
user_spec.rb
require 'spec_helper'
describe User do
it "should have valid factory" do
FactoryGirl.build(:user1).should be_valid
end
end
Error returned:
Failures:
1) User should have valid factory
Failure/Error: FactoryGirl.build(:user1).should be_valid
NoMethodError:
undefined method `first_name=' for #<User:0x000000061410f8>
# ./spec/models/user_spec.rb:5:in `block (2 levels) in <top (required)>'
Finished in 0.05459 seconds
1 example, 1 failure
Failed examples:
rspec ./spec/models/user_spec.rb:4 # User should have valid factory
Randomized with seed 29084
spec/factories.rb
FactoryGirl.define do
factory :admin1, class: User do
first_name "admin"
last_name "minstrator"
password "admin1234"
profile_name "profilename"
email "admin#admin.com"
password_confirmation "admin1234"
admin true
end
factory :user1, class: User do
first_name "user2"
last_name "man2"
password "user1234"
profile_name "profilename"
email "user2#user.com"
password_confirmation "user1234"
admin false
end
end
It works fine when using the data on development in my seed.rb but now I've started testing using Rspec it has all gone wrong.
What am I doing incorrectly here. I'm not a huge fan of testing at the moment but I need to improve my skill set here as I know it can be extremely useful for web applications.
You help is greatly appreciated, please let me know if you need anymore info.
If your code works in development, but not in test, my guess is that your test copy of the database is not in sync. Try running rake db:test:prepare or rake db:test:clone and run your specs again.
Note:
db:test:clone isn't required in Rails 4.2.0 'WARNING: db:test:clone is deprecated. The Rails test helper now maintains your test schema automatically, see the release notes for details.')
I believe the issue here was that one of my migrations was missing and because it didn't have users first_name in the model there was nothing defined.
A big tip to all newbies, never ever ever delete any of your migrations.
As Homer Simpson quite rightly said "D'oh"
I am doing TDD/BDD in Ruby on Rails 3 with Rspec (2.11.0) and FactoryGirl (4.0.0). I have a factory for a Category model:
FactoryGirl.define "Category" do
factory :category do
name "Foo"
end
end
If I drop, create then migrate the database in the test enviroment I get this error:
rake aborted!
Could not find table 'categories'
This problem occurs because FactoryGirl expects the tables to already exist (for some odd reason). If I remove the spec folder from my rails app and do db:migrate, it works. Also if I mark factory-girl-rails from my Gemfile as :require => false it also works (then I have to comment that require in order to run rspec).
I found some information about this problem here: https://github.com/thoughtbot/factory_girl/issues/88
Is there something wrong that I'm doing? How can I "pass by" the FactoryGirl stage in the db:migration task?
I think you need to have factory girl definition like that in Gemfile:
gem 'factory_girl_rails', :require => false
And then you just require it in your spec_helper.rb like that:
require 'factory_girl_rails'
This is the way I'm always using this gem. You don't need to require it in other places than spec_helper.rb. Your current desired approach is just wrong.
A simple fix to this issue is to delay evaluation of any models in your factories by wrapping them in blocks. So, instead of this:
factory :cake do
name "Delicious Cake"
frosting Frosting.new(:flavor => 'chocolate')
filling Filling.new(:flavor => 'red velvet')
end
Do this (notice the curly braces):
factory :cake do
name "Delicious Cake in a box"
frosting { Frosting.new(:flavor => 'chocolate') }
filling { Filling.new(:flavor => 'red velvet') }
end
If you have a lot of factories this may not be feasible, but it is rather straightforward. See also here.
Information from: http://guides.rubyonrails.org/testing.html
When you do end up destroying your testing database (and it will happen, trust me),
you can rebuild it from scratch according to the specs defined in the development
database. You can do this by running rake db:test:prepare.
The rake db:migrate above runs any pending migrations on the development environment
and updates db/schema.rb. The rake db:test:load recreates the test database from the
current db/schema.rb. On subsequent attempts, it is a good idea to first run db:test:prepare, as it first checks for pending migrations and warns you appropriately.
rake db:test:clone Recreate the test database from the current environment’s database schema
rake db:test:clone_structure Recreate the test database from the development structure
rake db:test:load Recreate the test database from the current schema.rb
rake db:test:prepare Check for pending migrations and load the test schema
rake db:test:purge Empty the test database.
You shouldn't need to do any of that.. I think the issue is that your argument to FactoryGirl.define..
try this.
FactoryGirl.define do
factory :category do
name "Foo"
end
end
That should work fine, and does not screw up my migrations or load.. Today, I had to fix an issue where I was referencing a model constant from my factory directly and had to put it in a block to fix things.
FactoryGirl.define do
factory :category do
# this causes unknown table isseus
# state Category::Active
# this does not.
state { Category::Active }
end
end
I'm creating a new Rails 3.1 application using Cucumber, Devise, and Factory_Girl. I installed successfully Devise and Cucumber. I then created the spec/factories.rb file that contains the following:
require 'factory_girl'
Factory.define :user do |user|
user.name 'Test User'
user.email 'test#email.com'
user.password' testpass'
end
I also added spec/support/devise.rb to add in the test hooks for Devise:
RSpec.configure do |config|
config.include Devise::TestHelpers, :type => :controller
end
In regards to testing, I have not touched anything else and now everytime I run any rake command I get the following (I ran rake spec in this case, just to make sure everything is ready for tests):
rake aborted!
Factory already registered: user
Tasks: TOP => spec => db:test:prepare => db:abort_if_pending_migrations => environment
(See full trace by running task with --trace)
Now if I remove the Factory.define block from the factories file, it runs fine. I've done some Google searching and have come up with absolutely nothing. Since it's saying the Factory is already registered, is Devise for whatever reason, creating a factory already?