When building the following factory:
Factory.define :user do |f|
f.sequence(:name) { |n| "foo#{n}" }
f.resume_type_id { ResumeType.first.id }
end
ResumeType.first returns nil and I get an error.
ResumeType records are loaded via fixtures. I checked using the console and the entries are there, the table is not empty.
I've found a similar example in the factory_girl mailing list, and it's supposed to work.
What am I missing? Do I have to somehow tell factory_girl to set up the fixtures before running the tests?
This is what my test_helper looks like:
ENV["RAILS_ENV"] = "test"
require File.expand_path(File.dirname(__FILE__) + "/../config/environment")
require 'test_help'
class ActiveSupport::TestCase
self.use_transactional_fixtures = true
self.use_instantiated_fixtures = false
fixtures :all
end
My solution to this was to create a db/seeds.rb file which contained model code to generate my seed data:
# Create the user roles
Role.create(:name => "Master", :level => 99)
Role.create(:name => "Admin", :level => 80)
Role.create(:name => "Editor", :level => 40)
Role.create(:name => "Blogger", :level => 30)
Role.create(:name => "User", :level => 0)
And then include it in my spec_helper.rb:
ENV["RAILS_ENV"] = 'test'
require File.expand_path(File.join(File.dirname(__FILE__),'..','config','environment'))
require 'spec/autorun'
require 'spec/rails'
require "#{Rails.root}/db/seeds.rb"
(To be fair, I haven't managed to get autospec to play nice with this yet as it keeps duplicating my seed data, but I haven't tried all that hard either.)
This also has the benefit of being Rails 3 ready and working with the rake db:seed task.
Another option is to add seed.rb in your test or spec directory and require it in your helper file before your factories:
require File.expand_path(File.dirname(__FILE__) + "/seed")
require File.expand_path(File.dirname(__FILE__) + "/factories")
Rails 2.3
Related
I have some data, which I want to pre-load in my add on booting. I've made an rake task and it works good. I tried to put code in config/initializers but it starts too early (I need all models to be loaded). after_initialize is not good too for me. I place code example lower
require 'rake'
load File.join(Rails.root, 'lib', 'tasks', 'rights.rake')
Rake::Task['dev:create_rights'].invoke
So, where is good place to put this code? Of course I can put it in AR::Base or so on, but it is ugly.
Here is the task, if It will help.
namespace :dev do
desc "Creation of the minimal rights"
task :create_rights => :environment do
klasses = ActiveSupport::DescendantsTracker.descendants(AbstractModel)
default_rights = RightsList.default_rights
Role.includes(:rights).all.each do |role|
klasses.reject{|klass| role.rights.pluck(:klass_name).include? klass.underscore }.each do |klass|
Right.create role: role, klass_name: klass.underscore, rights_per_class: default_rights
end
end
end
end
Thank you
UPDATE
Got dirty solution with adding in config/application.rb
config.after_initialize do
require 'rake'
load File.join(Rails.root, 'lib', 'tasks', 'rights.rake')
Rails.application.eager_load!
Rake::Task['dev:create_rights'].invoke
end
And I understand that it is still wrong way. Is here good way?
[Aside: I am slowly answering my own question in "a concise recipe for installing, configuring and running minitest under autotest or Guard"]
My environment: Ruby 2.0. Padrino 0.10.7. Minitest 2.6.2. RackTest 0.6.2.
Short form: What is the best way to extend $LOAD_PATH to include my test directory so I can simply require 'test_helper' in my test files?
Long form:
Here's a sample test file. Note the require_relative "../../../test_helper" -- this requires keeping track of the test file relative to the test_helper.
# file: test/models/api/v0/index_test.rb
require_relative '../../../test_helper'
describe 'nobody home' do
it 'fetch fails' do
get "/api/v0/a_uri_that_does_not_exist"
last_response.status.must_equal 404
end
end
Here's the test helper:
# file: test/test_helper.rb
PADRINO_ENV = 'test' unless defined?(PADRINO_ENV)
require File.expand_path('../../config/boot', __FILE__)
class MiniTest::Unit::TestCase
include Rack::Test::Methods
def app
Demo.tap { |app| }
end
end
And finally, the rakefile that drives it (generated by padrino, invoked via padrino rake test):
# file: test/test.rake
require 'rake/testtask'
test_tasks = Dir['test/*/'].map { |d| File.basename(d) }
$stderr.puts("=== test_tasks = #{test_tasks}")
test_tasks.each do |folder|
Rake::TestTask.new("test:#{folder}") do |test|
test.pattern = "test/#{folder}/**/*_test.rb"
test.verbose = true
end
end
desc "Run application test suite"
task 'test' => test_tasks.map { |f| "test:#{f}" }
So: what would it take to replace the brittle require_relative '../../../test_helper' with a dependable and easily remembered require 'test_helper'?
you need to add libs:
Rake::TestTask.new("test:#{folder}") do |test|
test.pattern = "test/#{folder}/**/*_test.rb"
test.verbose = true
test.libs << 'test' # <-- this
end
Or if you invoke directly it with ruby:
$ ruby -Itest test/test_file.rb
I am using Ruby on Rails 3.2.2, cucumber-rails-1.3.0, rspec-rails-2.8.1 and capybara-1.1.2 with the Selenium driver. After receiving the answer to a my previous question I had a doubt: should I use the Selenium ruby-gem or the Jasmine ruby-gem in order to test view files with RSpec? If so, since I am already using Selenium in order to test JavaScript for view files with Cucumber, why (when testing with RSpec) should I use Jasmine instead of Selenium? That is, why to use two ruby-gems that have the same purpose and make the same things?
Generally and practically speaking, how do you advice to test view files by using RSpec? ... but, is it the "right way" to test view files with RSpec or should I test those by using Cucumber?
I prefer to use selenium server, the selenium IDE in firefox to record and selenium client for rspec.
selenium_helper.rb
ENV["RAILS_ENV"] ||= 'test'
require File.expand_path(File.join(File.dirname(__FILE__),'../..','config','environment'))
require 'spec/autorun'
require 'spec/rails'
require 'factory_girl'
require 'rspec/instafail'
require "selenium/client"
Spec::Runner.configure do |config|
end
rspec_tester_file_spec.rb
require "selenium/selenium_helper"
require "selenium/modules/loginator"
describe "tester" do
attr_reader :selenium_driver
alias :page :selenium_driver
before(:all) do
#verification_errors = []
#selenium_driver = Selenium::Client::Driver.new \
:host => "localhost",
:port => 4444,
:browser => "*firefox",
:url => "http://localhost:3000",
:timeout_in_second => 60
end
before(:each) do
#selenium_driver.start_new_browser_session
end
append_after(:each) do
#selenium_driver.close_current_browser_session
end
it "login and then try to search for stuff" do
#login.run_login(page)
page.click "link=CSR"
page.wait_for_page_to_load "30000"
page.type "id=isq_Name", "john smith"
page.click "css=input[type=\"submit\"]"
page.wait_for_page_to_load "30000"
page.is_text_present("Update")
page.is_text_present("Date")
page.is_text_present("PIN")
page.is_text_present("Name")
end
I'm trying to use Factory Girl in a rake task like this:
require 'factory_girl'
require File.expand_path("spec/factories.rb")
namespace :users do
desc "Create sample users for use in development"
task :create_sample_users => :environment do
Factory(:user, :email => "pending#acme.com")
Factory(:approved_user, :email => "user#acme.com")
end
end
However when I run rake users:create_sample_users I get the error uninitialized constant Entry (Entry is the name of one of my app's classes).
Can anyone tell me how to get Factory girl to see my classes? It's working fine in my tests, just failing in my rake tasks.
I'm guessing that Rails hasn't loaded your models at the point you are requiring the factories. Try this:
require 'factory_girl'
namespace :users do
desc "Create sample users for use in development"
task :create_sample_users => :environment do
require File.expand_path("spec/factories.rb")
Factory(:user, :email => "pending#acme.com")
Factory(:approved_user, :email => "user#acme.com")
end
end
For factory_bot which has replaced factory_girl use:
require 'factory_bot'
namespace :users do
desc "Create sample users for use in development"
task :create_sample_users => :environment do
include FactoryBot::Syntax::Methods
create(:user, :email => "pending#acme.com")
end
end
#dmcnally's answer didn't work for me, as I was getting odd errors of constants not found. Instead, I resolved it by shelling out to rails runner:
sh "rails runner 'FactoryGirl.create :user'"
I have some seed data (for price ranges) that is the same in prod, dev, test and doesn't change. I need that data in my test db to run my cuke tests.
I am load my seed data into test DB before the scenario loads, but it's failing.
I have the following in my features/support/env.rb file
# from http://www.andhapp.com/blog/2009/11/07/using-factory_girl-with-cucumber/
Before do
require 'factory_girl_rails'
# Dir.glob(File.join(File.dirname(__FILE__), '../../spec/factories/*.rb')).each {|f| require f }
Dir.glob(File.join(File.dirname(__FILE__), '../../db/seeds.rb')).each {|f| require f }
end
Which loads the following file:
# wipe out all previous data
Price.delete_all #is there a factory way of doing this?
# set defaults
Factory.define :price do |price|
price.id 1
price.price_range "$100"
end
# insert seed data
#price = Factory(:price, :id => 1, :price_range => "$100 - $500")
#price = Factory(:price, :id => 2, :price_range => "$500 - $1,000")
#price = Factory(:price, :id => 3, :price_range => "$1,000 - $1,000")
#price = Factory(:price, :id => 4, :price_range => "$10,000 - $100,000")
I get the following error message:
Factory already defined: price (Factory::DuplicateDefinitionError)
/Library/Ruby/Gems/1.8/gems/factory_girl-1.3.3/lib/factory_girl/factory.rb:61:in `define'
/Applications/MAMP/htdocs/rails_testing/feedbackd/features/support/../../db/seeds.rb:16
/Library/Ruby/Gems/1.8/gems/activesupport-3.0.3/lib/active_support/dependencies.rb:239:in `require'
/Library/Ruby/Gems/1.8/gems/activesupport-3.0.3/lib/active_support/dependencies.rb:239:in `require'
/Library/Ruby/Gems/1.8/gems/activesupport-3.0.3/lib/active_support/dependencies.rb:227:in `load_dependency'
/Library/Ruby/Gems/1.8/gems/activesupport-3.0.3/lib/active_support/dependencies.rb:239:in `require'
/Applications/MAMP/htdocs/rails_testing/feedbackd/features/support/env.rb:92
/Applications/MAMP/htdocs/rails_testing/feedbackd/features/support/env.rb:92:in `each'
/Applications/MAMP/htdocs/rails_testing/feedbackd/features/support/env.rb:92:in `Before'
Any thoughts?
You can only call Factory.define :price once, and I would probably not put it in the file that it's in right now. Do you have a factories folder? It usually lives in spec/factories. In there I would create the file price.rb, and define your factory once, there. factory_girl should automatically load all of those definitions up for you once.
If you're using Rails3 and you have factory_girl_rails in your Gemfile, then you don't even need that require 'factory_girl_rails', it does it for you.
Also if you have a new-ish version of cucumber the installer should automatically have added this section for you in env.rb:
if defined?(ActiveRecord::Base)
begin
require 'database_cleaner'
DatabaseCleaner.strategy = :truncation
rescue LoadError => ignore_if_database_cleaner_not_present
end
end
DatabaseCleaner is a good way to do the truncation instead of using your Price.delete_all
The last thing is seeds.rb - It's a good concept and something very similar to what we do in one of our apps at work.
But keep in mind, everything in the features/support directory is automatically required by cucumber, so you don't need to have that Dir.glob nonsense.
With factory_girl we don't use the default rails seeds file because it's not really applicable (in our opinion).
I would just add a file named anything (ours is named db_setup.rb) that looks something like this:
Before do
# Truncates the DB before each Scenario,
# make sure you've added database_cleaner to your Gemfile.
DatabaseCleaner.clean
Factory(:price, :attr1 => 'blah'...)
# More factories here etc
end
Take a look at hooks:
https://github.com/aslakhellesoy/cucumber/wiki/Hooks
You can use tagged hooks to only load up specific seed data, much like you would only execute specific tags in cucumber.
You can also employ the heavy handed rails way and do a rake db:test:clone.