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.
Related
I'm working on an existing app with a test suite based on vanilla Rails fixtures and MiniTest. Switching to FactoryGirl or the like is not an option.
I'd like to find a relatively complex open source Rails app to learn more about best practices with using fixtures. Any suggestions?
Take a look at https://github.com/Shopify/active_merchant, it also uses some fixtures
I've discovered Faker for myself, what is important:
It creates unique data every time while seeding database.
In some cases it does matter and better than same data. So, it is suitable for fixtures only;-)
It has handy templates for most cases e.g. phone.
You can check example in GitLab repo.
I want to create fake usage of my app, as a tutorial.
In order to do so, I need to create fake data (with the same structure and association in real data) to send to my templates, so it renders the same view when my users will have when using the app.
But unfortunately, I didn't find an easy way to do that, except hard coding the examples (fake usage) as a separate view, that looks like the generated view with true data. But this is not useful when you have to change the template, one day or another.
And, mixing true data with fake ones in the database (and then retrieving only fake data when needed) doesn't seem to be a good idea.
Do you have an idea or a gem to suggest?
One option to consider is to use a factory gem (such as factory_girl) or similar (I personally like machinist) and then create some form of script that initializes objects in the test environment.
This may not be the intended or ideal use for a test environment, but you'd be able to utilize your app in a non-production environment with fake data, and allows you to keep data separate from real and/or development data.
The only "gotcha" I can think of is that you'll want to ensure that any automatic testing gem (such as rspec) drops the test database before your tests run. If you don't, you could see errors in your tests due to data already existing in the database.
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.
When developing a Rails app with a legacy schema that is in-use by an existing application, if tables have NOT NULL constraints on foreign id columns throughout the schema, in order to create/save models for tests, models need to exist for those associations, and their associations, etc. So, it isn't an easy as just creating one model at a time as you need it and testing with it.
As far as testing goes, this seems to be a problem if you are using FactoryGirl and want to create and save model instances to return from controllers, etc. when all of the association dependencies are involved. Another option is to mock, but mocking can be a little more time consuming and it doesn't allow you to do integration testing as easily. Another is to use fixtures, but those are time consuming and brittle. Another is to pre-populate the test database with production data, but that doesn't solve the need for factories, etc./known data to expect in tests, and Rails usually expects to start with a clean DB for the test environment.
What strategies for developing models, tests, etc. do you use when you have an existing complex schema that you are bolting a Rails app onto- not just for reading data, but also writing to the existing schema that is in use by an existing production application? (i.e. the "rebuild the ship while at sea" problem)
When we first started out on this problem, I was looking for something that could autogenerate models from the existing schema. I found Dr. Nic's magic model generator, but it only stated that worked in Rails 2.x. I got a Rails 2.x environment running (forget the specific version it worked in) but it didn't seem to help much, so I wrote a script to generate our models. However, when we started development we then had a load of models, so we started to try to move out the ones we didn't need, then needed to comment out associations to models that were no longer there, but some of those were required/NOT NULL foreign keys, so we're now having to move them back in and uncomment those more than we thought we would.
We did write and uncover some things that were helpful during the process, not all of which we've used, but they might be helpful to others:
https://github.com/influitive/apartment
https://github.com/karledurante/secondbase
https://github.com/drnic/composite_primary_keys
https://github.com/garysweaver/activerecord-define_nils
https://github.com/garysweaver/activerecord-native_db_types_override
https://github.com/garysweaver/modelist
https://github.com/garysweaver/stepford
https://github.com/garysweaver/structure_sql_to_migration
As for test data setup, I started writing a tool to automate the development of FactoryGirl factories called Stepford and wrote Modelist to help us test models, resolve circular dependencies, and identify model dependencies, so we don't have to include all automatically generated models.
So far really, the only answer I've come up with and have heard other say also is that rebuilding an existing application, even piecemeal, with different technologies is difficult, slow, and error-prone.
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.