I am using Cucumber, RSpec, and Factory Girl for the testing of my Rails application. But I have several lookup tables that contain mostly static data. So I'm trying to figure out the best way to populate these when testing. Doing them individually in FactoryGirl seems tedious and I'd like to stay away from fixtures. For development and production, I populate them in my seeds.rb file.
Thanks!
Use Factory Girl .sequence, Populator and Faker and you'll never run out of lab rats!
Factory.define(:model) do |m|
m.sequence(:title) { |n| "model-#{n}" }
m.author Faker::Name.name
m.short Populator.words(5)
m.long Populator.paragraphs(1..3)
end
Then maybe in a before :each block
#models = []
15.times { #models << Factory.create(:model) }
Or you can use only Populator to fill your database before tests.
Maybe something like
rake RAILS_ENV=test db:seed
in your test helper file?
Related
We could not run rake db:schema:load on a new machine because somewhere when loading the Rails environment for the rake task a class method was being called that tried to access a table in the db, which obviously did not yet exist.
I found that it was coming from a FactoryGirl definition.
For 2 of the factories we were setting a location_id variable to the world location.id like this
FactoryGirl.define do
factory :some_model do
....
....
cached_location_id Location.world.id
....
end
end
so when rails was loading all our code, it was immediately running the Location.world. I think this is peculiar to FactoryGirl.
How to solve this?
So just change it to only run the Location.world code when the Factory is asked to create the model using { }s like this:
FactoryGirl.define do
factory :some_model do
....
....
cached_location_id {Location.world.id }
....
end
end
What a Gotchya!
I'm practicing testing (just got into it), and am wondering whether it's better to use shoulda-matchers or Factory Girl - or a combination of both - in testing models. For example, I currently just use the simple shoulda-matchers test, which is nice and straightforward:
RSpec.describe User, :type => :model do
describe User do
it { should validate_presence_of(:username) }
it { should validate_presence_of(:password_decoded) }
it { should validate_length_of(:password).is_at_least(3) }
it { should validate_presence_of(:session_token) }
it { should have_one(:shopping_cart)}
end
end
But, from my understanding, this doesn't actually instantiate a User object like Factory Girl would. Is the above "sufficient" for testing? Any thoughts appreciated!
factory_girl and shoulda-matchers do two different things. Most Rails applications need both of those things. It's not either-or. The fact that the same people (Thoughtbot) are behind both gems is a good clue that they're both useful at the same time.
factory_girl allows you to create (only in memory or in the database) objects to use in your tests. Most applications need to create similar objects over and over again in their tests; factory_girl removes the duplication in doing that. It also allows you to customize a predefined object easily (more easily than a Rails fixture, for example). The model spec you showed doesn't need factory_girl, but if you have any code in your models more complicated than basic configuration it will probably be helpful to use factory_girl to create models to test.
shoulda-matchers makes it easier to assert that you got the results you expected in your tests. It provides RSpec matchers for asserting things about models and controllers. Most applications will find shoulda-matchers' ActiveModel matchers useful in ensuring that their models are well validated. (Personally I get more use out of shoulda-matchers' ActiveModel matchers than the ActiveRecord matchers.)
For basic associations and validations, I think shoulda matchers are fine. I use Factories to test other methods and more complex validations. Here's a simple example for a method that returns a value based on an instance's attributes. I've also shown how to use sequence to always generate a unique email address which can often trip you up in tests.
class User
def fullname
"#{firstname} #{surname}"
end
end
factories/users.rb
FactoryGirl.define do
sequence(:username) { |n| "user-#{n}" }
factory :user do
email { |_u| "#{FactoryGirl.generate(:username)}#example.com" }
password 'password'
password_confirmation 'password'
firstname 'John'
surname 'Smith'
end
end
user_spec.rb
RSpec.describe User do
describe "#fullname" do
it "returns the first and surnames separated by a space" do
user = FactoryGirl.create(:user)
expect(user.fullname).to eq "John Smith"
end
end
end
If you are going to have small models and tests you may create your example data using seeds but if you are going to add feature tests as well then I would suggest to use FactoryGirl.
I believe shoulda-matchers is a must for all tests.
Im trying to implement a database-based sequence generator in rails so i wrote a code that goes something like
#semaphore.synchronize {
seq = Sequence.find_by_name(type)
seq.value += 1
seq.save
val = seq.value
unless prefix.nil?
"#{prefix}-#{val}"
else
"#{val}"
end
}
My question is, is it possible to setup the initial sequence data using factory girl and be able to access it using Sequence.find_by_name or fixture loading is my only option? i.e. rake db:fixtures:load RAILS_ENV=test FIXTURES_PATH=spec/fixtures?
Thanks
Ok, i was able to find the answer.
I created my Sequence definition in factory girl as below:
FactoryGirl.define do
factory :membership_sequence, class: Sequence do
name 'membership'
value 1
end
factory :payment_sequence, class: Sequence do
name 'payment'
value 1
end
end
Then, in the before(:all) I called the create() method
before(:all) do
# create the sequences
create(:membership_sequence)
create(:payment_sequence)
end
and voila! the Sequence.find_by_name shall work now.
To answer your question why i choose to implement sequence generation manually than using rails active record autogenerated ids, it's because i want to be able to generate sequences such as PREFIX-2015-0001, PREFIX-2016-0001
On the Rails console my Class User looks like this:
irb(main):005:0> User
=> User(id: integer, name: string, created_at: datetime, updated_at: datetime)
I can generate an instance of User using
irb(main):006:0> User.create(:name => "user0")
What I want to do is test my database by creating a number X of instances of User. I thought about writing a Ruby script in which I cycle through a loop - something like (not real Ruby code!)
for i in 1..X do
User.create(:name => "name"+i)
end
But I don't know how to access my Class in Ruby and how to "tell" the console to generate actual objects.
Thanks for an answer!
You have a few options here. The best option is to learn how to write unit tests, either using Rails's default Test::Unit, or RSpec, or some other alternative. This is the right way, and in fact Rails comes all wired up with tests by default. You've got a test directory, and rake test and other testing tasks. If you use Rails generators (rails g model Foo), it'll even create the test files for you. You just need to fill them out.
If you're not ready to learn the testing frameworks, then you can put your code above into a file (let's call it test_user.rb) and run it through rails runner. That will bootstrap the Rails environment before executing your code, and you'll have access to the model:
rails runner test_user.rb
It seems like you're trying to create some seed data for your database. Why not run your code in Rails console directly? Or you could create a Rake task, and run the seeding from there.
I would also recommend using Faker, this will give you some real-looking data:
require 'faker'
for i in 1..X do
u = User.new
u.first_name = Faker::Name.first_name
u.last_name = Faker::Name.last_name
u.email = Faker::Internet.email
u.notes = Faker::Lorem.paragraph
u.cell_phone = Faker::PhoneNumber.cell_phone
u.home_phone = Faker::PhoneNumber.phone_number
u.save
end
I need to fill the test development database with data, for example from factorygirl, but I'd like to use it from rails console.
How I put example data in db so I can fetch it from console and do some test there?
Faker is also a good solution.
Here's how my lib/tasks/sample_data.rake looks like. I run it with rake db:populate.
Creates 50 entries with random info.
require 'faker'
namespace :db do
desc "Fill database with sample data"
task :populate => :environment do
Rake::Task['db:reset'].invoke
50.times do |n|
name = Faker::Company.name
year = 1900+rand(111)
rating = 1+rand(10)
watched = (1 == rand(2) ? true : false)
imdb_id = rand(1000000)
Movie.create!(:name => name,
:year => year,
:rating => rating,
:watched => watched,
:imdb_id => imdb_id)
end
end
end
I've made a gem test_dummy that works like Factory Girl to define lots of fake data. When properly configured you can do things like this:
# Create 100 fake companies
100.times { Company.create_dummy }
# Create a single fake company on-demand
fake_company = Company.create_dummy
The alternative is to use the db/seeds.rb facility or to load in your fixtures into your development environment.
Michael Hartl provides an excellent introduction to this topic as part of the railstutorial.org program.
He uses a gem called Factory Girl, which is designed to ease the process of populating a database with sample data.
E.G.
http://ruby.railstutorial.org/chapters/user-microposts#sec:sample_microposts
https://github.com/railstutorial/sample_app/blob/master/lib/tasks/sample_data.rake
Is it just in the Rails console or just 'from the console'?
I like to use a Thor or Rake task to do that. Instead of Factory Girl I use Machinist.
You may want to check this answer
Rails: Good Rspec2 example usage? (Also: Cucumber, Pickle, Capybara)