What's a good way to handle data across Prod, Dev, Test DB's in Rails 3 (using Cucumber)? - ruby-on-rails

I have a small Rails 3 app (you have a listing with photos, and prices), and am trying to get into Cucumber BDD testing.
I have 2 types of Database data:
1)
There's consistent data (like a table of price ranges) that needs to be the same across my Prod, Dev, and Test servers.
2)
Then there's the other data that can change from each environment (like usernames, listing data etc). I just need to make sure I have a good spread of data in my dev and test servers that matches data that should / would be in prod.
I have 2 questions.
First:
What's the best way to handle data like this? How can I ensure consistency across the different environments in a painless way?
Second:
I'm using fixtures to populate my dev db. I'm having a hard time populating my test DB. What's the best way to populate the test DB (while using Cucumber) so I can run through my scenarios?

as suggested, db/seeds can be used for some use cases, you can also checkout this solution: http://jedschneider.posterous.com/using-semi-static-data-as-an-activerecord-mod that may address other use cases.
In regards to cucumber, the true cucumber philosophy would be to create a resource through the web interface, eg to create a user: go to user sign in, register, sign in as that user. They discourage direct model access (page 292 ish), but it is too convenient to not do, in my opinion, as long as the web interface workflow is also tested.
For this, I prefer using factories over fixtures as they are less fragile in on-going development. I would recommend factory_girl or factory_girl_rails for Rails 3. Thus you can have a step definition:
/Given a valid user exists?/ do
#user = Factory(:user)
end
which populates the user table with a user an creates an instance variable that you can use to follow through the scenario with. If you want to use fixtures with cucumber, setup a before hook that will load your fixtures for you.

https://github.com/rails/rails/commit/4932f7b38f72104819022abca0c952ba6f9888cb
The idea behind db/seeds.rb is for that kind of data that is pretty much static and needs to be universal. Anything in that file will be pulled in during db:setup, and can be added manually with rake db:seed
second question should be straight forward, rake db:fixtures:load should not be dependant on enviornment. So you should be able to do something like RAILS_ENV=test rake db:fixtures:load and that should load up your test database with your fixture data.

Related

How best to create table on initialization?

Happy New Year everyone.
In my Rails 4 application I have a table plans containing the records for the plans that a user can subscribe to.
It is absolutely paramount for the app that this table is populated at any time, in development, test, and production mode. Otherwise the app will not work.
What is the best way to create those records?
Should I put a create method into an initializer? Or set up a rake task and run it manually whenever I restart the server (sounds a bit cumbersome, though)?
Thanks for any help in this matter.
Rails has a 'seeds' feature that should be used for seeding a database with initial data.
It's a really simple feature: just fill up db/seeds.rb with some Ruby code, and run rake db:seed
source: http://edgeguides.rubyonrails.org/active_record_migrations.html#migrations-and-seed-data
If you want to use data in your test environment, you might also be interested in using fixtures for your plans. Take a look at http://guides.rubyonrails.org/testing.html#the-low-down-on-fixtures

What's wrong with Rspec, FactoryGirl and real sample data?

I've been leaning some of RoR, and when I got to TDD, stuff started to get more complicated. At some point of my App, I thought it would be better to run my tests over the real data.
Real Data vs Sample Data
Searching the web, I found that tests were not meant to run over real data, but over sample data. But yet I couldn't agree with that.
Let's supose my app had an Alias System. So when you access a random url it figures out what that fragment wants and redirects to the proper canonical url. And let's add that an alias dictionary is stored in some models. How would we test agains that dictionary? Hard code spec files for every alias/keyword?
Sticking with real data
The first two things I've realized, yet very unsurely, is:
Rspec testing environment wouldn't access development model's data.
FactoryGirl rules over my testing database, so it's not my option to populate it.
The best solution I could figure out, as the complete newbie I am, is that I could create some classes in spec/support folder and call them inside my factories so as to get that real data. Those classes have a short sample of my real database info, nested, and so my test can go 'real'.
What can pros around suggest to improve it?
I think you may want to look into building a seeds.rb file to populate your databases. This is usually used to initialize the development database so it can be used in your app (and queried in the rails console), but you can use it to seed your test database as described in this answer.
You certainly should not use your development database for testing. You can either seed the test database, or create factories that reflect various scenarios.
FactoryGirl rules over my testing database, so it's not my option to populate it.
You can use more than one factory to represent a business entity, depending on the scenario under test. FactoryGirl makes this easy by allowing you to nest factories. You can define a factory with a basic set of valid attributes and use that in unit tests. For integration (feature) tests, you can use a nested factory that expands on the basic attributes to implement a particular scenario. You can have as many variations of these implementation-specific factories as you need.

