can we load seed data when start cucumber?
Please support me a way.
You could use Factory Girl to in your cucumber tests to setup your 'stuff'
Background:
A car exists
Scenario: I drive a car
Given I am in a car
And I have keys in the ignition
When I turn the keys
...
Then you'll create the car in your step definitions, with something like
#car = Factory.create(:car)
I prefer this approach:
https://github.com/cucumber/cucumber/wiki/fixtures
I'm not opening the fixtures vs factories debate, of course, just saying that I've yet to see a case where files of data (seed, or otherwise) cease to be useful.
Once yaml fixtures are defined, they can be instantiated procedurally via Fixtures.create_fixtures per above, or set up as rake tasks.
They're just plain files, not code intended to have side effects - I have more confidence letting non-technical people add their data to fixtures files (esp. CSV).
Related
I want to test my Ruby-on-Rails website that uses PostgreSQL database with Cucumber.
I also have the FactoryGirl gem installed, so I can create factories.
I understand that the typical way to create data for the test database would be to write Gherkin tables and put them in the background block of a cucumber file. But I already have a Ruby script that creates samle data suitable for the test database.
Yet, I am currently lost in Cucumber’s settings. Could you please advise how to make Cucumber run my Ruby script populating the test database before each test and how to clean the test database after each test. Apparently, my google-fu is inadequate for this task.
Just:
add the cucumber rule like I have 4 clock in the pocket to features/clock.feature (for example).
implement the rule in the features/step_definition/clock_steps.rb (for example) to create defined amount Clock models, and single Pocket model. and associate them:
When /I have (\d+) clock in the pocket/ do |amount|
pocket = FactoryGirl.create :pocket
amount.times { FactoryGirl.create :clock, pocket: pocket }
end
So, you then will get some data populated.
If you want predefine the step for most scenarios you can either:
Create a larger step (for example) called I have basic clock setup, then define it as an above one, but add another required steps into it.
or
Use step recursion (this is non-recommended way) as follows:
When /I have basic clock setup/ do |amount|
step 'I have 4 clock in the pocket'
end
I ended up using a Before do block in the .rb file with Cucumber tests:
Before do
<code to populate the test database here>
end
Given /first condition/
do some stuff
end
...and so on
So far I use rspec and factories only, not fixtures or seed data. But now I need a (static) Coupon table with a dozen or so records of config data to be available to my app when running my integration tests (rspec + capybara, not cuke).
My rspec tests have a FactoryGirl factory that creates a Store.
In my app, when a Store is initialized by init_store(coupon_code), a coupon code is passed in that turns on/off various features (by looking up the settings for that coupon in Coupon table).
So, when I create a Store factory, I also need to specify (via trait?) a coupon code. Then, down in my model, the method that initializes a store will use the coupon code to lookup a bunch of settings in the Coupon table. (Each coupon has about 20 attributes that turn on/off various Store features.)
My coupons.yml file contains the actual coupon table data used by my app. Now I need to make them available to the app when tests are being run. (Don't care about 'brittle', this table doesn't change.)
Having not used fixtures OR seed data with rspec, I'm not sure how/where to put my coupons.yml file and how to make the coupons 'load' into the test Coupon table so they are available to my app while tests are running.
Do I pre-populate seed data with coupons.yml? If so, how can I have that get loaded into my test database each time my tests run?
Or, should I use fixtures?
Either way, where should coupons.yml go and how do I load it (in the Store factories? in one of the specs? In specs_helper?)
When I search for stuff like "using fixtures and factories" or "using seed data with rspec" all I find is the advice "use factories" and yeah, I get that. But for this particular situation I need both, so any help would be appreciated.
I do something like this, and I use seeds rather than fixtures (though I'm sure you could use fixtures too).
In spec_helper.rb
RSpec.configure do |config|
...
config.before :suite do
DatabaseCleaner.strategy = :truncation, {:except => %w[table1 table2]}
DatabaseCleaner.clean_with :truncation
Rails.application.load_seed
end
...
end
So the DatabaseCleaner.strategy line is telling database_cleaner to clean everything except the array of tables you pass it.
After setting the strategy, you simply call Rails.application.load_seed to load the seed data.
Hope that helps, let me know if you have any questions.
I'd like to be able to use Rails' test fixture helpers in Cucumber, but the information provided on the Cucumber wiki seems... out of date at best: https://github.com/cucumber/cucumber/wiki/Fixtures (heading: Fixture Helper Methods)
Google has been less than helpful.
Is there a good way to do this?
Update: Tried using ActiveRecord::TestFixtures to no avail it seems like this is the class to do the job, but can't get it mixed into the World correctly
One of the reasons there's so little information on fixtures is that most rails developers are now all using Factory Girl to generate test data.
Factory Girl provides you mush more control over both the data that's generated (and when it's created), but it also allows you a lot more control of the associated model classes you inevitably will need.
After an hour of brain cramming, I was able to make it work.
Replace
fix = Fixtures.cached_fixtures(ActiveRecord::Base.connection, table_name)[fixture_symbol.to_s]
with
fix = Fixtures.cached_fixtures(ActiveRecord::Base.connection, table_name).first.fixtures[fixture_symbol.to_s]
I have already updated the wiki at https://github.com/cucumber/cucumber/wiki/Fixtures
I need to populate my production database app with data in particular tables. This is before anyone ever even touches the application. This data would also be required in development mode as it's required for testing against. Fixtures are normally the way to go for testing data, but what's the "best practice" for Ruby on Rails to ship this data to the live database also upon db creation?
ultimately this is a two part question I suppose.
1) What's the best way to load test data into my database for development, this will be roughly 1,000 items. Is it through a migration or through fixtures? The reason this is a different answer than the question below is that in development, there's certain fields in the tables that I'd like to make random. In production, these fields would all start with the same value of 0.
2) What's the best way to bootstrap a production db with live data I need in it, is this also through a migration or fixture?
I think the answer is to seed as described here: http://lptf.blogspot.com/2009/09/seed-data-in-rails-234.html but I need a way to seed for development and seed for production. Also, why bother using Fixtures if seeding is available? When does one seed and when does one use fixtures?
Usually fixtures are used to provide your tests with data, not to populate data into your database. You can - and some people have, like the links you point to - use fixtures for this purpose.
Fixtures are OK, but using Ruby gives us some advantages: for example, being able to read from a CSV file and populate records based on that data set. Or reading from a YAML fixture file if you really want to: since your starting with a programming language your options are wide open from there.
My current team tried to use db/seed.rb, and checking RAILS_ENV to load only certain data in certain places.
The annoying thing about db:seed is that it's meant to be a one shot thing: so if you have additional items to add in the middle of development - or when your app has hit production - ... well, you need to take that into consideration (ActiveRecord's find_or_create_by...() method might be your friend here).
We tried the Bootstrapper plugin, which puts a nice DSL over the RAILS_ENV checking, and lets your run only the environment you want. It's pretty nice.
Our needs actually went beyond that - we found we needed database style migrations for our seed data. Right now we are putting normal Ruby scripts into a folder (db/bootstrapdata/) and running these scripts with Arild Shirazi's required gem to load (and thus run) the scripts in this directory.
Now this only gives you part of the database style migrations. It's not hard to go from this to creating something where these data migrations can only be run once (like database migrations).
Your needs might stop at bootstrapper: we have pretty unique needs (developing the system when we only know half the spec, larg-ish Rails team, big data migration from the previous generation of software. Your needs might be simpler).
If you did want to use fixtures the advantage over seed is that you can easily export also.
A quick guess at how the rake task may looks is as follows
desc 'Export the data objects to Fixtures from data in an existing
database. Defaults to development database. Set RAILS_ENV to override.'
task :export => :environment do
sql = "SELECT * FROM %s"
skip_tables = ["schema_info"]
export_tables = [
"roles",
"roles_users",
"roles_utilities",
"user_filters",
"users",
"utilities"
]
time_now = Time.now.strftime("%Y_%h_%d_%H%M")
folder = "#{RAILS_ROOT}/db/fixtures/#{time_now}/"
FileUtils.mkdir_p folder
puts "Exporting data to #{folder}"
ActiveRecord::Base.establish_connection(:development)
export_tables.each do |table_name|
i = "000"
File.open("#{folder}/#{table_name}.yml", 'w') do |file|
data = ActiveRecord::Base.connection.select_all(sql % table_name)
file.write data.inject({}) { |hash, record|
hash["#{table_name}_#{i.succ!}"] = record
hash }.to_yaml
end
end
end
desc "Import the models that have YAML files in
db/fixture/defaults or from a specified path."
task :import do
location = 'db/fixtures/default'
puts ""
puts "enter import path [#{location}]"
location_in = STDIN.gets.chomp
location = location_in unless location_in.blank?
ENV['FIXTURES_PATH'] = location
puts "Importing data from #{ENV['FIXTURES_PATH']}"
Rake::Task["db:fixtures:load"].invoke
end
We have a ton of non-user data: 500 product types that haven't changed in 20 years, 200GB of geospatial data that never changes (Queens is always 40.73N/73.82W)... etc. It's the same in Development and Production. It should be the same in Test, but the during testing Rails empties all of the test tables, and it takes a ton of time to re-populate during testing.
What is the Rails way to partition this non-user data so that it doesn't have to be repopulated in Test?
The documentation for this is found in the Fixtures class. (Search for "Transactional fixtures" on that page.)
The example they give starts out like this:
class FooTest < ActiveSupport::TestCase
self.use_transactional_fixtures = true
self.use_instantiated_fixtures = false
...
One of the projects I work on uses a test database with zero fixtures, so we just define this globally in test_helper.rb.
class ActiveSupport::TestCase
self.use_transactional_fixtures = true
self.use_instantiated_fixtures = false
end
jdl shows you the settings to use for enabling and disabling transactional_fixtures, you should be able to set:
# Use self in ActiveSupport::TestCase if you don't have a config block
# in test/test_helper.rb
#
config.use_transactional_fixtures = false
And stop Rails from trying to load fixtures before each run of your tests. The downside is you can't assume all your fixtures are loaded into the DB.
Real Answer
You have too much data in your fixtures. The Railsy thing to do it load only the necessary data in test fixtures; You do not need 200G of geospatial data (what freaking dataset is that anyway? that sounds way too big), and you probably don't need all 500 products.
Tests are for your code, so only include the few geospatial points you need for a test, or only include a few products with unique properties. Keep the DB light enough to be loaded quickly.
Your test fixtures should be separate from you application bootstrapping data, take advantage of that.
Real Real Answer
Don't touch the database in your tests (or, touch it very little). The database is slow and fixtures are difficult or impossible to maintain well. Instead, try using a stubbing framework like Mocha or flexmock. It's faster, and makes your tests read in a clearer manner. Tests are for code, you can stub the database out of the situation and trust that ActiveRecord works (because...it's tested too! :-).
If you do choose to stick with fixtures, I recommend using factory_girl instead of the built in Rails fixtures. You'll have a much better starting point.