What are best practices to handle database data in 'test' mode?

I am using Ruby on Rails 3.2.2, cucumber-rails-1.3.0, rspec-rails-2.8.1 and capybara-1.1.2. I have this problem but I started thinking that maybe I'm doing something wrong... mostly about seeding data in the test database for testing purposes. Specifically, my issue is related to how to properly manage data in the test database when I have to test my application.
My doubt is: By seeding data (For Your Information: I use the ROOT_PATH/db/seed.rb file to inject that data) in the test database I'm doing things as they should be done? That is, how should I populate the test database since the data in that database* is required in order to make to properly work my application for testing purposes? Should I populate the test database at all?
In other words, what are best practices to handle database data in test mode (in my case)? And, generally speaking, how the situation should be handled?
***** For example, in order to work my application requires at least data related to an "anonymous" user, to "basic" articles, to "basic" article categories, etc.
You should use one of the following:
Fixtures. See corresponding Rails documentation
Factories. The most popular tool to created/manage factories is FactoryGirl. IMHO that's the best solution.
Make sure data is seeded into test database. See this StackOverflow question.
I had a similar problem, association made it necessary to have a bit of seed data:
Factories will make your tests really slow, they are perfectly OK for single objects, but not for a lot of seed data that has to be created for each test
Fixture Builder - http://github.com/rdy/fixture_builder
I created a bunch of fixtures and just load them from the DB for each test, cut my test time down by 40%. You can also load the seeds file instead.
But be careful, deleting or updating records will create unwanted side effects. Use factories for those specs.
Mock and Stub everything so that your tests rarely touch the DB.
This has become very unpopular, you will eventually get passing specs that don't pick up on your actual errors.

factory_girl vs fixtures for development data (Rails)

I like the factory_girl approach in tests, but one thing I'm a little unclear on is what to do about development data.
Usually with fixtures we had some dummy users, models etc in development. Then in tests we can create more on the fly or reference the existing ones but every developer had the same data in dev.
What's the common way to create development data with factory_girl? I saw rake db:seed but this looks like it's intended to be used in production also, so not quite the same thing.
I generally create fake data using Factories inside seeds.rb.
I just prepend the code with if Rails.env.development?

RSpec setup for an application that depends on an external database from another application

I've had to add features to an application that depends on a database from another application. I've been able to set up a connection to this external database and pull data from it. However, I'm not sure how to get my main application to create a test database for this external application.
It would be awesome if there some way to pull in the schema for this database and create it in the same manner that 'rake db:test:prepare' does. Is there any configuration capabilities for RSpec to do this, or will I have to roll my own task?
I am not aware of any simple way to do this.
You could have a sql schema prepared and load it in your test database trough a custom rake task
But if it is for testing, it might be a good idea for you to look into Factories
For example Factory girl
"factory_girl is a fixtures replacement with a straightforward definition syntax, support for multiple build strategies (saved instances, unsaved instances, attribute hashes, and stubbed objects), and support for multiple factories for the same class (user, admin_user, and so on), including factory inheritance."
And a screencast
Is this a Rails app? If so, the db:test:prepare task and the related tasks will still work, even if you are using RSpec.
I ended up just running rake db:test:prepare for the external application and update the database configs of the application I'm developing to include the test DB for the external application. I'd like to automate the rake db:test:prepare for the external app, however I don't see myself updating its schema that often.

Resources